cadet_api_get_channel.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011, 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/cadet_api_get_channel.c
  18. * @brief cadet api: client implementation of cadet service
  19. * @author Bartlomiej Polot
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_constants.h"
  25. #include "gnunet_cadet_service.h"
  26. #include "cadet.h"
  27. #include "cadet_protocol.h"
  28. /**
  29. * Operation handle.
  30. */
  31. struct GNUNET_CADET_ChannelMonitor {
  32. /**
  33. * Channel callback.
  34. */
  35. GNUNET_CADET_ChannelCB channel_cb;
  36. /**
  37. * Info callback closure for @c channel_cb.
  38. */
  39. void *channel_cb_cls;
  40. /**
  41. * Configuration we use.
  42. */
  43. const struct GNUNET_CONFIGURATION_Handle *cfg;
  44. /**
  45. * Message queue to talk to CADET service.
  46. */
  47. struct GNUNET_MQ_Handle *mq;
  48. /**
  49. * Task to reconnect.
  50. */
  51. struct GNUNET_SCHEDULER_Task *reconnect_task;
  52. /**
  53. * Backoff for reconnect attempts.
  54. */
  55. struct GNUNET_TIME_Relative backoff;
  56. /**
  57. * Peer we want information about.
  58. */
  59. struct GNUNET_PeerIdentity peer;
  60. };
  61. /**
  62. * Check that message received from CADET service is well-formed.
  63. *
  64. * @param cls unused
  65. * @param message the message we got
  66. * @return #GNUNET_OK if the message is well-formed,
  67. * #GNUNET_SYSERR otherwise
  68. */
  69. static int
  70. check_channel_info(void *cls,
  71. const struct GNUNET_CADET_ChannelInfoMessage *message)
  72. {
  73. (void)cls;
  74. return GNUNET_OK;
  75. }
  76. /**
  77. * Process a local peer info reply, pass info to the user.
  78. *
  79. * @param cls Closure
  80. * @param message Message itself.
  81. */
  82. static void
  83. handle_channel_info(void *cls,
  84. const struct GNUNET_CADET_ChannelInfoMessage *message)
  85. {
  86. struct GNUNET_CADET_ChannelMonitor *cm = cls;
  87. struct GNUNET_CADET_ChannelInternals ci;
  88. ci.root = message->root;
  89. ci.dest = message->dest;
  90. cm->channel_cb(cm->channel_cb_cls,
  91. &ci);
  92. GNUNET_CADET_get_channel_cancel(cm);
  93. }
  94. /**
  95. * Process a local peer info reply, pass info to the user.
  96. *
  97. * @param cls Closure
  98. * @param message Message itself.
  99. */
  100. static void
  101. handle_channel_info_end(void *cls,
  102. const struct GNUNET_MessageHeader *message)
  103. {
  104. struct GNUNET_CADET_ChannelMonitor *cm = cls;
  105. cm->channel_cb(cm->channel_cb_cls,
  106. NULL);
  107. GNUNET_CADET_get_channel_cancel(cm);
  108. }
  109. /**
  110. * Reconnect to the service and try again.
  111. *
  112. * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
  113. */
  114. static void
  115. reconnect(void *cls);
  116. /**
  117. * Function called on connection trouble. Reconnects.
  118. *
  119. * @param cls a `struct GNUNET_CADET_ChannelMonitor``
  120. * @param error error code from MQ
  121. */
  122. static void
  123. error_handler(void *cls,
  124. enum GNUNET_MQ_Error error)
  125. {
  126. struct GNUNET_CADET_ChannelMonitor *cm = cls;
  127. GNUNET_MQ_destroy(cm->mq);
  128. cm->mq = NULL;
  129. cm->backoff = GNUNET_TIME_randomized_backoff(cm->backoff,
  130. GNUNET_TIME_UNIT_MINUTES);
  131. cm->reconnect_task = GNUNET_SCHEDULER_add_delayed(cm->backoff,
  132. &reconnect,
  133. cm);
  134. }
  135. /**
  136. * Reconnect to the service and try again.
  137. *
  138. * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
  139. */
  140. static void
  141. reconnect(void *cls)
  142. {
  143. struct GNUNET_CADET_ChannelMonitor *cm = cls;
  144. struct GNUNET_MQ_MessageHandler handlers[] = {
  145. GNUNET_MQ_hd_fixed_size(channel_info_end,
  146. GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL_END,
  147. struct GNUNET_MessageHeader,
  148. cm),
  149. GNUNET_MQ_hd_var_size(channel_info,
  150. GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL,
  151. struct GNUNET_CADET_ChannelInfoMessage,
  152. cm),
  153. GNUNET_MQ_handler_end()
  154. };
  155. struct GNUNET_CADET_RequestChannelInfoMessage *msg;
  156. struct GNUNET_MQ_Envelope *env;
  157. cm->reconnect_task = NULL;
  158. cm->mq = GNUNET_CLIENT_connect(cm->cfg,
  159. "cadet",
  160. handlers,
  161. &error_handler,
  162. cm);
  163. if (NULL == cm->mq)
  164. return;
  165. env = GNUNET_MQ_msg(msg,
  166. GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_CHANNEL);
  167. msg->target = cm->peer;
  168. GNUNET_MQ_send(cm->mq,
  169. env);
  170. }
  171. /**
  172. * Request information about a specific channel of the running cadet peer.
  173. *
  174. * @param cfg configuration to use
  175. * @param peer ID of the other end of the channel.
  176. * @param callback Function to call with the requested data.
  177. * @param callback_cls Closure for @c callback.
  178. * @return NULL on error
  179. */
  180. struct GNUNET_CADET_ChannelMonitor *
  181. GNUNET_CADET_get_channel(const struct GNUNET_CONFIGURATION_Handle *cfg,
  182. struct GNUNET_PeerIdentity *peer,
  183. GNUNET_CADET_ChannelCB callback,
  184. void *callback_cls)
  185. {
  186. struct GNUNET_CADET_ChannelMonitor *cm;
  187. if (NULL == callback)
  188. {
  189. GNUNET_break(0);
  190. return NULL;
  191. }
  192. cm = GNUNET_new(struct GNUNET_CADET_ChannelMonitor);
  193. cm->channel_cb = callback;
  194. cm->channel_cb_cls = callback_cls;
  195. cm->cfg = cfg;
  196. cm->peer = *peer;
  197. reconnect(cm);
  198. if (NULL == cm->mq)
  199. {
  200. GNUNET_free(cm);
  201. return NULL;
  202. }
  203. return cm;
  204. }
  205. /**
  206. * Cancel a channel monitor request. The callback will not be called (anymore).
  207. *
  208. * @param h Cadet handle.
  209. * @return Closure that was given to #GNUNET_CADET_get_channel().
  210. */
  211. void *
  212. GNUNET_CADET_get_channel_cancel(struct GNUNET_CADET_ChannelMonitor *cm)
  213. {
  214. void *ret = cm->channel_cb_cls;
  215. if (NULL != cm->mq)
  216. GNUNET_MQ_destroy(cm->mq);
  217. if (NULL != cm->reconnect_task)
  218. GNUNET_SCHEDULER_cancel(cm->reconnect_task);
  219. GNUNET_free(cm);
  220. return ret;
  221. }
  222. /* end of cadet_api_get_channel.c */