gnunet-service-conversation.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file conversation/gnunet-service-conversation.c
  19. * @brief conversation service implementation
  20. * @author Simon Dieterle
  21. * @author Andreas Fuchs
  22. * @author Christian Grothoff
  23. */
  24. #include "platform.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_protocols.h"
  27. #include "gnunet_applications.h"
  28. #include "gnunet_constants.h"
  29. #include "gnunet_signatures.h"
  30. #include "gnunet_cadet_service.h"
  31. #include "gnunet_conversation_service.h"
  32. #include "conversation.h"
  33. /**
  34. * How long is our signature on a call valid? Needs to be long enough for time zone
  35. * differences and network latency to not matter. No strong need for it to be short,
  36. * but we simply like all signatures to eventually expire.
  37. */
  38. #define RING_TIMEOUT GNUNET_TIME_UNIT_DAYS
  39. /**
  40. * A line connects a local client with a cadet channel (or, if it is an
  41. * open line, is waiting for a cadet channel).
  42. */
  43. struct Line;
  44. /**
  45. * The possible connection status
  46. */
  47. enum ChannelStatus
  48. {
  49. /**
  50. * Our phone is ringing, waiting for the client to pick up.
  51. */
  52. CS_CALLEE_RINGING,
  53. /**
  54. * We are talking!
  55. */
  56. CS_CALLEE_CONNECTED,
  57. /**
  58. * We're in shutdown, sending hangup messages before cleaning up.
  59. */
  60. CS_CALLEE_SHUTDOWN,
  61. /**
  62. * We are waiting for the phone to be picked up.
  63. */
  64. CS_CALLER_CALLING,
  65. /**
  66. * We are talking!
  67. */
  68. CS_CALLER_CONNECTED,
  69. /**
  70. * We're in shutdown, sending hangup messages before cleaning up.
  71. */
  72. CS_CALLER_SHUTDOWN
  73. };
  74. /**
  75. * A `struct Channel` represents a cadet channel, which is a P2P
  76. * connection to another conversation service. Multiple channels can
  77. * be attached the the same `struct Line`, which represents a local
  78. * client. We keep them in a linked list.
  79. */
  80. struct Channel
  81. {
  82. /**
  83. * This is a DLL.
  84. */
  85. struct Channel *next;
  86. /**
  87. * This is a DLL.
  88. */
  89. struct Channel *prev;
  90. /**
  91. * Line associated with the channel.
  92. */
  93. struct Line *line;
  94. /**
  95. * Handle for the reliable channel (contol data)
  96. */
  97. struct GNUNET_CADET_Channel *channel_reliable;
  98. /**
  99. * Handle for unreliable channel (audio data)
  100. */
  101. struct GNUNET_CADET_Channel *channel_unreliable;
  102. /**
  103. * Transmit handle for pending audio messages
  104. */
  105. struct GNUNET_CADET_TransmitHandle *unreliable_mth;
  106. /**
  107. * Message queue for control messages
  108. */
  109. struct GNUNET_MQ_Handle *reliable_mq;
  110. /**
  111. * Target of the line, if we are the caller.
  112. */
  113. struct GNUNET_PeerIdentity target;
  114. /**
  115. * Temporary buffer for audio data.
  116. */
  117. void *audio_data;
  118. /**
  119. * Number of bytes in @e audio_data.
  120. */
  121. size_t audio_size;
  122. /**
  123. * Channel identifier.
  124. */
  125. uint32_t cid;
  126. /**
  127. * Remote line number.
  128. */
  129. uint32_t remote_line;
  130. /**
  131. * Current status of this line.
  132. */
  133. enum ChannelStatus status;
  134. /**
  135. * #GNUNET_YES if the channel was suspended by the other peer.
  136. */
  137. int8_t suspended_remote;
  138. /**
  139. * #GNUNET_YES if the channel was suspended by the local client.
  140. */
  141. int8_t suspended_local;
  142. };
  143. /**
  144. * A `struct Line` connects a local client with cadet channels.
  145. */
  146. struct Line
  147. {
  148. /**
  149. * Kept in a DLL.
  150. */
  151. struct Line *next;
  152. /**
  153. * Kept in a DLL.
  154. */
  155. struct Line *prev;
  156. /**
  157. * This is a DLL.
  158. */
  159. struct Channel *channel_head;
  160. /**
  161. * This is a DLL.
  162. */
  163. struct Channel *channel_tail;
  164. /**
  165. * Handle to the line client.
  166. */
  167. struct GNUNET_SERVER_Client *client;
  168. /**
  169. * Generator for channel IDs.
  170. */
  171. uint32_t cid_gen;
  172. /**
  173. * Our line number.
  174. */
  175. uint32_t local_line;
  176. };
  177. /**
  178. * Our configuration.
  179. */
  180. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  181. /**
  182. * Notification context containing all connected clients.
  183. */
  184. static struct GNUNET_SERVER_NotificationContext *nc;
  185. /**
  186. * Handle for cadet
  187. */
  188. static struct GNUNET_CADET_Handle *cadet;
  189. /**
  190. * Identity of this peer.
  191. */
  192. static struct GNUNET_PeerIdentity my_identity;
  193. /**
  194. * Head of DLL of active lines.
  195. */
  196. static struct Line *lines_head;
  197. /**
  198. * Tail of DLL of active lines.
  199. */
  200. static struct Line *lines_tail;
  201. /**
  202. * Counter for generating local line numbers.
  203. * FIXME: randomize generation in the future
  204. * to eliminate information leakage.
  205. */
  206. static uint32_t local_line_cnt;
  207. /**
  208. * Function to register a phone.
  209. *
  210. * @param cls closure, NULL
  211. * @param client the client from which the message is
  212. * @param message the message from the client
  213. */
  214. static void
  215. handle_client_register_message (void *cls,
  216. struct GNUNET_SERVER_Client *client,
  217. const struct GNUNET_MessageHeader *message)
  218. {
  219. const struct ClientPhoneRegisterMessage *msg;
  220. struct Line *line;
  221. msg = (const struct ClientPhoneRegisterMessage *) message;
  222. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  223. if (NULL != line)
  224. {
  225. GNUNET_break (0);
  226. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  227. return;
  228. }
  229. line = GNUNET_new (struct Line);
  230. line->client = client;
  231. GNUNET_SERVER_notification_context_add (nc, client);
  232. GNUNET_SERVER_client_set_user_context (client, line);
  233. GNUNET_CONTAINER_DLL_insert (lines_head,
  234. lines_tail,
  235. line);
  236. line->local_line = ntohl (msg->line) & (~ (1 << 31));
  237. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  238. }
  239. /**
  240. * Function to handle a pickup request message from the client
  241. *
  242. * @param cls closure, NULL
  243. * @param client the client from which the message is
  244. * @param message the message from the client
  245. */
  246. static void
  247. handle_client_pickup_message (void *cls,
  248. struct GNUNET_SERVER_Client *client,
  249. const struct GNUNET_MessageHeader *message)
  250. {
  251. const struct ClientPhonePickupMessage *msg;
  252. struct GNUNET_MQ_Envelope *e;
  253. struct CadetPhonePickupMessage *mppm;
  254. struct Line *line;
  255. struct Channel *ch;
  256. msg = (const struct ClientPhonePickupMessage *) message;
  257. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  258. if (NULL == line)
  259. {
  260. GNUNET_break (0);
  261. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  262. return;
  263. }
  264. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  265. if (msg->cid == ch->cid)
  266. break;
  267. if (NULL == ch)
  268. {
  269. /* could have been destroyed asynchronously, ignore message */
  270. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  271. "Channel %u not found\n",
  272. msg->cid);
  273. GNUNET_SERVER_receive_done (client, GNUNET_YES);
  274. return;
  275. }
  276. switch (ch->status)
  277. {
  278. case CS_CALLEE_RINGING:
  279. ch->status = CS_CALLEE_CONNECTED;
  280. break;
  281. case CS_CALLEE_CONNECTED:
  282. GNUNET_break (0);
  283. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  284. return;
  285. case CS_CALLEE_SHUTDOWN:
  286. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  287. "Ignoring client's PICKUP message, line is in SHUTDOWN\n");
  288. break;
  289. case CS_CALLER_CALLING:
  290. case CS_CALLER_CONNECTED:
  291. case CS_CALLER_SHUTDOWN:
  292. GNUNET_break (0);
  293. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  294. return;
  295. }
  296. GNUNET_break (CS_CALLEE_CONNECTED == ch->status);
  297. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  298. "Sending PICK_UP message to cadet\n");
  299. e = GNUNET_MQ_msg (mppm,
  300. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP);
  301. GNUNET_MQ_send (ch->reliable_mq, e);
  302. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  303. }
  304. /**
  305. * Destroy a channel.
  306. *
  307. * @param ch channel to destroy.
  308. */
  309. static void
  310. destroy_line_cadet_channels (struct Channel *ch)
  311. {
  312. struct Line *line = ch->line;
  313. struct GNUNET_CADET_Channel *t;
  314. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  315. "Destroying cadet channels\n");
  316. if (NULL != ch->reliable_mq)
  317. {
  318. GNUNET_MQ_destroy (ch->reliable_mq);
  319. ch->reliable_mq = NULL;
  320. }
  321. if (NULL != ch->unreliable_mth)
  322. {
  323. GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
  324. ch->unreliable_mth = NULL;
  325. }
  326. if (NULL != (t = ch->channel_unreliable))
  327. {
  328. ch->channel_unreliable = NULL;
  329. GNUNET_CADET_channel_destroy (t);
  330. }
  331. if (NULL != (t = ch->channel_reliable))
  332. {
  333. ch->channel_reliable = NULL;
  334. GNUNET_CADET_channel_destroy (t);
  335. }
  336. GNUNET_CONTAINER_DLL_remove (line->channel_head,
  337. line->channel_tail,
  338. ch);
  339. GNUNET_free_non_null (ch->audio_data);
  340. GNUNET_free (ch);
  341. }
  342. /**
  343. * We are done signalling shutdown to the other peer. Close down
  344. * the channel.
  345. *
  346. * @param cls the `struct Channel` to reset/terminate
  347. */
  348. static void
  349. mq_done_finish_caller_shutdown (void *cls)
  350. {
  351. struct Channel *ch = cls;
  352. switch (ch->status)
  353. {
  354. case CS_CALLEE_RINGING:
  355. GNUNET_break (0);
  356. break;
  357. case CS_CALLEE_CONNECTED:
  358. GNUNET_break (0);
  359. break;
  360. case CS_CALLEE_SHUTDOWN:
  361. destroy_line_cadet_channels (ch);
  362. break;
  363. case CS_CALLER_CALLING:
  364. GNUNET_break (0);
  365. break;
  366. case CS_CALLER_CONNECTED:
  367. GNUNET_break (0);
  368. break;
  369. case CS_CALLER_SHUTDOWN:
  370. destroy_line_cadet_channels (ch);
  371. break;
  372. }
  373. }
  374. /**
  375. * Function to handle a hangup request message from the client
  376. *
  377. * @param cls closure, NULL
  378. * @param client the client from which the message is
  379. * @param message the message from the client
  380. */
  381. static void
  382. handle_client_hangup_message (void *cls,
  383. struct GNUNET_SERVER_Client *client,
  384. const struct GNUNET_MessageHeader *message)
  385. {
  386. const struct ClientPhoneHangupMessage *msg;
  387. struct GNUNET_MQ_Envelope *e;
  388. struct CadetPhoneHangupMessage *mhum;
  389. struct Line *line;
  390. struct Channel *ch;
  391. msg = (const struct ClientPhoneHangupMessage *) message;
  392. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  393. if (NULL == line)
  394. {
  395. GNUNET_break (0);
  396. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  397. return;
  398. }
  399. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  400. if (msg->cid == ch->cid)
  401. break;
  402. if (NULL == ch)
  403. {
  404. /* could have been destroyed asynchronously, ignore message */
  405. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  406. "Channel %u not found\n",
  407. msg->cid);
  408. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  409. return;
  410. }
  411. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  412. "Received HANGUP for channel %u which is in state %d\n",
  413. msg->cid,
  414. ch->status);
  415. switch (ch->status)
  416. {
  417. case CS_CALLEE_RINGING:
  418. ch->status = CS_CALLEE_SHUTDOWN;
  419. break;
  420. case CS_CALLEE_CONNECTED:
  421. ch->status = CS_CALLEE_SHUTDOWN;
  422. break;
  423. case CS_CALLEE_SHUTDOWN:
  424. /* maybe the other peer closed asynchronously... */
  425. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  426. return;
  427. case CS_CALLER_CALLING:
  428. ch->status = CS_CALLER_SHUTDOWN;
  429. break;
  430. case CS_CALLER_CONNECTED:
  431. ch->status = CS_CALLER_SHUTDOWN;
  432. break;
  433. case CS_CALLER_SHUTDOWN:
  434. /* maybe the other peer closed asynchronously... */
  435. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  436. return;
  437. }
  438. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  439. "Sending HANG_UP message via cadet\n");
  440. e = GNUNET_MQ_msg (mhum,
  441. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
  442. GNUNET_MQ_notify_sent (e,
  443. &mq_done_finish_caller_shutdown,
  444. ch);
  445. GNUNET_MQ_send (ch->reliable_mq, e);
  446. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  447. }
  448. /**
  449. * Function to handle a suspend request message from the client
  450. *
  451. * @param cls closure, NULL
  452. * @param client the client from which the message is
  453. * @param message the message from the client
  454. */
  455. static void
  456. handle_client_suspend_message (void *cls,
  457. struct GNUNET_SERVER_Client *client,
  458. const struct GNUNET_MessageHeader *message)
  459. {
  460. const struct ClientPhoneSuspendMessage *msg;
  461. struct GNUNET_MQ_Envelope *e;
  462. struct CadetPhoneSuspendMessage *mhum;
  463. struct Line *line;
  464. struct Channel *ch;
  465. msg = (const struct ClientPhoneSuspendMessage *) message;
  466. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  467. if (NULL == line)
  468. {
  469. GNUNET_break (0);
  470. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  471. return;
  472. }
  473. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  474. if (msg->cid == ch->cid)
  475. break;
  476. if (NULL == ch)
  477. {
  478. /* could have been destroyed asynchronously, ignore message */
  479. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  480. "Channel %u not found\n",
  481. msg->cid);
  482. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  483. return;
  484. }
  485. if (GNUNET_YES == ch->suspended_local)
  486. {
  487. GNUNET_break (0);
  488. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  489. return;
  490. }
  491. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  492. "Received SUSPEND for channel %u which is in state %d\n",
  493. msg->cid,
  494. ch->status);
  495. switch (ch->status)
  496. {
  497. case CS_CALLEE_RINGING:
  498. GNUNET_break (0);
  499. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  500. return;
  501. case CS_CALLEE_CONNECTED:
  502. ch->suspended_local = GNUNET_YES;
  503. break;
  504. case CS_CALLEE_SHUTDOWN:
  505. /* maybe the other peer closed asynchronously... */
  506. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  507. return;
  508. case CS_CALLER_CALLING:
  509. GNUNET_break (0);
  510. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  511. return;
  512. case CS_CALLER_CONNECTED:
  513. ch->suspended_local = GNUNET_YES;
  514. break;
  515. case CS_CALLER_SHUTDOWN:
  516. /* maybe the other peer closed asynchronously... */
  517. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  518. return;
  519. }
  520. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  521. "Sending SUSPEND message via cadet\n");
  522. e = GNUNET_MQ_msg (mhum,
  523. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND);
  524. GNUNET_MQ_send (ch->reliable_mq, e);
  525. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  526. }
  527. /**
  528. * Function to handle a resume request message from the client
  529. *
  530. * @param cls closure, NULL
  531. * @param client the client from which the message is
  532. * @param message the message from the client
  533. */
  534. static void
  535. handle_client_resume_message (void *cls,
  536. struct GNUNET_SERVER_Client *client,
  537. const struct GNUNET_MessageHeader *message)
  538. {
  539. const struct ClientPhoneResumeMessage *msg;
  540. struct GNUNET_MQ_Envelope *e;
  541. struct CadetPhoneResumeMessage *mhum;
  542. struct Line *line;
  543. struct Channel *ch;
  544. msg = (const struct ClientPhoneResumeMessage *) message;
  545. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  546. if (NULL == line)
  547. {
  548. GNUNET_break (0);
  549. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  550. return;
  551. }
  552. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  553. if (msg->cid == ch->cid)
  554. break;
  555. if (NULL == ch)
  556. {
  557. /* could have been destroyed asynchronously, ignore message */
  558. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  559. "Channel %u not found\n",
  560. msg->cid);
  561. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  562. return;
  563. }
  564. if (GNUNET_YES != ch->suspended_local)
  565. {
  566. GNUNET_break (0);
  567. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  568. return;
  569. }
  570. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  571. "Received RESUME for channel %u which is in state %d\n",
  572. msg->cid,
  573. ch->status);
  574. switch (ch->status)
  575. {
  576. case CS_CALLEE_RINGING:
  577. GNUNET_break (0);
  578. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  579. return;
  580. case CS_CALLEE_CONNECTED:
  581. ch->suspended_local = GNUNET_NO;
  582. break;
  583. case CS_CALLEE_SHUTDOWN:
  584. /* maybe the other peer closed asynchronously... */
  585. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  586. return;
  587. case CS_CALLER_CALLING:
  588. GNUNET_break (0);
  589. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  590. return;
  591. case CS_CALLER_CONNECTED:
  592. ch->suspended_local = GNUNET_NO;
  593. break;
  594. case CS_CALLER_SHUTDOWN:
  595. /* maybe the other peer closed asynchronously... */
  596. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  597. return;
  598. }
  599. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  600. "Sending RESUME message via cadet\n");
  601. e = GNUNET_MQ_msg (mhum,
  602. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME);
  603. GNUNET_MQ_send (ch->reliable_mq, e);
  604. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  605. }
  606. /**
  607. * Function to handle call request from the client
  608. *
  609. * @param cls closure, NULL
  610. * @param client the client from which the message is
  611. * @param message the message from the client
  612. */
  613. static void
  614. handle_client_call_message (void *cls,
  615. struct GNUNET_SERVER_Client *client,
  616. const struct GNUNET_MessageHeader *message)
  617. {
  618. const struct ClientCallMessage *msg;
  619. struct Line *line;
  620. struct Channel *ch;
  621. struct GNUNET_MQ_Envelope *e;
  622. struct CadetPhoneRingMessage *ring;
  623. msg = (const struct ClientCallMessage *) message;
  624. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  625. if (NULL != line)
  626. {
  627. GNUNET_break (0);
  628. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  629. return;
  630. }
  631. line = GNUNET_new (struct Line);
  632. line->client = client;
  633. line->local_line = (local_line_cnt++) | (1 << 31);
  634. GNUNET_SERVER_client_set_user_context (client, line);
  635. GNUNET_SERVER_notification_context_add (nc, client);
  636. GNUNET_CONTAINER_DLL_insert (lines_head,
  637. lines_tail,
  638. line);
  639. ch = GNUNET_new (struct Channel);
  640. ch->line = line;
  641. GNUNET_CONTAINER_DLL_insert (line->channel_head,
  642. line->channel_tail,
  643. ch);
  644. ch->target = msg->target;
  645. ch->remote_line = ntohl (msg->line);
  646. ch->status = CS_CALLER_CALLING;
  647. ch->channel_reliable = GNUNET_CADET_channel_create (cadet,
  648. ch,
  649. &msg->target,
  650. GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
  651. GNUNET_CADET_OPTION_RELIABLE);
  652. ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable);
  653. e = GNUNET_MQ_msg (ring, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING);
  654. ring->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING);
  655. ring->purpose.size = htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
  656. sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  657. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
  658. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
  659. GNUNET_CRYPTO_ecdsa_key_get_public (&msg->caller_id,
  660. &ring->caller_id);
  661. ring->remote_line = msg->line;
  662. ring->source_line = htonl (line->local_line);
  663. ring->target = msg->target;
  664. ring->source = my_identity;
  665. ring->expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (RING_TIMEOUT));
  666. GNUNET_assert (GNUNET_OK ==
  667. GNUNET_CRYPTO_ecdsa_sign (&msg->caller_id,
  668. &ring->purpose,
  669. &ring->signature));
  670. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  671. "Sending RING message via cadet\n");
  672. GNUNET_MQ_send (ch->reliable_mq, e);
  673. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  674. }
  675. /**
  676. * Transmit audio data via unreliable cadet channel.
  677. *
  678. * @param cls the `struct Channel` we are transmitting for
  679. * @param size number of bytes available in @a buf
  680. * @param buf where to copy the data
  681. * @return number of bytes copied to @a buf
  682. */
  683. static size_t
  684. transmit_line_audio (void *cls,
  685. size_t size,
  686. void *buf)
  687. {
  688. struct Channel *ch = cls;
  689. struct CadetAudioMessage *mam = buf;
  690. ch->unreliable_mth = NULL;
  691. if ( (NULL == buf) ||
  692. (size < sizeof (struct CadetAudioMessage) + ch->audio_size) )
  693. {
  694. /* eh, other error handling? */
  695. return 0;
  696. }
  697. mam->header.size = htons (sizeof (struct CadetAudioMessage) + ch->audio_size);
  698. mam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO);
  699. mam->remote_line = htonl (ch->remote_line);
  700. mam->source_line = htonl (ch->line->local_line);
  701. memcpy (&mam[1], ch->audio_data, ch->audio_size);
  702. GNUNET_free (ch->audio_data);
  703. ch->audio_data = NULL;
  704. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  705. "Sending %u bytes of audio data from line %u to remote line %u via cadet\n",
  706. ch->audio_size, ch->line->local_line, ch->remote_line);
  707. return sizeof (struct CadetAudioMessage) + ch->audio_size;
  708. }
  709. /**
  710. * Function to handle audio data from the client
  711. *
  712. * @param cls closure, NULL
  713. * @param client the client from which the message is
  714. * @param message the message from the client
  715. */
  716. static void
  717. handle_client_audio_message (void *cls,
  718. struct GNUNET_SERVER_Client *client,
  719. const struct GNUNET_MessageHeader *message)
  720. {
  721. const struct ClientAudioMessage *msg;
  722. struct Line *line;
  723. struct Channel *ch;
  724. size_t size;
  725. size = ntohs (message->size) - sizeof (struct ClientAudioMessage);
  726. msg = (const struct ClientAudioMessage *) message;
  727. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  728. if (NULL == line)
  729. {
  730. GNUNET_break (0);
  731. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  732. return;
  733. }
  734. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  735. if (msg->cid == ch->cid)
  736. break;
  737. if (NULL == ch)
  738. {
  739. /* could have been destroyed asynchronously, ignore message */
  740. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  741. "Channel %u not found\n",
  742. msg->cid);
  743. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  744. return;
  745. }
  746. switch (ch->status)
  747. {
  748. case CS_CALLEE_RINGING:
  749. case CS_CALLER_CALLING:
  750. GNUNET_break (0);
  751. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  752. return;
  753. case CS_CALLEE_CONNECTED:
  754. case CS_CALLER_CONNECTED:
  755. /* common case, handled below */
  756. break;
  757. case CS_CALLEE_SHUTDOWN:
  758. case CS_CALLER_SHUTDOWN:
  759. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
  760. "Cadet audio channel in shutdown; audio data dropped\n");
  761. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  762. return;
  763. }
  764. if (GNUNET_YES == ch->suspended_local)
  765. {
  766. GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "This channel is suspended locally\n");
  767. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  768. return;
  769. }
  770. if (NULL == ch->channel_unreliable)
  771. {
  772. GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
  773. _("Cadet audio channel not ready; audio data dropped\n"));
  774. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  775. return;
  776. }
  777. if (NULL != ch->unreliable_mth)
  778. {
  779. /* NOTE: we may want to not do this and instead combine the data */
  780. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  781. "Bandwidth insufficient; dropping previous audio data segment with %u bytes\n",
  782. (unsigned int) ch->audio_size);
  783. GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
  784. ch->unreliable_mth = NULL;
  785. GNUNET_free (ch->audio_data);
  786. ch->audio_data = NULL;
  787. }
  788. ch->audio_size = size;
  789. ch->audio_data = GNUNET_malloc (ch->audio_size);
  790. memcpy (ch->audio_data,
  791. &msg[1],
  792. size);
  793. ch->unreliable_mth = GNUNET_CADET_notify_transmit_ready (ch->channel_unreliable,
  794. GNUNET_NO,
  795. GNUNET_TIME_UNIT_FOREVER_REL,
  796. sizeof (struct CadetAudioMessage)
  797. + ch->audio_size,
  798. &transmit_line_audio,
  799. ch);
  800. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  801. }
  802. /**
  803. * We are done signalling shutdown to the other peer.
  804. * Destroy the channel.
  805. *
  806. * @param cls the `struct GNUNET_CADET_channel` to destroy
  807. */
  808. static void
  809. mq_done_destroy_channel (void *cls)
  810. {
  811. struct GNUNET_CADET_Channel *channel = cls;
  812. GNUNET_CADET_channel_destroy (channel);
  813. }
  814. /**
  815. * Function to handle a ring message incoming over cadet
  816. *
  817. * @param cls closure, NULL
  818. * @param channel the channel over which the message arrived
  819. * @param channel_ctx the channel context, can be NULL
  820. * or point to the `struct Channel`
  821. * @param message the incoming message
  822. * @return #GNUNET_OK
  823. */
  824. static int
  825. handle_cadet_ring_message (void *cls,
  826. struct GNUNET_CADET_Channel *channel,
  827. void **channel_ctx,
  828. const struct GNUNET_MessageHeader *message)
  829. {
  830. const struct CadetPhoneRingMessage *msg;
  831. struct Line *line;
  832. struct Channel *ch;
  833. struct GNUNET_MQ_Envelope *e;
  834. struct CadetPhoneHangupMessage *hang_up;
  835. struct ClientPhoneRingMessage cring;
  836. struct GNUNET_MQ_Handle *reliable_mq;
  837. msg = (const struct CadetPhoneRingMessage *) message;
  838. if ( (msg->purpose.size != htonl (sizeof (struct GNUNET_PeerIdentity) * 2 +
  839. sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  840. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
  841. sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) ||
  842. (GNUNET_OK !=
  843. GNUNET_CRYPTO_ecdsa_verify (GNUNET_SIGNATURE_PURPOSE_CONVERSATION_RING,
  844. &msg->purpose,
  845. &msg->signature,
  846. &msg->caller_id)) )
  847. {
  848. GNUNET_break_op (0);
  849. return GNUNET_SYSERR;
  850. }
  851. GNUNET_CADET_receive_done (channel); /* needed? */
  852. for (line = lines_head; NULL != line; line = line->next)
  853. if (line->local_line == ntohl (msg->remote_line))
  854. break;
  855. if (NULL == line)
  856. {
  857. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  858. _("No available phone for incoming call on line %u, sending HANG_UP signal\n"),
  859. ntohl (msg->remote_line));
  860. e = GNUNET_MQ_msg (hang_up,
  861. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP);
  862. GNUNET_MQ_notify_sent (e,
  863. &mq_done_destroy_channel,
  864. channel);
  865. reliable_mq = GNUNET_CADET_mq_create (channel);
  866. GNUNET_MQ_send (reliable_mq, e);
  867. /* FIXME: do we need to clean up reliable_mq somehow/somewhere? */
  868. return GNUNET_OK;
  869. }
  870. ch = GNUNET_new (struct Channel);
  871. ch->line = line;
  872. GNUNET_CONTAINER_DLL_insert (line->channel_head,
  873. line->channel_tail,
  874. ch);
  875. ch->status = CS_CALLEE_RINGING;
  876. ch->remote_line = ntohl (msg->source_line);
  877. ch->channel_reliable = channel;
  878. ch->reliable_mq = GNUNET_CADET_mq_create (ch->channel_reliable);
  879. ch->cid = line->cid_gen++;
  880. ch->target = msg->source;
  881. *channel_ctx = ch;
  882. cring.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING);
  883. cring.header.size = htons (sizeof (cring));
  884. cring.cid = ch->cid;
  885. cring.caller_id = msg->caller_id;
  886. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  887. "Sending RING message to client. CID %u:(%u, %u)\n",
  888. ch->cid, ch->remote_line, line->local_line);
  889. GNUNET_SERVER_notification_context_unicast (nc,
  890. line->client,
  891. &cring.header,
  892. GNUNET_NO);
  893. return GNUNET_OK;
  894. }
  895. /**
  896. * Function to handle a hangup message incoming over cadet
  897. *
  898. * @param cls closure, NULL
  899. * @param channel the channel over which the message arrived
  900. * @param channel_ctx the channel context, can be NULL
  901. * or point to the `struct Channel`
  902. * @param message the incoming message
  903. * @return #GNUNET_OK
  904. */
  905. static int
  906. handle_cadet_hangup_message (void *cls,
  907. struct GNUNET_CADET_Channel *channel,
  908. void **channel_ctx,
  909. const struct GNUNET_MessageHeader *message)
  910. {
  911. struct Channel *ch = *channel_ctx;
  912. struct Line *line;
  913. struct ClientPhoneHangupMessage hup;
  914. enum ChannelStatus status;
  915. if (NULL == ch)
  916. {
  917. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  918. "HANGUP message received for non-existing line, dropping channel.\n");
  919. return GNUNET_SYSERR;
  920. }
  921. line = ch->line;
  922. *channel_ctx = NULL;
  923. hup.header.size = htons (sizeof (hup));
  924. hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
  925. hup.cid = ch->cid;
  926. status = ch->status;
  927. GNUNET_CADET_receive_done (channel);
  928. destroy_line_cadet_channels (ch);
  929. switch (status)
  930. {
  931. case CS_CALLEE_RINGING:
  932. case CS_CALLEE_CONNECTED:
  933. break;
  934. case CS_CALLEE_SHUTDOWN:
  935. return GNUNET_OK;
  936. case CS_CALLER_CALLING:
  937. case CS_CALLER_CONNECTED:
  938. break;
  939. case CS_CALLER_SHUTDOWN:
  940. return GNUNET_OK;
  941. }
  942. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  943. "Sending HANG UP message to client\n");
  944. GNUNET_SERVER_notification_context_unicast (nc,
  945. line->client,
  946. &hup.header,
  947. GNUNET_NO);
  948. return GNUNET_OK;
  949. }
  950. /**
  951. * Function to handle a pickup message incoming over cadet
  952. *
  953. * @param cls closure, NULL
  954. * @param channel the channel over which the message arrived
  955. * @param channel_ctx the channel context, can be NULL
  956. * or point to the `struct Channel`
  957. * @param message the incoming message
  958. * @return #GNUNET_OK if message was OK,
  959. * #GNUNET_SYSERR if message violated the protocol
  960. */
  961. static int
  962. handle_cadet_pickup_message (void *cls,
  963. struct GNUNET_CADET_Channel *channel,
  964. void **channel_ctx,
  965. const struct GNUNET_MessageHeader *message)
  966. {
  967. struct Channel *ch = *channel_ctx;
  968. struct Line *line;
  969. struct ClientPhonePickupMessage pick;
  970. if (NULL == ch)
  971. {
  972. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  973. "PICKUP message received for non-existing channel, dropping channel.\n");
  974. return GNUNET_SYSERR;
  975. }
  976. line = ch->line;
  977. GNUNET_CADET_receive_done (channel);
  978. switch (ch->status)
  979. {
  980. case CS_CALLEE_RINGING:
  981. case CS_CALLEE_CONNECTED:
  982. GNUNET_break_op (0);
  983. destroy_line_cadet_channels (ch);
  984. return GNUNET_SYSERR;
  985. case CS_CALLEE_SHUTDOWN:
  986. GNUNET_break_op (0);
  987. destroy_line_cadet_channels (ch);
  988. return GNUNET_SYSERR;
  989. case CS_CALLER_CALLING:
  990. ch->status = CS_CALLER_CONNECTED;
  991. break;
  992. case CS_CALLER_CONNECTED:
  993. GNUNET_break_op (0);
  994. return GNUNET_OK;
  995. case CS_CALLER_SHUTDOWN:
  996. GNUNET_break_op (0);
  997. mq_done_finish_caller_shutdown (ch);
  998. return GNUNET_SYSERR;
  999. }
  1000. pick.header.size = htons (sizeof (pick));
  1001. pick.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICKED_UP);
  1002. pick.cid = ch->cid;
  1003. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1004. "Sending PICKED UP message to client\n");
  1005. GNUNET_SERVER_notification_context_unicast (nc,
  1006. line->client,
  1007. &pick.header,
  1008. GNUNET_NO);
  1009. ch->channel_unreliable = GNUNET_CADET_channel_create (cadet,
  1010. ch,
  1011. &ch->target,
  1012. GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
  1013. GNUNET_CADET_OPTION_DEFAULT);
  1014. if (NULL == ch->channel_unreliable)
  1015. {
  1016. GNUNET_break (0);
  1017. }
  1018. return GNUNET_OK;
  1019. }
  1020. /**
  1021. * Function to handle a suspend message incoming over cadet
  1022. *
  1023. * @param cls closure, NULL
  1024. * @param channel the channel over which the message arrived
  1025. * @param channel_ctx the channel context, can be NULL
  1026. * or point to the `struct Channel`
  1027. * @param message the incoming message
  1028. * @return #GNUNET_OK
  1029. */
  1030. static int
  1031. handle_cadet_suspend_message (void *cls,
  1032. struct GNUNET_CADET_Channel *channel,
  1033. void **channel_ctx,
  1034. const struct GNUNET_MessageHeader *message)
  1035. {
  1036. struct Channel *ch = *channel_ctx;
  1037. struct Line *line;
  1038. struct ClientPhoneSuspendMessage suspend;
  1039. if (NULL == ch)
  1040. {
  1041. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1042. "SUSPEND message received for non-existing line, dropping channel.\n");
  1043. return GNUNET_SYSERR;
  1044. }
  1045. line = ch->line;
  1046. suspend.header.size = htons (sizeof (suspend));
  1047. suspend.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND);
  1048. suspend.cid = ch->cid;
  1049. GNUNET_CADET_receive_done (channel);
  1050. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1051. "Suspending channel CID: %u(%u:%u)\n",
  1052. ch->cid, ch->remote_line, line->local_line);
  1053. switch (ch->status)
  1054. {
  1055. case CS_CALLEE_RINGING:
  1056. GNUNET_break_op (0);
  1057. break;
  1058. case CS_CALLEE_CONNECTED:
  1059. ch->suspended_remote = GNUNET_YES;
  1060. break;
  1061. case CS_CALLEE_SHUTDOWN:
  1062. return GNUNET_OK;
  1063. case CS_CALLER_CALLING:
  1064. GNUNET_break_op (0);
  1065. break;
  1066. case CS_CALLER_CONNECTED:
  1067. ch->suspended_remote = GNUNET_YES;
  1068. break;
  1069. case CS_CALLER_SHUTDOWN:
  1070. return GNUNET_OK;
  1071. }
  1072. GNUNET_SERVER_notification_context_unicast (nc,
  1073. line->client,
  1074. &suspend.header,
  1075. GNUNET_NO);
  1076. return GNUNET_OK;
  1077. }
  1078. /**
  1079. * Function to handle a resume message incoming over cadet
  1080. *
  1081. * @param cls closure, NULL
  1082. * @param channel the channel over which the message arrived
  1083. * @param channel_ctx the channel context, can be NULL
  1084. * or point to the `struct Channel`
  1085. * @param message the incoming message
  1086. * @return #GNUNET_OK
  1087. */
  1088. static int
  1089. handle_cadet_resume_message (void *cls,
  1090. struct GNUNET_CADET_Channel *channel,
  1091. void **channel_ctx,
  1092. const struct GNUNET_MessageHeader *message)
  1093. {
  1094. struct Channel *ch = *channel_ctx;
  1095. struct Line *line;
  1096. struct ClientPhoneResumeMessage resume;
  1097. if (NULL == ch)
  1098. {
  1099. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1100. "RESUME message received for non-existing line, dropping channel.\n");
  1101. return GNUNET_SYSERR;
  1102. }
  1103. line = ch->line;
  1104. resume.header.size = htons (sizeof (resume));
  1105. resume.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME);
  1106. resume.cid = ch->cid;
  1107. GNUNET_CADET_receive_done (channel);
  1108. if (GNUNET_YES != ch->suspended_remote)
  1109. {
  1110. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1111. "RESUME message received for non-suspended channel, dropping channel.\n");
  1112. return GNUNET_SYSERR;
  1113. }
  1114. switch (ch->status)
  1115. {
  1116. case CS_CALLEE_RINGING:
  1117. GNUNET_break (0);
  1118. break;
  1119. case CS_CALLEE_CONNECTED:
  1120. ch->suspended_remote = GNUNET_NO;
  1121. break;
  1122. case CS_CALLEE_SHUTDOWN:
  1123. return GNUNET_OK;
  1124. case CS_CALLER_CALLING:
  1125. GNUNET_break (0);
  1126. break;
  1127. case CS_CALLER_CONNECTED:
  1128. ch->suspended_remote = GNUNET_NO;
  1129. break;
  1130. case CS_CALLER_SHUTDOWN:
  1131. return GNUNET_OK;
  1132. }
  1133. GNUNET_SERVER_notification_context_unicast (nc,
  1134. line->client,
  1135. &resume.header,
  1136. GNUNET_NO);
  1137. return GNUNET_OK;
  1138. }
  1139. /**
  1140. * Function to handle an audio message incoming over cadet
  1141. *
  1142. * @param cls closure, NULL
  1143. * @param channel the channel over which the message arrived
  1144. * @param channel_ctx the channel context, can be NULL
  1145. * or point to the `struct Channel`
  1146. * @param message the incoming message
  1147. * @return #GNUNET_OK
  1148. */
  1149. static int
  1150. handle_cadet_audio_message (void *cls,
  1151. struct GNUNET_CADET_Channel *channel,
  1152. void **channel_ctx,
  1153. const struct GNUNET_MessageHeader *message)
  1154. {
  1155. const struct CadetAudioMessage *msg;
  1156. struct Channel *ch = *channel_ctx;
  1157. struct Line *line;
  1158. struct GNUNET_PeerIdentity sender;
  1159. size_t msize = ntohs (message->size) - sizeof (struct CadetAudioMessage);
  1160. char buf[msize + sizeof (struct ClientAudioMessage)];
  1161. struct ClientAudioMessage *cam;
  1162. const union GNUNET_CADET_ChannelInfo *info;
  1163. msg = (const struct CadetAudioMessage *) message;
  1164. if (NULL == ch)
  1165. {
  1166. info = GNUNET_CADET_channel_get_info (channel,
  1167. GNUNET_CADET_OPTION_PEER);
  1168. if (NULL == info)
  1169. {
  1170. GNUNET_break (0);
  1171. return GNUNET_SYSERR;
  1172. }
  1173. sender = info->peer;
  1174. for (line = lines_head; NULL != line; line = line->next)
  1175. if (line->local_line == ntohl (msg->remote_line))
  1176. {
  1177. for (ch = line->channel_head; NULL != ch; ch = ch->next)
  1178. {
  1179. if ( (CS_CALLEE_CONNECTED == ch->status) &&
  1180. (0 == memcmp (&ch->target,
  1181. &sender,
  1182. sizeof (struct GNUNET_PeerIdentity))) &&
  1183. (NULL == ch->channel_unreliable) &&
  1184. (ch->remote_line == ntohl (msg->source_line)) )
  1185. break;
  1186. }
  1187. break;
  1188. }
  1189. if (NULL == line)
  1190. {
  1191. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1192. "Received %u bytes of AUDIO data for non-existing line %u, dropping.\n",
  1193. msize, ntohl (msg->remote_line));
  1194. return GNUNET_SYSERR;
  1195. }
  1196. if (NULL == ch)
  1197. {
  1198. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1199. "Received %u bytes of AUDIO data for unknown sender.\n",
  1200. msize);
  1201. return GNUNET_SYSERR;
  1202. }
  1203. if ((GNUNET_YES == ch->suspended_local) || (GNUNET_YES == ch->suspended_remote))
  1204. {
  1205. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1206. "Received %u bytes of AUDIO data on suspended channel CID %u:(%u:%u); dropping\n",
  1207. msize, ch->cid, ch->remote_line, line->local_line);
  1208. GNUNET_CADET_receive_done (channel);
  1209. return GNUNET_OK;
  1210. }
  1211. ch->channel_unreliable = channel;
  1212. *channel_ctx = ch;
  1213. }
  1214. GNUNET_CADET_receive_done (channel);
  1215. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1216. "Forwarding %u bytes of AUDIO data to client CID %u:(%u:%u)\n",
  1217. msize, ch->cid, ch->remote_line, ch->line->local_line);
  1218. cam = (struct ClientAudioMessage *) buf;
  1219. cam->header.size = htons (sizeof (buf));
  1220. cam->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
  1221. cam->cid = ch->cid;
  1222. memcpy (&cam[1], &msg[1], msize);
  1223. GNUNET_SERVER_notification_context_unicast (nc,
  1224. ch->line->client,
  1225. &cam->header,
  1226. GNUNET_YES);
  1227. return GNUNET_OK;
  1228. }
  1229. /**
  1230. * Method called whenever another peer has added us to a channel
  1231. * the other peer initiated.
  1232. *
  1233. * @param cls closure
  1234. * @param channel new handle to the channel
  1235. * @param initiator peer that started the channel
  1236. * @param port port
  1237. * @param options channel option flags
  1238. * @return initial channel context for the channel;
  1239. * (can be NULL -- that's not an error)
  1240. */
  1241. static void *
  1242. inbound_channel (void *cls,
  1243. struct GNUNET_CADET_Channel *channel,
  1244. const struct GNUNET_PeerIdentity *initiator,
  1245. uint32_t port, enum GNUNET_CADET_ChannelOption options)
  1246. {
  1247. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  1248. _("Received incoming Cadet channel on port %u\n"),
  1249. (unsigned int) port);
  1250. return NULL;
  1251. }
  1252. /**
  1253. * Function called whenever an inbound channel is destroyed. Should clean up
  1254. * any associated state.
  1255. *
  1256. * @param cls closure (set from #GNUNET_CADET_connect)
  1257. * @param channel connection to the other end (henceforth invalid)
  1258. * @param channel_ctx place where local state associated
  1259. * with the channel is stored;
  1260. * may point to the `struct Channel`
  1261. */
  1262. static void
  1263. inbound_end (void *cls,
  1264. const struct GNUNET_CADET_Channel *channel,
  1265. void *channel_ctx)
  1266. {
  1267. struct Channel *ch = channel_ctx;
  1268. struct Line *line;
  1269. struct ClientPhoneHangupMessage hup;
  1270. if (NULL == ch)
  1271. {
  1272. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1273. "Cadet channel destroyed, but channel is unknown to us\n");
  1274. return;
  1275. }
  1276. line = ch->line;
  1277. if (ch->channel_unreliable == channel)
  1278. {
  1279. if (NULL != ch->unreliable_mth)
  1280. {
  1281. GNUNET_CADET_notify_transmit_ready_cancel (ch->unreliable_mth);
  1282. ch->unreliable_mth = NULL;
  1283. }
  1284. ch->channel_unreliable = NULL;
  1285. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1286. "Unreliable channel destroyed\n");
  1287. return;
  1288. }
  1289. if (ch->channel_reliable != channel)
  1290. {
  1291. /* recursive call, I'm the one destroying 'ch' right now */
  1292. return;
  1293. }
  1294. ch->channel_reliable = NULL;
  1295. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1296. "Cadet channel destroyed by Cadet in state %d\n",
  1297. ch->status);
  1298. hup.header.size = htons (sizeof (hup));
  1299. hup.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
  1300. hup.cid = ch->cid;
  1301. switch (ch->status)
  1302. {
  1303. case CS_CALLEE_RINGING:
  1304. case CS_CALLEE_CONNECTED:
  1305. GNUNET_SERVER_notification_context_unicast (nc,
  1306. line->client,
  1307. &hup.header,
  1308. GNUNET_NO);
  1309. break;
  1310. case CS_CALLEE_SHUTDOWN:
  1311. break;
  1312. case CS_CALLER_CALLING:
  1313. case CS_CALLER_CONNECTED:
  1314. GNUNET_SERVER_notification_context_unicast (nc,
  1315. line->client,
  1316. &hup.header,
  1317. GNUNET_NO);
  1318. break;
  1319. case CS_CALLER_SHUTDOWN:
  1320. break;
  1321. }
  1322. destroy_line_cadet_channels (ch);
  1323. }
  1324. /**
  1325. * A client disconnected. Remove all of its data structure entries.
  1326. *
  1327. * @param cls closure, NULL
  1328. * @param client identification of the client
  1329. */
  1330. static void
  1331. handle_client_disconnect (void *cls,
  1332. struct GNUNET_SERVER_Client *client)
  1333. {
  1334. struct Line *line;
  1335. if (NULL == client)
  1336. return;
  1337. line = GNUNET_SERVER_client_get_user_context (client, struct Line);
  1338. if (NULL == line)
  1339. return;
  1340. GNUNET_SERVER_client_set_user_context (client, (void *)NULL);
  1341. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  1342. "Client disconnected, closing line\n");
  1343. GNUNET_CONTAINER_DLL_remove (lines_head,
  1344. lines_tail,
  1345. line);
  1346. while (NULL != line->channel_head)
  1347. destroy_line_cadet_channels (line->channel_head);
  1348. GNUNET_free (line);
  1349. }
  1350. /**
  1351. * Shutdown nicely
  1352. *
  1353. * @param cls closure, NULL
  1354. * @param tc the task context
  1355. */
  1356. static void
  1357. do_shutdown (void *cls,
  1358. const struct GNUNET_SCHEDULER_TaskContext *tc)
  1359. {
  1360. struct Line *line;
  1361. struct Channel *ch;
  1362. while (NULL != (line = lines_head))
  1363. {
  1364. while (NULL != (ch = line->channel_head))
  1365. destroy_line_cadet_channels (ch);
  1366. GNUNET_CONTAINER_DLL_remove (lines_head,
  1367. lines_tail,
  1368. line);
  1369. GNUNET_SERVER_client_set_user_context (line->client, (void *) NULL);
  1370. GNUNET_free (line);
  1371. }
  1372. if (NULL != cadet)
  1373. {
  1374. GNUNET_CADET_disconnect (cadet);
  1375. cadet = NULL;
  1376. }
  1377. if (NULL != nc)
  1378. {
  1379. GNUNET_SERVER_notification_context_destroy (nc);
  1380. nc = NULL;
  1381. }
  1382. }
  1383. /**
  1384. * Main function that will be run by the scheduler.
  1385. *
  1386. * @param cls closure
  1387. * @param server server handle
  1388. * @param c configuration
  1389. */
  1390. static void
  1391. run (void *cls,
  1392. struct GNUNET_SERVER_Handle *server,
  1393. const struct GNUNET_CONFIGURATION_Handle *c)
  1394. {
  1395. static const struct GNUNET_SERVER_MessageHandler server_handlers[] = {
  1396. {&handle_client_register_message, NULL,
  1397. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER,
  1398. sizeof (struct ClientPhoneRegisterMessage)},
  1399. {&handle_client_pickup_message, NULL,
  1400. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP,
  1401. sizeof (struct ClientPhonePickupMessage) },
  1402. {&handle_client_suspend_message, NULL,
  1403. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_SUSPEND,
  1404. sizeof (struct ClientPhoneSuspendMessage) },
  1405. {&handle_client_resume_message, NULL,
  1406. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RESUME,
  1407. sizeof (struct ClientPhoneResumeMessage) },
  1408. {&handle_client_hangup_message, NULL,
  1409. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
  1410. sizeof (struct ClientPhoneHangupMessage) },
  1411. {&handle_client_call_message, NULL,
  1412. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_CALL,
  1413. sizeof (struct ClientCallMessage) },
  1414. {&handle_client_audio_message, NULL,
  1415. GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
  1416. 0},
  1417. {NULL, NULL, 0, 0}
  1418. };
  1419. static struct GNUNET_CADET_MessageHandler cadet_handlers[] = {
  1420. {&handle_cadet_ring_message,
  1421. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RING,
  1422. sizeof (struct CadetPhoneRingMessage)},
  1423. {&handle_cadet_hangup_message,
  1424. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_HANG_UP,
  1425. sizeof (struct CadetPhoneHangupMessage)},
  1426. {&handle_cadet_pickup_message,
  1427. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_PICK_UP,
  1428. sizeof (struct CadetPhonePickupMessage)},
  1429. {&handle_cadet_suspend_message,
  1430. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_SUSPEND,
  1431. sizeof (struct CadetPhoneSuspendMessage)},
  1432. {&handle_cadet_resume_message,
  1433. GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_PHONE_RESUME,
  1434. sizeof (struct CadetPhoneResumeMessage)},
  1435. {&handle_cadet_audio_message, GNUNET_MESSAGE_TYPE_CONVERSATION_CADET_AUDIO,
  1436. 0},
  1437. {NULL, 0, 0}
  1438. };
  1439. static uint32_t ports[] = {
  1440. GNUNET_APPLICATION_TYPE_CONVERSATION_CONTROL,
  1441. GNUNET_APPLICATION_TYPE_CONVERSATION_AUDIO,
  1442. 0
  1443. };
  1444. cfg = c;
  1445. GNUNET_assert (GNUNET_OK ==
  1446. GNUNET_CRYPTO_get_peer_identity (cfg,
  1447. &my_identity));
  1448. cadet = GNUNET_CADET_connect (cfg,
  1449. NULL,
  1450. &inbound_channel,
  1451. &inbound_end,
  1452. cadet_handlers,
  1453. ports);
  1454. if (NULL == cadet)
  1455. {
  1456. GNUNET_break (0);
  1457. GNUNET_SCHEDULER_shutdown ();
  1458. return;
  1459. }
  1460. nc = GNUNET_SERVER_notification_context_create (server, 16);
  1461. GNUNET_SERVER_add_handlers (server, server_handlers);
  1462. GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
  1463. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  1464. &do_shutdown,
  1465. NULL);
  1466. }
  1467. /**
  1468. * The main function for the conversation service.
  1469. *
  1470. * @param argc number of arguments from the command line
  1471. * @param argv command line arguments
  1472. * @return 0 ok, 1 on error
  1473. */
  1474. int
  1475. main (int argc,
  1476. char *const *argv)
  1477. {
  1478. return (GNUNET_OK ==
  1479. GNUNET_SERVICE_run (argc, argv,
  1480. "conversation",
  1481. GNUNET_SERVICE_OPTION_NONE,
  1482. &run, NULL)) ? 0 : 1;
  1483. }
  1484. /* end of gnunet-service-conversation.c */