diff options
Diffstat (limited to 'src/ats/gnunet-service-ats-new.c')
-rw-r--r-- | src/ats/gnunet-service-ats-new.c | 804 |
1 files changed, 0 insertions, 804 deletions
diff --git a/src/ats/gnunet-service-ats-new.c b/src/ats/gnunet-service-ats-new.c deleted file mode 100644 index f2ef92436..000000000 --- a/src/ats/gnunet-service-ats-new.c +++ /dev/null | |||
@@ -1,804 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file ats/gnunet-service-ats-new.c | ||
22 | * @brief ats service | ||
23 | * @author Matthias Wachs | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_statistics_service.h" | ||
29 | #include "gnunet_ats_plugin_new.h" | ||
30 | #include "ats2.h" | ||
31 | |||
32 | |||
33 | /** | ||
34 | * What type of client is this client? | ||
35 | */ | ||
36 | enum ClientType | ||
37 | { | ||
38 | /** | ||
39 | * We don't know yet. | ||
40 | */ | ||
41 | CT_NONE = 0, | ||
42 | |||
43 | /** | ||
44 | * Transport service. | ||
45 | */ | ||
46 | CT_TRANSPORT, | ||
47 | |||
48 | /** | ||
49 | * Application. | ||
50 | */ | ||
51 | CT_APPLICATION | ||
52 | }; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Information we track per client. | ||
57 | */ | ||
58 | struct Client; | ||
59 | |||
60 | /** | ||
61 | * Preferences expressed by a client are kept in a DLL per client. | ||
62 | */ | ||
63 | struct ClientPreference | ||
64 | { | ||
65 | /** | ||
66 | * DLL pointer. | ||
67 | */ | ||
68 | struct ClientPreference *next; | ||
69 | |||
70 | /** | ||
71 | * DLL pointer. | ||
72 | */ | ||
73 | struct ClientPreference *prev; | ||
74 | |||
75 | /** | ||
76 | * Which client expressed the preference? | ||
77 | */ | ||
78 | struct Client *client; | ||
79 | |||
80 | /** | ||
81 | * Plugin's representation of the preference. | ||
82 | */ | ||
83 | struct GNUNET_ATS_PreferenceHandle *ph; | ||
84 | |||
85 | /** | ||
86 | * Details about the preference. | ||
87 | */ | ||
88 | struct GNUNET_ATS_Preference pref; | ||
89 | }; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Information about ongoing sessions of the transport client. | ||
94 | */ | ||
95 | struct GNUNET_ATS_Session | ||
96 | { | ||
97 | /** | ||
98 | * Session data exposed to the plugin. | ||
99 | */ | ||
100 | struct GNUNET_ATS_SessionData data; | ||
101 | |||
102 | /** | ||
103 | * The transport client that provided the session. | ||
104 | */ | ||
105 | struct Client *client; | ||
106 | |||
107 | /** | ||
108 | * Session state in the plugin. | ||
109 | */ | ||
110 | struct GNUNET_ATS_SessionHandle *sh; | ||
111 | |||
112 | /** | ||
113 | * Unique ID for the session when talking with the client. | ||
114 | */ | ||
115 | uint32_t session_id; | ||
116 | }; | ||
117 | |||
118 | |||
119 | /** | ||
120 | * Information we track per client. | ||
121 | */ | ||
122 | struct Client | ||
123 | { | ||
124 | /** | ||
125 | * Type of the client, initially #CT_NONE. | ||
126 | */ | ||
127 | enum ClientType type; | ||
128 | |||
129 | /** | ||
130 | * Service handle of the client. | ||
131 | */ | ||
132 | struct GNUNET_SERVICE_Client *client; | ||
133 | |||
134 | /** | ||
135 | * Message queue to talk to the client. | ||
136 | */ | ||
137 | struct GNUNET_MQ_Handle *mq; | ||
138 | |||
139 | /** | ||
140 | * Details depending on @e type. | ||
141 | */ | ||
142 | union | ||
143 | { | ||
144 | struct | ||
145 | { | ||
146 | /** | ||
147 | * Head of DLL of preferences expressed by this client. | ||
148 | */ | ||
149 | struct ClientPreference *cp_head; | ||
150 | |||
151 | /** | ||
152 | * Tail of DLL of preferences expressed by this client. | ||
153 | */ | ||
154 | struct ClientPreference *cp_tail; | ||
155 | } application; | ||
156 | |||
157 | struct | ||
158 | { | ||
159 | /** | ||
160 | * Map from session IDs to `struct GNUNET_ATS_Session` objects. | ||
161 | */ | ||
162 | struct GNUNET_CONTAINER_MultiHashMap32 *sessions; | ||
163 | } transport; | ||
164 | } details; | ||
165 | }; | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Handle for statistics. | ||
170 | */ | ||
171 | static struct GNUNET_STATISTICS_Handle *stats; | ||
172 | |||
173 | /** | ||
174 | * Our solver. | ||
175 | */ | ||
176 | static struct GNUNET_ATS_SolverFunctions *plugin; | ||
177 | |||
178 | /** | ||
179 | * Solver plugin name as string | ||
180 | */ | ||
181 | static char *plugin_name; | ||
182 | |||
183 | /** | ||
184 | * The transport client (there can only be one at a time). | ||
185 | */ | ||
186 | static struct Client *transport_client; | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Function called by the solver to prompt the transport to | ||
191 | * try out a new address. | ||
192 | * | ||
193 | * @param cls closure, NULL | ||
194 | * @param pid peer this is about | ||
195 | * @param address address the transport should try | ||
196 | */ | ||
197 | static void | ||
198 | suggest_cb (void *cls, | ||
199 | const struct GNUNET_PeerIdentity *pid, | ||
200 | const char *address) | ||
201 | { | ||
202 | struct GNUNET_MQ_Envelope *env; | ||
203 | size_t slen = strlen (address) + 1; | ||
204 | struct AddressSuggestionMessage *as; | ||
205 | |||
206 | if (NULL == transport_client) | ||
207 | { | ||
208 | // FIXME: stats! | ||
209 | return; | ||
210 | } | ||
211 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
212 | "Suggesting address `%s' of peer `%s'\n", | ||
213 | address, | ||
214 | GNUNET_i2s (pid)); | ||
215 | env = GNUNET_MQ_msg_extra (as, | ||
216 | slen, | ||
217 | GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION); | ||
218 | as->peer = *pid; | ||
219 | memcpy (&as[1], | ||
220 | address, | ||
221 | slen); | ||
222 | GNUNET_MQ_send (transport_client->mq, | ||
223 | env); | ||
224 | } | ||
225 | |||
226 | |||
227 | /** | ||
228 | * Function called by the solver to tell the transpor to | ||
229 | * allocate bandwidth for the specified session. | ||
230 | * | ||
231 | * @param cls closure, NULL | ||
232 | * @param session session this is about | ||
233 | * @param peer peer this is about | ||
234 | * @param bw_in suggested bandwidth for receiving | ||
235 | * @param bw_out suggested bandwidth for transmission | ||
236 | */ | ||
237 | static void | ||
238 | allocate_cb (void *cls, | ||
239 | struct GNUNET_ATS_Session *session, | ||
240 | const struct GNUNET_PeerIdentity *peer, | ||
241 | struct GNUNET_BANDWIDTH_Value32NBO bw_in, | ||
242 | struct GNUNET_BANDWIDTH_Value32NBO bw_out) | ||
243 | { | ||
244 | struct GNUNET_MQ_Envelope *env; | ||
245 | struct SessionAllocationMessage *sam; | ||
246 | |||
247 | (void) cls; | ||
248 | if ((NULL == transport_client) || | ||
249 | (session->client != transport_client)) | ||
250 | { | ||
251 | /* transport must have just died and solver is addressing the | ||
252 | losses of sessions (possibly of previous transport), ignore! */ | ||
253 | return; | ||
254 | } | ||
255 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
256 | "Allocating %u/%u bytes for %p of peer `%s'\n", | ||
257 | ntohl (bw_in.value__), | ||
258 | ntohl (bw_out.value__), | ||
259 | session, | ||
260 | GNUNET_i2s (peer)); | ||
261 | env = GNUNET_MQ_msg (sam, | ||
262 | GNUNET_MESSAGE_TYPE_ATS_SESSION_ALLOCATION); | ||
263 | sam->session_id = session->session_id; | ||
264 | sam->peer = *peer; | ||
265 | sam->bandwidth_in = bw_in; | ||
266 | sam->bandwidth_out = bw_out; | ||
267 | GNUNET_MQ_send (transport_client->mq, | ||
268 | env); | ||
269 | } | ||
270 | |||
271 | |||
272 | /** | ||
273 | * Convert @a properties to @a prop | ||
274 | * | ||
275 | * @param properties in NBO | ||
276 | * @param prop[out] in HBO | ||
277 | */ | ||
278 | static void | ||
279 | prop_ntoh (const struct PropertiesNBO *properties, | ||
280 | struct GNUNET_ATS_Properties *prop) | ||
281 | { | ||
282 | prop->delay = GNUNET_TIME_relative_ntoh (properties->delay); | ||
283 | prop->goodput_out = ntohl (properties->goodput_out); | ||
284 | prop->goodput_in = ntohl (properties->goodput_in); | ||
285 | prop->utilization_out = ntohl (properties->utilization_out); | ||
286 | prop->utilization_in = ntohl (properties->utilization_in); | ||
287 | prop->distance = ntohl (properties->distance); | ||
288 | prop->mtu = ntohl (properties->mtu); | ||
289 | prop->nt = (enum GNUNET_NetworkType) ntohl (properties->nt); | ||
290 | prop->cc = (enum GNUNET_TRANSPORT_CommunicatorCharacteristics) ntohl ( | ||
291 | properties->cc); | ||
292 | } | ||
293 | |||
294 | |||
295 | /** | ||
296 | * We have received a `struct ExpressPreferenceMessage` from an application client. | ||
297 | * | ||
298 | * @param cls handle to the client | ||
299 | * @param msg the start message | ||
300 | */ | ||
301 | static void | ||
302 | handle_suggest (void *cls, | ||
303 | const struct ExpressPreferenceMessage *msg) | ||
304 | { | ||
305 | struct Client *c = cls; | ||
306 | struct ClientPreference *cp; | ||
307 | |||
308 | if (CT_NONE == c->type) | ||
309 | c->type = CT_APPLICATION; | ||
310 | if (CT_APPLICATION != c->type) | ||
311 | { | ||
312 | GNUNET_break (0); | ||
313 | GNUNET_SERVICE_client_drop (c->client); | ||
314 | return; | ||
315 | } | ||
316 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
317 | "Client suggested we talk to %s with preference %d at rate %u\n", | ||
318 | GNUNET_i2s (&msg->peer), | ||
319 | (int) ntohl (msg->pk), | ||
320 | (int) ntohl (msg->bw.value__)); | ||
321 | cp = GNUNET_new (struct ClientPreference); | ||
322 | cp->client = c; | ||
323 | cp->pref.peer = msg->peer; | ||
324 | cp->pref.bw = msg->bw; | ||
325 | cp->pref.pk = (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk); | ||
326 | cp->ph = plugin->preference_add (plugin->cls, | ||
327 | &cp->pref); | ||
328 | GNUNET_CONTAINER_DLL_insert (c->details.application.cp_head, | ||
329 | c->details.application.cp_tail, | ||
330 | cp); | ||
331 | GNUNET_SERVICE_client_continue (c->client); | ||
332 | } | ||
333 | |||
334 | |||
335 | /** | ||
336 | * We have received a `struct ExpressPreferenceMessage` from an application client. | ||
337 | * | ||
338 | * @param cls handle to the client | ||
339 | * @param msg the start message | ||
340 | */ | ||
341 | static void | ||
342 | handle_suggest_cancel (void *cls, | ||
343 | const struct ExpressPreferenceMessage *msg) | ||
344 | { | ||
345 | struct Client *c = cls; | ||
346 | struct ClientPreference *cp; | ||
347 | |||
348 | if (CT_NONE == c->type) | ||
349 | c->type = CT_APPLICATION; | ||
350 | if (CT_APPLICATION != c->type) | ||
351 | { | ||
352 | GNUNET_break (0); | ||
353 | GNUNET_SERVICE_client_drop (c->client); | ||
354 | return; | ||
355 | } | ||
356 | for (cp = c->details.application.cp_head; | ||
357 | NULL != cp; | ||
358 | cp = cp->next) | ||
359 | if ((cp->pref.pk == (enum GNUNET_MQ_PreferenceKind) ntohl (msg->pk)) && | ||
360 | (cp->pref.bw.value__ == msg->bw.value__) && | ||
361 | (0 == GNUNET_memcmp (&cp->pref.peer, | ||
362 | &msg->peer))) | ||
363 | break; | ||
364 | if (NULL == cp) | ||
365 | { | ||
366 | GNUNET_break (0); | ||
367 | GNUNET_SERVICE_client_drop (c->client); | ||
368 | return; | ||
369 | } | ||
370 | plugin->preference_del (plugin->cls, | ||
371 | cp->ph, | ||
372 | &cp->pref); | ||
373 | GNUNET_CONTAINER_DLL_remove (c->details.application.cp_head, | ||
374 | c->details.application.cp_tail, | ||
375 | cp); | ||
376 | GNUNET_free (cp); | ||
377 | GNUNET_SERVICE_client_continue (c->client); | ||
378 | } | ||
379 | |||
380 | |||
381 | /** | ||
382 | * Handle 'start' messages from transport clients. | ||
383 | * | ||
384 | * @param cls client that sent the request | ||
385 | * @param message the request message | ||
386 | */ | ||
387 | static void | ||
388 | handle_start (void *cls, | ||
389 | const struct GNUNET_MessageHeader *hdr) | ||
390 | { | ||
391 | struct Client *c = cls; | ||
392 | |||
393 | if (CT_NONE != c->type) | ||
394 | { | ||
395 | GNUNET_break (0); | ||
396 | GNUNET_SERVICE_client_drop (c->client); | ||
397 | return; | ||
398 | } | ||
399 | c->type = CT_TRANSPORT; | ||
400 | c->details.transport.sessions | ||
401 | = GNUNET_CONTAINER_multihashmap32_create (128); | ||
402 | if (NULL != transport_client) | ||
403 | { | ||
404 | GNUNET_SERVICE_client_drop (transport_client->client); | ||
405 | transport_client = NULL; | ||
406 | } | ||
407 | transport_client = c; | ||
408 | GNUNET_SERVICE_client_continue (c->client); | ||
409 | } | ||
410 | |||
411 | |||
412 | /** | ||
413 | * Check 'session_add' message is well-formed and comes from a | ||
414 | * transport client. | ||
415 | * | ||
416 | * @param cls client that sent the request | ||
417 | * @param message the request message | ||
418 | * @return #GNUNET_OK if @a message is well-formed | ||
419 | */ | ||
420 | static int | ||
421 | check_session_add (void *cls, | ||
422 | const struct SessionAddMessage *message) | ||
423 | { | ||
424 | struct Client *c = cls; | ||
425 | |||
426 | GNUNET_MQ_check_zero_termination (message); | ||
427 | if (CT_TRANSPORT != c->type) | ||
428 | { | ||
429 | GNUNET_break (0); | ||
430 | return GNUNET_SYSERR; | ||
431 | } | ||
432 | return GNUNET_OK; | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Handle 'session add' messages from transport clients. | ||
438 | * | ||
439 | * @param cls client that sent the request | ||
440 | * @param message the request message | ||
441 | */ | ||
442 | static void | ||
443 | handle_session_add (void *cls, | ||
444 | const struct SessionAddMessage *message) | ||
445 | { | ||
446 | struct Client *c = cls; | ||
447 | const char *address = (const char *) &message[1]; | ||
448 | struct GNUNET_ATS_Session *session; | ||
449 | int inbound_only = (GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY == | ||
450 | ntohs (message->header.type)); | ||
451 | |||
452 | session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, | ||
453 | message->session_id); | ||
454 | if (NULL != session) | ||
455 | { | ||
456 | GNUNET_break (0); | ||
457 | GNUNET_SERVICE_client_drop (c->client); | ||
458 | return; | ||
459 | } | ||
460 | session = GNUNET_new (struct GNUNET_ATS_Session); | ||
461 | session->data.session = session; | ||
462 | session->client = c; | ||
463 | session->session_id = message->session_id; | ||
464 | session->data.peer = message->peer; | ||
465 | prop_ntoh (&message->properties, | ||
466 | &session->data.prop); | ||
467 | session->data.inbound_only = inbound_only; | ||
468 | GNUNET_assert (GNUNET_YES == | ||
469 | GNUNET_CONTAINER_multihashmap32_put ( | ||
470 | c->details.transport.sessions, | ||
471 | message->session_id, | ||
472 | session, | ||
473 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
474 | session->sh = plugin->session_add (plugin->cls, | ||
475 | &session->data, | ||
476 | address); | ||
477 | GNUNET_assert (NULL != session->sh); | ||
478 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
479 | "Transport has new session %p to %s\n", | ||
480 | session, | ||
481 | GNUNET_i2s (&message->peer)); | ||
482 | GNUNET_SERVICE_client_continue (c->client); | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Handle 'session update' messages from transport clients. | ||
488 | * | ||
489 | * @param cls client that sent the request | ||
490 | * @param msg the request message | ||
491 | */ | ||
492 | static void | ||
493 | handle_session_update (void *cls, | ||
494 | const struct SessionUpdateMessage *msg) | ||
495 | { | ||
496 | struct Client *c = cls; | ||
497 | struct GNUNET_ATS_Session *session; | ||
498 | |||
499 | if (CT_TRANSPORT != c->type) | ||
500 | { | ||
501 | GNUNET_break (0); | ||
502 | GNUNET_SERVICE_client_drop (c->client); | ||
503 | return; | ||
504 | } | ||
505 | session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, | ||
506 | msg->session_id); | ||
507 | if (NULL == session) | ||
508 | { | ||
509 | GNUNET_break (0); | ||
510 | GNUNET_SERVICE_client_drop (c->client); | ||
511 | return; | ||
512 | } | ||
513 | prop_ntoh (&msg->properties, | ||
514 | &session->data.prop); | ||
515 | plugin->session_update (plugin->cls, | ||
516 | session->sh, | ||
517 | &session->data); | ||
518 | GNUNET_SERVICE_client_continue (c->client); | ||
519 | } | ||
520 | |||
521 | |||
522 | /** | ||
523 | * Handle 'session delete' messages from transport clients. | ||
524 | * | ||
525 | * @param cls client that sent the request | ||
526 | * @param message the request message | ||
527 | */ | ||
528 | static void | ||
529 | handle_session_del (void *cls, | ||
530 | const struct SessionDelMessage *message) | ||
531 | { | ||
532 | struct Client *c = cls; | ||
533 | struct GNUNET_ATS_Session *session; | ||
534 | |||
535 | if (CT_TRANSPORT != c->type) | ||
536 | { | ||
537 | GNUNET_break (0); | ||
538 | GNUNET_SERVICE_client_drop (c->client); | ||
539 | return; | ||
540 | } | ||
541 | session = GNUNET_CONTAINER_multihashmap32_get (c->details.transport.sessions, | ||
542 | message->session_id); | ||
543 | if (NULL == session) | ||
544 | { | ||
545 | GNUNET_break (0); | ||
546 | GNUNET_SERVICE_client_drop (c->client); | ||
547 | return; | ||
548 | } | ||
549 | GNUNET_assert (NULL != session->sh); | ||
550 | plugin->session_del (plugin->cls, | ||
551 | session->sh, | ||
552 | &session->data); | ||
553 | session->sh = NULL; | ||
554 | GNUNET_assert (GNUNET_YES == | ||
555 | GNUNET_CONTAINER_multihashmap32_remove ( | ||
556 | c->details.transport.sessions, | ||
557 | session->session_id, | ||
558 | session)); | ||
559 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
560 | "Transport lost session %p to %s\n", | ||
561 | session, | ||
562 | GNUNET_i2s (&session->data.peer)); | ||
563 | GNUNET_free (session); | ||
564 | GNUNET_SERVICE_client_continue (c->client); | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * A client connected to us. Setup the local client | ||
570 | * record. | ||
571 | * | ||
572 | * @param cls unused | ||
573 | * @param client handle of the client | ||
574 | * @param mq message queue to talk to @a client | ||
575 | * @return @a client | ||
576 | */ | ||
577 | static void * | ||
578 | client_connect_cb (void *cls, | ||
579 | struct GNUNET_SERVICE_Client *client, | ||
580 | struct GNUNET_MQ_Handle *mq) | ||
581 | { | ||
582 | struct Client *c = GNUNET_new (struct Client); | ||
583 | |||
584 | c->client = client; | ||
585 | c->mq = mq; | ||
586 | return c; | ||
587 | } | ||
588 | |||
589 | |||
590 | /** | ||
591 | * Function called on each session to release associated state | ||
592 | * on transport disconnect. | ||
593 | * | ||
594 | * @param cls the `struct Client` | ||
595 | * @param key unused (session_id) | ||
596 | * @param value a `struct GNUNET_ATS_Session` | ||
597 | */ | ||
598 | static int | ||
599 | free_session (void *cls, | ||
600 | uint32_t key, | ||
601 | void *value) | ||
602 | { | ||
603 | struct Client *c = cls; | ||
604 | struct GNUNET_ATS_Session *session = value; | ||
605 | |||
606 | (void) key; | ||
607 | GNUNET_assert (c == session->client); | ||
608 | GNUNET_assert (NULL != session->sh); | ||
609 | plugin->session_del (plugin->cls, | ||
610 | session->sh, | ||
611 | &session->data); | ||
612 | session->sh = NULL; | ||
613 | GNUNET_free (session); | ||
614 | return GNUNET_OK; | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * A client disconnected from us. Tear down the local client | ||
620 | * record. | ||
621 | * | ||
622 | * @param cls unused | ||
623 | * @param client handle of the client | ||
624 | * @param app_ctx our `struct Client` | ||
625 | */ | ||
626 | static void | ||
627 | client_disconnect_cb (void *cls, | ||
628 | struct GNUNET_SERVICE_Client *client, | ||
629 | void *app_ctx) | ||
630 | { | ||
631 | struct Client *c = app_ctx; | ||
632 | |||
633 | (void) cls; | ||
634 | GNUNET_assert (c->client == client); | ||
635 | switch (c->type) | ||
636 | { | ||
637 | case CT_NONE: | ||
638 | break; | ||
639 | |||
640 | case CT_APPLICATION: | ||
641 | for (struct ClientPreference *cp = c->details.application.cp_head; | ||
642 | NULL != cp; | ||
643 | cp = c->details.application.cp_head) | ||
644 | { | ||
645 | plugin->preference_del (plugin->cls, | ||
646 | cp->ph, | ||
647 | &cp->pref); | ||
648 | GNUNET_CONTAINER_DLL_remove (c->details.application.cp_head, | ||
649 | c->details.application.cp_tail, | ||
650 | cp); | ||
651 | GNUNET_free (cp); | ||
652 | } | ||
653 | break; | ||
654 | |||
655 | case CT_TRANSPORT: | ||
656 | if (transport_client == c) | ||
657 | transport_client = NULL; | ||
658 | GNUNET_CONTAINER_multihashmap32_iterate (c->details.transport.sessions, | ||
659 | &free_session, | ||
660 | c); | ||
661 | GNUNET_CONTAINER_multihashmap32_destroy (c->details.transport.sessions); | ||
662 | break; | ||
663 | } | ||
664 | GNUNET_free (c); | ||
665 | } | ||
666 | |||
667 | |||
668 | /** | ||
669 | * Task run at the end during shutdown. | ||
670 | * | ||
671 | * @param cls unused | ||
672 | */ | ||
673 | static void | ||
674 | final_cleanup (void *cls) | ||
675 | { | ||
676 | (void) cls; | ||
677 | if (NULL != stats) | ||
678 | { | ||
679 | GNUNET_STATISTICS_destroy (stats, | ||
680 | GNUNET_NO); | ||
681 | stats = NULL; | ||
682 | } | ||
683 | if (NULL != plugin) | ||
684 | { | ||
685 | GNUNET_PLUGIN_unload (plugin_name, | ||
686 | plugin); | ||
687 | plugin = NULL; | ||
688 | } | ||
689 | if (NULL != plugin_name) | ||
690 | { | ||
691 | GNUNET_free (plugin_name); | ||
692 | plugin_name = NULL; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | |||
697 | /** | ||
698 | * Task run during shutdown. | ||
699 | * | ||
700 | * @param cls unused | ||
701 | */ | ||
702 | static void | ||
703 | cleanup_task (void *cls) | ||
704 | { | ||
705 | (void) cls; | ||
706 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
707 | "ATS shutdown initiated\n"); | ||
708 | GNUNET_SCHEDULER_add_now (&final_cleanup, | ||
709 | NULL); | ||
710 | } | ||
711 | |||
712 | |||
713 | /** | ||
714 | * Process template requests. | ||
715 | * | ||
716 | * @param cls closure | ||
717 | * @param cfg configuration to use | ||
718 | * @param service the initialized service | ||
719 | */ | ||
720 | static void | ||
721 | run (void *cls, | ||
722 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
723 | struct GNUNET_SERVICE_Handle *service) | ||
724 | { | ||
725 | static struct GNUNET_ATS_PluginEnvironment env; | ||
726 | char *solver; | ||
727 | |||
728 | stats = GNUNET_STATISTICS_create ("ats", | ||
729 | cfg); | ||
730 | if (GNUNET_SYSERR == | ||
731 | GNUNET_CONFIGURATION_get_value_string (cfg, | ||
732 | "ats", | ||
733 | "SOLVER", | ||
734 | &solver)) | ||
735 | { | ||
736 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
737 | "No ATS solver configured, using 'simple' approach\n"); | ||
738 | solver = GNUNET_strdup ("simple"); | ||
739 | } | ||
740 | GNUNET_SCHEDULER_add_shutdown (&cleanup_task, | ||
741 | NULL); | ||
742 | env.cls = NULL; | ||
743 | env.cfg = cfg; | ||
744 | env.stats = stats; | ||
745 | env.suggest_cb = &suggest_cb; | ||
746 | env.allocate_cb = &allocate_cb; | ||
747 | GNUNET_asprintf (&plugin_name, | ||
748 | "libgnunet_plugin_ats2_%s", | ||
749 | solver); | ||
750 | GNUNET_free (solver); | ||
751 | if (NULL == (plugin = GNUNET_PLUGIN_load (plugin_name, | ||
752 | &env))) | ||
753 | { | ||
754 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
755 | _ ("Failed to initialize solver `%s'!\n"), | ||
756 | plugin_name); | ||
757 | GNUNET_SCHEDULER_shutdown (); | ||
758 | return; | ||
759 | } | ||
760 | } | ||
761 | |||
762 | |||
763 | /** | ||
764 | * Define "main" method using service macro. | ||
765 | */ | ||
766 | GNUNET_SERVICE_MAIN | ||
767 | ("ats", | ||
768 | GNUNET_SERVICE_OPTION_NONE, | ||
769 | &run, | ||
770 | &client_connect_cb, | ||
771 | &client_disconnect_cb, | ||
772 | NULL, | ||
773 | GNUNET_MQ_hd_fixed_size (suggest, | ||
774 | GNUNET_MESSAGE_TYPE_ATS_SUGGEST, | ||
775 | struct ExpressPreferenceMessage, | ||
776 | NULL), | ||
777 | GNUNET_MQ_hd_fixed_size (suggest_cancel, | ||
778 | GNUNET_MESSAGE_TYPE_ATS_SUGGEST_CANCEL, | ||
779 | struct ExpressPreferenceMessage, | ||
780 | NULL), | ||
781 | GNUNET_MQ_hd_fixed_size (start, | ||
782 | GNUNET_MESSAGE_TYPE_ATS_START, | ||
783 | struct GNUNET_MessageHeader, | ||
784 | NULL), | ||
785 | GNUNET_MQ_hd_var_size (session_add, | ||
786 | GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD, | ||
787 | struct SessionAddMessage, | ||
788 | NULL), | ||
789 | GNUNET_MQ_hd_var_size (session_add, | ||
790 | GNUNET_MESSAGE_TYPE_ATS_SESSION_ADD_INBOUND_ONLY, | ||
791 | struct SessionAddMessage, | ||
792 | NULL), | ||
793 | GNUNET_MQ_hd_fixed_size (session_update, | ||
794 | GNUNET_MESSAGE_TYPE_ATS_SESSION_UPDATE, | ||
795 | struct SessionUpdateMessage, | ||
796 | NULL), | ||
797 | GNUNET_MQ_hd_fixed_size (session_del, | ||
798 | GNUNET_MESSAGE_TYPE_ATS_SESSION_DEL, | ||
799 | struct SessionDelMessage, | ||
800 | NULL), | ||
801 | GNUNET_MQ_handler_end ()); | ||
802 | |||
803 | |||
804 | /* end of gnunet-service-ats.c */ | ||