gnunet-service-ats_scheduling.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011-2014 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 ats/gnunet-service-ats_scheduling.c
  19. * @brief ats service, interaction with 'scheduling' API
  20. * @author Matthias Wachs
  21. * @author Christian Grothoff
  22. */
  23. #include "platform.h"
  24. #include "gnunet-service-ats_addresses.h"
  25. #include "gnunet-service-ats_scheduling.h"
  26. #include "ats.h"
  27. /**
  28. * Context for sending messages to clients.
  29. */
  30. static struct GNUNET_SERVER_NotificationContext *nc;
  31. /**
  32. * Actual handle to the client.
  33. */
  34. static struct GNUNET_SERVER_Client *my_client;
  35. /**
  36. * Register a new scheduling client.
  37. *
  38. * @param client handle of the new client
  39. * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  40. */
  41. int
  42. GAS_scheduling_add_client (struct GNUNET_SERVER_Client *client)
  43. {
  44. if (NULL != my_client)
  45. {
  46. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  47. "This ATS already has a scheduling client, refusing new scheduling client for now.\n");
  48. return GNUNET_SYSERR;
  49. }
  50. my_client = client;
  51. GNUNET_SERVER_notification_context_add (nc,
  52. client);
  53. GNUNET_SERVER_client_set_user_context (client,
  54. &nc);
  55. return GNUNET_OK;
  56. }
  57. /**
  58. * Unregister a client (which may have been a scheduling client,
  59. * but this is not assured).
  60. *
  61. * @param client handle of the (now dead) client
  62. */
  63. void
  64. GAS_scheduling_remove_client (struct GNUNET_SERVER_Client *client)
  65. {
  66. if (my_client != client)
  67. return;
  68. GAS_addresses_destroy_all ();
  69. my_client = NULL;
  70. }
  71. /**
  72. * Transmit the given address suggestion and bandwidth update to all scheduling
  73. * clients.
  74. *
  75. * @param peer peer for which this is an address suggestion
  76. * @param session_id session ID to use for the given client
  77. * @param bandwidth_out assigned outbound bandwidth
  78. * @param bandwidth_in assigned inbound bandwidth
  79. */
  80. void
  81. GAS_scheduling_transmit_address_suggestion (const struct GNUNET_PeerIdentity *peer,
  82. uint32_t session_id,
  83. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
  84. struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
  85. {
  86. struct AddressSuggestionMessage msg;
  87. if (NULL == my_client)
  88. return;
  89. GNUNET_STATISTICS_update (GSA_stats,
  90. "# address suggestions made",
  91. 1,
  92. GNUNET_NO);
  93. msg.header.size = htons (sizeof (struct AddressSuggestionMessage));
  94. msg.header.type = htons (GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION);
  95. msg.peer = *peer;
  96. msg.session_id = htonl (session_id);
  97. msg.bandwidth_out = bandwidth_out;
  98. msg.bandwidth_in = bandwidth_in;
  99. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  100. "ATS sends quota for peer `%s': (in/out) %u/%u\n",
  101. GNUNET_i2s (peer),
  102. (unsigned int) ntohl (bandwidth_in.value__),
  103. (unsigned int) ntohl (bandwidth_out.value__));
  104. GNUNET_SERVER_notification_context_unicast (nc,
  105. my_client,
  106. &msg.header,
  107. GNUNET_YES);
  108. }
  109. /**
  110. * Handle 'address add' messages from clients.
  111. *
  112. * @param cls unused, NULL
  113. * @param client client that sent the request
  114. * @param message the request message
  115. */
  116. void
  117. GAS_handle_address_add (void *cls,
  118. struct GNUNET_SERVER_Client *client,
  119. const struct GNUNET_MessageHeader *message)
  120. {
  121. const struct AddressAddMessage *m;
  122. const struct GNUNET_ATS_Information *atsi;
  123. const char *address;
  124. const char *plugin_name;
  125. uint16_t address_length;
  126. uint16_t plugin_name_length;
  127. uint32_t ats_count;
  128. uint16_t size;
  129. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  130. "Received `%s' message\n",
  131. "ADDRESS_ADD");
  132. size = ntohs (message->size);
  133. if (size < sizeof (struct AddressAddMessage))
  134. {
  135. GNUNET_break (0);
  136. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  137. return;
  138. }
  139. m = (const struct AddressAddMessage *) message;
  140. ats_count = ntohl (m->ats_count);
  141. address_length = ntohs (m->address_length);
  142. plugin_name_length = ntohs (m->plugin_name_length);
  143. atsi = (const struct GNUNET_ATS_Information *) &m[1];
  144. address = (const char *) &atsi[ats_count];
  145. if (plugin_name_length != 0)
  146. plugin_name = &address[address_length];
  147. else
  148. plugin_name = "";
  149. if ((address_length + plugin_name_length +
  150. ats_count * sizeof (struct GNUNET_ATS_Information) +
  151. sizeof (struct AddressAddMessage) != ntohs (message->size)) ||
  152. (ats_count >
  153. GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)) ||
  154. ((plugin_name_length > 0) && (plugin_name[plugin_name_length - 1] != '\0')))
  155. {
  156. GNUNET_break (0);
  157. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  158. return;
  159. }
  160. GNUNET_STATISTICS_update (GSA_stats,
  161. "# addresses created", 1,
  162. GNUNET_NO);
  163. GAS_addresses_add (&m->peer,
  164. plugin_name,
  165. address,
  166. address_length,
  167. ntohl (m->address_local_info),
  168. ntohl (m->session_id),
  169. atsi, ats_count);
  170. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  171. }
  172. /**
  173. * Handle 'address update' messages from clients.
  174. *
  175. * @param cls unused, NULL
  176. * @param client client that sent the request
  177. * @param message the request message
  178. */
  179. void
  180. GAS_handle_address_update (void *cls,
  181. struct GNUNET_SERVER_Client *client,
  182. const struct GNUNET_MessageHeader *message)
  183. {
  184. const struct AddressUpdateMessage *m;
  185. const struct GNUNET_ATS_Information *atsi;
  186. uint32_t ats_count;
  187. uint16_t size;
  188. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  189. "Received `%s' message\n",
  190. "ADDRESS_UPDATE");
  191. size = ntohs (message->size);
  192. if (size < sizeof (struct AddressUpdateMessage))
  193. {
  194. GNUNET_break (0);
  195. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  196. return;
  197. }
  198. m = (const struct AddressUpdateMessage *) message;
  199. ats_count = ntohl (m->ats_count);
  200. atsi = (const struct GNUNET_ATS_Information *) &m[1];
  201. if ((ats_count * sizeof (struct GNUNET_ATS_Information) +
  202. sizeof (struct AddressUpdateMessage) != ntohs (message->size)) ||
  203. (ats_count >
  204. GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_ATS_Information)))
  205. {
  206. GNUNET_break (0);
  207. GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
  208. return;
  209. }
  210. GNUNET_STATISTICS_update (GSA_stats,
  211. "# address updates received",
  212. 1,
  213. GNUNET_NO);
  214. GAS_addresses_update (&m->peer,
  215. ntohl (m->session_id),
  216. atsi, ats_count);
  217. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  218. }
  219. /**
  220. * Handle 'address destroyed' messages from clients.
  221. *
  222. * @param cls unused, NULL
  223. * @param client client that sent the request
  224. * @param message the request message
  225. */
  226. void
  227. GAS_handle_address_destroyed (void *cls,
  228. struct GNUNET_SERVER_Client *client,
  229. const struct GNUNET_MessageHeader *message)
  230. {
  231. const struct AddressDestroyedMessage *m;
  232. struct SessionReleaseMessage srm;
  233. m = (const struct AddressDestroyedMessage *) message;
  234. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  235. "Received `%s' message\n",
  236. "ADDRESS_DESTROYED");
  237. GNUNET_STATISTICS_update (GSA_stats,
  238. "# addresses destroyed",
  239. 1,
  240. GNUNET_NO);
  241. GAS_addresses_destroy (&m->peer,
  242. ntohl (m->session_id));
  243. srm.header.type = ntohs (GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE);
  244. srm.header.size = ntohs (sizeof (struct SessionReleaseMessage));
  245. srm.session_id = m->session_id;
  246. srm.peer = m->peer;
  247. GNUNET_SERVER_notification_context_unicast (nc,
  248. client,
  249. &srm.header,
  250. GNUNET_NO);
  251. GNUNET_SERVER_receive_done (client, GNUNET_OK);
  252. }
  253. /**
  254. * Initialize scheduling subsystem.
  255. *
  256. * @param server handle to our server
  257. * @param ah the address handle to use
  258. */
  259. void
  260. GAS_scheduling_init (struct GNUNET_SERVER_Handle *server)
  261. {
  262. nc = GNUNET_SERVER_notification_context_create (server, 128);
  263. }
  264. /**
  265. * Shutdown scheduling subsystem.
  266. */
  267. void
  268. GAS_scheduling_done ()
  269. {
  270. if (NULL != my_client)
  271. {
  272. my_client = NULL;
  273. }
  274. GNUNET_SERVER_notification_context_destroy (nc);
  275. nc = NULL;
  276. }
  277. /* end of gnunet-service-ats_scheduling.c */