gnunet-cadet.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 2017, 2019 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file cadet/gnunet-cadet.c
  18. * @brief Print information about cadet tunnels and peers.
  19. * @author Bartlomiej Polot
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_cadet_service.h"
  25. #include "cadet.h"
  26. #define STREAM_BUFFER_SIZE 1024 // Pakets
  27. /**
  28. * Option -P.
  29. */
  30. static int request_peers;
  31. /**
  32. * Option --peer
  33. */
  34. static char *peer_id;
  35. /**
  36. * Option -T.
  37. */
  38. static int request_tunnels;
  39. /**
  40. * Option --connection
  41. */
  42. static char *conn_id;
  43. /**
  44. * Option --channel
  45. */
  46. static char *channel_id;
  47. /**
  48. * Port to listen on (-o).
  49. */
  50. static char *listen_port;
  51. /**
  52. * Request echo service
  53. */
  54. static int echo;
  55. /**
  56. * Time of last echo request.
  57. */
  58. static struct GNUNET_TIME_Absolute echo_time;
  59. /**
  60. * Task for next echo request.
  61. */
  62. static struct GNUNET_SCHEDULER_Task *echo_task;
  63. /**
  64. * Peer to connect to.
  65. */
  66. static char *target_id;
  67. /**
  68. * Port to connect to
  69. */
  70. static char *target_port = "default";
  71. /**
  72. * Cadet handle.
  73. */
  74. static struct GNUNET_CADET_Handle *mh;
  75. /**
  76. * Our configuration.
  77. */
  78. static const struct GNUNET_CONFIGURATION_Handle *my_cfg;
  79. /**
  80. * Active get path operation.
  81. */
  82. static struct GNUNET_CADET_GetPath *gpo;
  83. /**
  84. * Active peer listing operation.
  85. */
  86. static struct GNUNET_CADET_PeersLister *plo;
  87. /**
  88. * Active tunnel listing operation.
  89. */
  90. static struct GNUNET_CADET_ListTunnels *tio;
  91. /**
  92. * Channel handle.
  93. */
  94. static struct GNUNET_CADET_Channel *ch;
  95. /**
  96. * HashCode of the given port string
  97. */
  98. static struct GNUNET_HashCode porthash;
  99. /**
  100. * Data structure for ongoing reception of incoming virtual circuits.
  101. */
  102. struct GNUNET_CADET_Port *lp;
  103. /**
  104. * Task for reading from stdin.
  105. */
  106. static struct GNUNET_SCHEDULER_Task *rd_task;
  107. /**
  108. * Task for main job.
  109. */
  110. static struct GNUNET_SCHEDULER_Task *job;
  111. static unsigned int sent_pkt;
  112. /**
  113. * Wait for input on STDIO and send it out over the #ch.
  114. */
  115. static void
  116. listen_stdio(void);
  117. /**
  118. * Convert encryption status to human readable string.
  119. *
  120. * @param status Encryption status.
  121. *
  122. * @return Human readable string.
  123. */
  124. static const char *
  125. enc_2s(uint16_t status)
  126. {
  127. switch (status)
  128. {
  129. case 0:
  130. return "NULL ";
  131. case 1:
  132. return "KSENT";
  133. case 2:
  134. return "KRECV";
  135. case 3:
  136. return "READY";
  137. default:
  138. return "";
  139. }
  140. }
  141. /**
  142. * Convert connection status to human readable string.
  143. *
  144. * @param status Connection status.
  145. *
  146. * @return Human readable string.
  147. */
  148. static const char *
  149. conn_2s(uint16_t status)
  150. {
  151. switch (status)
  152. {
  153. case 0:
  154. return "NEW ";
  155. case 1:
  156. return "SRCH ";
  157. case 2:
  158. return "WAIT ";
  159. case 3:
  160. return "READY";
  161. case 4:
  162. return "SHUTD";
  163. default:
  164. return "";
  165. }
  166. }
  167. /**
  168. * Task to shut down this application.
  169. *
  170. * @param cls Closure (unused).
  171. */
  172. static void
  173. shutdown_task(void *cls)
  174. {
  175. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n");
  176. if (NULL != lp)
  177. {
  178. GNUNET_CADET_close_port(lp);
  179. lp = NULL;
  180. }
  181. if (NULL != ch)
  182. {
  183. GNUNET_CADET_channel_destroy(ch);
  184. ch = NULL;
  185. }
  186. if (NULL != gpo)
  187. {
  188. GNUNET_CADET_get_path_cancel(gpo);
  189. gpo = NULL;
  190. }
  191. if (NULL != plo)
  192. {
  193. GNUNET_CADET_list_peers_cancel(plo);
  194. plo = NULL;
  195. }
  196. if (NULL != tio)
  197. {
  198. GNUNET_CADET_list_tunnels_cancel(tio);
  199. tio = NULL;
  200. }
  201. if (NULL != mh)
  202. {
  203. GNUNET_CADET_disconnect(mh);
  204. mh = NULL;
  205. }
  206. if (NULL != rd_task)
  207. {
  208. GNUNET_SCHEDULER_cancel(rd_task);
  209. rd_task = NULL;
  210. }
  211. if (NULL != echo_task)
  212. {
  213. GNUNET_SCHEDULER_cancel(echo_task);
  214. echo_task = NULL;
  215. }
  216. if (NULL != job)
  217. {
  218. GNUNET_SCHEDULER_cancel(job);
  219. job = NULL;
  220. }
  221. }
  222. void
  223. mq_cb(void *cls)
  224. {
  225. listen_stdio();
  226. }
  227. /**
  228. * Task run in stdio mode, after some data is available at stdin.
  229. *
  230. * @param cls Closure (unused).
  231. */
  232. static void
  233. read_stdio(void *cls)
  234. {
  235. struct GNUNET_MQ_Envelope *env;
  236. struct GNUNET_MessageHeader *msg;
  237. char buf[60000];
  238. ssize_t data_size;
  239. rd_task = NULL;
  240. data_size = read(0, buf, 60000);
  241. if (data_size < 1)
  242. {
  243. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  244. "read() returned %s\n",
  245. strerror(errno));
  246. GNUNET_SCHEDULER_shutdown();
  247. return;
  248. }
  249. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  250. "Read %u bytes from stdio\n",
  251. (unsigned int)data_size);
  252. env = GNUNET_MQ_msg_extra(msg, data_size, GNUNET_MESSAGE_TYPE_CADET_CLI);
  253. GNUNET_memcpy(&msg[1], buf, data_size);
  254. GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env);
  255. sent_pkt++;
  256. if (GNUNET_NO == echo)
  257. {
  258. // Use MQ's notification if too much data of stdin is pooring in too fast.
  259. if (STREAM_BUFFER_SIZE < sent_pkt)
  260. {
  261. GNUNET_MQ_notify_sent(env, mq_cb, cls);
  262. sent_pkt = 0;
  263. }
  264. else
  265. {
  266. listen_stdio();
  267. }
  268. }
  269. else
  270. {
  271. echo_time = GNUNET_TIME_absolute_get();
  272. }
  273. }
  274. /**
  275. * Wait for input on STDIO and send it out over the #ch.
  276. */
  277. static void
  278. listen_stdio()
  279. {
  280. struct GNUNET_NETWORK_FDSet *rs;
  281. /* FIXME: why use 'rs' here, seems overly complicated... */
  282. rs = GNUNET_NETWORK_fdset_create();
  283. GNUNET_NETWORK_fdset_set_native(rs, 0); /* STDIN */
  284. rd_task = GNUNET_SCHEDULER_add_select(GNUNET_SCHEDULER_PRIORITY_DEFAULT,
  285. GNUNET_TIME_UNIT_FOREVER_REL,
  286. rs,
  287. NULL,
  288. &read_stdio,
  289. NULL);
  290. GNUNET_NETWORK_fdset_destroy(rs);
  291. }
  292. /**
  293. * Function called whenever a channel is destroyed. Should clean up
  294. * any associated state.
  295. *
  296. * It must NOT call #GNUNET_CADET_channel_destroy on the channel.
  297. *
  298. * @param cls closure
  299. * @param channel connection to the other end (henceforth invalid)
  300. */
  301. static void
  302. channel_ended(void *cls, const struct GNUNET_CADET_Channel *channel)
  303. {
  304. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n");
  305. GNUNET_assert(channel == ch);
  306. ch = NULL;
  307. GNUNET_SCHEDULER_shutdown();
  308. }
  309. /**
  310. * Method called whenever another peer has added us to a channel
  311. * the other peer initiated.
  312. * Only called (once) upon reception of data with a message type which was
  313. * subscribed to in #GNUNET_CADET_connect.
  314. *
  315. * A call to #GNUNET_CADET_channel_destroy causes the channel to be ignored.
  316. * In this case the handler MUST return NULL.
  317. *
  318. * @param cls closure
  319. * @param channel new handle to the channel
  320. * @param initiator peer that started the channel
  321. * @return initial channel context for the channel, we use @a channel
  322. */
  323. static void *
  324. channel_incoming(void *cls,
  325. struct GNUNET_CADET_Channel *channel,
  326. const struct GNUNET_PeerIdentity *initiator)
  327. {
  328. GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
  329. "Incoming connection from %s\n",
  330. GNUNET_i2s_full(initiator));
  331. GNUNET_assert(NULL == ch);
  332. GNUNET_assert(NULL != lp);
  333. GNUNET_CADET_close_port(lp);
  334. lp = NULL;
  335. ch = channel;
  336. if (GNUNET_NO == echo)
  337. listen_stdio();
  338. return channel;
  339. }
  340. /**
  341. * @brief Send an echo request to the remote peer.
  342. *
  343. * @param cls Closure (NULL).
  344. */
  345. static void
  346. send_echo(void *cls)
  347. {
  348. struct GNUNET_MQ_Envelope *env;
  349. struct GNUNET_MessageHeader *msg;
  350. echo_task = NULL;
  351. if (NULL == ch)
  352. return;
  353. env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_CADET_CLI);
  354. GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env);
  355. }
  356. /**
  357. * Check data message sanity. Does nothing so far (all messages are OK).
  358. *
  359. * @param cls Closure (unused).
  360. * @param message The message to check.
  361. * @return #GNUNET_OK to keep the channel open,
  362. * #GNUNET_SYSERR to close it (signal serious error).
  363. */
  364. static int
  365. check_data(void *cls, const struct GNUNET_MessageHeader *message)
  366. {
  367. return GNUNET_OK; /* all is well-formed */
  368. }
  369. /**
  370. * Function called whenever a message is received.
  371. *
  372. * Each time the function must call #GNUNET_CADET_receive_done on the channel
  373. * in order to receive the next message. This doesn't need to be immediate:
  374. * can be delayed if some processing is done on the message.
  375. *
  376. * @param cls NULL
  377. * @param message The actual message.
  378. */
  379. static void
  380. handle_data(void *cls, const struct GNUNET_MessageHeader *message)
  381. {
  382. size_t payload_size = ntohs(message->size) - sizeof(*message);
  383. uint16_t len;
  384. ssize_t done;
  385. uint16_t off;
  386. const char *buf;
  387. GNUNET_CADET_receive_done(ch);
  388. if (GNUNET_YES == echo)
  389. {
  390. if (NULL != listen_port)
  391. {
  392. struct GNUNET_MQ_Envelope *env;
  393. struct GNUNET_MessageHeader *msg;
  394. env =
  395. GNUNET_MQ_msg_extra(msg, payload_size, GNUNET_MESSAGE_TYPE_CADET_CLI);
  396. GNUNET_memcpy(&msg[1], &message[1], payload_size);
  397. GNUNET_MQ_send(GNUNET_CADET_get_mq(ch), env);
  398. return;
  399. }
  400. else
  401. {
  402. struct GNUNET_TIME_Relative latency;
  403. latency = GNUNET_TIME_absolute_get_duration(echo_time);
  404. echo_time = GNUNET_TIME_UNIT_FOREVER_ABS;
  405. GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
  406. "time: %s\n",
  407. GNUNET_STRINGS_relative_time_to_string(latency, GNUNET_NO));
  408. echo_task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS,
  409. &send_echo,
  410. NULL);
  411. }
  412. }
  413. len = ntohs(message->size) - sizeof(*message);
  414. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len);
  415. buf = (const char *)&message[1];
  416. off = 0;
  417. while (off < len)
  418. {
  419. done = write(1, &buf[off], len - off);
  420. if (done <= 0)
  421. {
  422. if (-1 == done)
  423. GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "write");
  424. GNUNET_SCHEDULER_shutdown();
  425. return;
  426. }
  427. off += done;
  428. }
  429. }
  430. /**
  431. * Method called to retrieve information about all peers in CADET, called
  432. * once per peer.
  433. *
  434. * After last peer has been reported, an additional call with NULL is done.
  435. *
  436. * @param cls Closure.
  437. * @param ple information about peer, or NULL on "EOF".
  438. */
  439. static void
  440. peers_callback(void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
  441. {
  442. if (NULL == ple)
  443. {
  444. plo = NULL;
  445. GNUNET_SCHEDULER_shutdown();
  446. return;
  447. }
  448. fprintf(stdout,
  449. "%s tunnel: %c, paths: %u\n",
  450. GNUNET_i2s_full(&ple->peer),
  451. ple->have_tunnel ? 'Y' : 'N',
  452. ple->n_paths);
  453. }
  454. /**
  455. * Method called to retrieve information about paths to a specific peer
  456. * known to the service.
  457. *
  458. * @param cls Closure.
  459. * @param ppd path detail
  460. */
  461. static void
  462. path_callback(void *cls, const struct GNUNET_CADET_PeerPathDetail *ppd)
  463. {
  464. if (NULL == ppd)
  465. {
  466. gpo = NULL;
  467. GNUNET_SCHEDULER_shutdown();
  468. return;
  469. }
  470. fprintf(stdout, "Path of length %u: ", ppd->path_length);
  471. for (unsigned int i = 0; i < ppd->path_length; i++)
  472. fprintf(stdout,
  473. (i == ppd->target_offset) ? "*%s* " : "%s ",
  474. GNUNET_i2s(&ppd->path[i]));
  475. fprintf(stdout, "\n");
  476. }
  477. /**
  478. * Method called to retrieve information about all tunnels in CADET.
  479. *
  480. * @param cls Closure.
  481. * @param td tunnel details
  482. */
  483. static void
  484. tunnels_callback(void *cls, const struct GNUNET_CADET_TunnelDetails *td)
  485. {
  486. if (NULL == td)
  487. {
  488. tio = NULL;
  489. GNUNET_SCHEDULER_shutdown();
  490. return;
  491. }
  492. fprintf(stdout,
  493. "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n",
  494. GNUNET_i2s_full(&td->peer),
  495. enc_2s(td->estate),
  496. conn_2s(td->cstate),
  497. td->channels,
  498. td->connections);
  499. }
  500. /**
  501. * Call CADET's meta API, get all peers known to a peer.
  502. *
  503. * @param cls Closure (unused).
  504. */
  505. static void
  506. get_peers(void *cls)
  507. {
  508. job = NULL;
  509. plo = GNUNET_CADET_list_peers(my_cfg, &peers_callback, NULL);
  510. }
  511. /**
  512. * Call CADET's monitor API, get info of one peer.
  513. *
  514. * @param cls Closure (unused).
  515. */
  516. static void
  517. show_peer(void *cls)
  518. {
  519. struct GNUNET_PeerIdentity pid;
  520. job = NULL;
  521. if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string(peer_id,
  522. strlen(peer_id),
  523. &pid.public_key))
  524. {
  525. fprintf(stderr, _("Invalid peer ID `%s'\n"), peer_id);
  526. GNUNET_SCHEDULER_shutdown();
  527. return;
  528. }
  529. gpo = GNUNET_CADET_get_path(my_cfg, &pid, &path_callback, NULL);
  530. }
  531. /**
  532. * Call CADET's meta API, get all tunnels known to a peer.
  533. *
  534. * @param cls Closure (unused).
  535. */
  536. static void
  537. get_tunnels(void *cls)
  538. {
  539. job = NULL;
  540. tio = GNUNET_CADET_list_tunnels(my_cfg, &tunnels_callback, NULL);
  541. }
  542. /**
  543. * Call CADET's monitor API, get info of one channel.
  544. *
  545. * @param cls Closure (unused).
  546. */
  547. static void
  548. show_channel(void *cls)
  549. {
  550. job = NULL;
  551. GNUNET_break(0);
  552. }
  553. /**
  554. * Call CADET's monitor API, get info of one connection.
  555. *
  556. * @param cls Closure (unused).
  557. */
  558. static void
  559. show_connection(void *cls)
  560. {
  561. job = NULL;
  562. GNUNET_break(0);
  563. }
  564. /**
  565. * Main function that will be run by the scheduler.
  566. *
  567. * @param cls closure
  568. * @param args remaining command-line arguments
  569. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  570. * @param cfg configuration
  571. */
  572. static void
  573. run(void *cls,
  574. char *const *args,
  575. const char *cfgfile,
  576. const struct GNUNET_CONFIGURATION_Handle *cfg)
  577. {
  578. struct GNUNET_MQ_MessageHandler handlers[] =
  579. { GNUNET_MQ_hd_var_size(data,
  580. GNUNET_MESSAGE_TYPE_CADET_CLI,
  581. struct GNUNET_MessageHeader,
  582. NULL),
  583. GNUNET_MQ_handler_end() };
  584. /* FIXME add option to monitor apps */
  585. my_cfg = cfg;
  586. target_id = args[0];
  587. if (target_id && args[1])
  588. target_port = args[1];
  589. if ((0 != (request_peers | request_tunnels) || NULL != conn_id ||
  590. NULL != channel_id) &&
  591. target_id != NULL)
  592. {
  593. fprintf(stderr,
  594. _("Extra arguments are not applicable "
  595. "in combination with this option.\n"));
  596. return;
  597. }
  598. if (NULL != peer_id)
  599. {
  600. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show peer\n");
  601. job = GNUNET_SCHEDULER_add_now(&show_peer, NULL);
  602. }
  603. else if (NULL != channel_id)
  604. {
  605. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show channel\n");
  606. job = GNUNET_SCHEDULER_add_now(&show_channel, NULL);
  607. }
  608. else if (NULL != conn_id)
  609. {
  610. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show connection\n");
  611. job = GNUNET_SCHEDULER_add_now(&show_connection, NULL);
  612. }
  613. else if (GNUNET_YES == request_peers)
  614. {
  615. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n");
  616. job = GNUNET_SCHEDULER_add_now(&get_peers, NULL);
  617. }
  618. else if (GNUNET_YES == request_tunnels)
  619. {
  620. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n");
  621. job = GNUNET_SCHEDULER_add_now(&get_tunnels, NULL);
  622. }
  623. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET service\n");
  624. mh = GNUNET_CADET_connect(cfg);
  625. GNUNET_SCHEDULER_add_shutdown(&shutdown_task, NULL);
  626. if (NULL == mh)
  627. {
  628. GNUNET_SCHEDULER_shutdown();
  629. return;
  630. }
  631. if (NULL != listen_port)
  632. {
  633. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening CADET listen port\n");
  634. GNUNET_CRYPTO_hash(listen_port, strlen(listen_port), &porthash);
  635. lp = GNUNET_CADET_open_port(mh,
  636. &porthash,
  637. &channel_incoming,
  638. NULL,
  639. NULL /* window changes */,
  640. &channel_ended,
  641. handlers);
  642. }
  643. if (NULL != target_id)
  644. {
  645. struct GNUNET_PeerIdentity pid;
  646. if (GNUNET_OK !=
  647. GNUNET_CRYPTO_eddsa_public_key_from_string(target_id,
  648. strlen(target_id),
  649. &pid.public_key))
  650. {
  651. GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE,
  652. _("Invalid target `%s'\n"),
  653. target_id);
  654. GNUNET_SCHEDULER_shutdown();
  655. return;
  656. }
  657. GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
  658. "Connecting to `%s:%s'\n",
  659. target_id,
  660. target_port);
  661. GNUNET_CRYPTO_hash(target_port, strlen(target_port), &porthash);
  662. ch = GNUNET_CADET_channel_create(mh,
  663. NULL,
  664. &pid,
  665. &porthash,
  666. NULL /* window changes */,
  667. &channel_ended,
  668. handlers);
  669. if (GNUNET_YES == echo)
  670. {
  671. echo_task = GNUNET_SCHEDULER_add_now(&send_echo, NULL);
  672. }
  673. else
  674. {
  675. listen_stdio();
  676. }
  677. }
  678. if ((NULL == lp) && (NULL == job) && (NULL == ch))
  679. {
  680. GNUNET_log(GNUNET_ERROR_TYPE_MESSAGE, _("No action requested\n"));
  681. GNUNET_SCHEDULER_shutdown();
  682. return;
  683. }
  684. }
  685. /**
  686. * The main function to obtain peer information.
  687. *
  688. * @param argc number of arguments from the command line
  689. * @param argv command line arguments
  690. * @return 0 ok, 1 on error
  691. */
  692. int
  693. main(int argc, char *const *argv)
  694. {
  695. int res;
  696. const char helpstr[] =
  697. "Create tunnels and retrieve info about CADET's status.";
  698. struct GNUNET_GETOPT_CommandLineOption options[] =
  699. { /* I would use the terminology 'circuit' here... --lynX */
  700. GNUNET_GETOPT_option_string(
  701. 'C',
  702. "connection",
  703. "CONNECTION_ID",
  704. gettext_noop("Provide information about a particular connection"),
  705. &conn_id),
  706. GNUNET_GETOPT_option_flag('e',
  707. "echo",
  708. gettext_noop("Activate echo mode"),
  709. &echo),
  710. GNUNET_GETOPT_option_string(
  711. 'o',
  712. "open-port",
  713. "SHARED_SECRET",
  714. gettext_noop(
  715. "Listen for connections using a shared secret among sender and recipient"),
  716. &listen_port),
  717. GNUNET_GETOPT_option_string('p',
  718. "peer",
  719. "PEER_ID",
  720. gettext_noop(
  721. "Provide information about a patricular peer"),
  722. &peer_id),
  723. GNUNET_GETOPT_option_flag('P',
  724. "peers",
  725. gettext_noop(
  726. "Provide information about all peers"),
  727. &request_peers),
  728. GNUNET_GETOPT_option_flag('T',
  729. "tunnels",
  730. gettext_noop(
  731. "Provide information about all tunnels"),
  732. &request_tunnels),
  733. GNUNET_GETOPT_OPTION_END
  734. };
  735. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args(argc, argv, &argc, &argv))
  736. return 2;
  737. res = GNUNET_PROGRAM_run(argc,
  738. argv,
  739. "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)",
  740. gettext_noop(helpstr),
  741. options,
  742. &run,
  743. NULL);
  744. GNUNET_free((void *)argv);
  745. if (GNUNET_OK == res)
  746. return 0;
  747. return 1;
  748. }
  749. /* end of gnunet-cadet.c */