diff options
Diffstat (limited to 'src/transport/gnunet-service-transport.c')
-rw-r--r-- | src/transport/gnunet-service-transport.c | 2788 |
1 files changed, 0 insertions, 2788 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c deleted file mode 100644 index fad2ca4a1..000000000 --- a/src/transport/gnunet-service-transport.c +++ /dev/null | |||
@@ -1,2788 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010-2016 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 transport/gnunet-service-transport.c | ||
22 | * @brief main for gnunet-service-transport | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_hello_lib.h" | ||
28 | #include "gnunet_statistics_service.h" | ||
29 | #include "gnunet_transport_service.h" | ||
30 | #include "gnunet_peerinfo_service.h" | ||
31 | #include "gnunet_ats_service.h" | ||
32 | #include "gnunet-service-transport.h" | ||
33 | #include "gnunet-service-transport_ats.h" | ||
34 | #include "gnunet-service-transport_hello.h" | ||
35 | #include "gnunet-service-transport_neighbours.h" | ||
36 | #include "gnunet-service-transport_plugins.h" | ||
37 | #include "gnunet-service-transport_validation.h" | ||
38 | #include "gnunet-service-transport_manipulation.h" | ||
39 | #include "transport.h" | ||
40 | |||
41 | /** | ||
42 | * Size of the blacklist hash map. | ||
43 | */ | ||
44 | #define TRANSPORT_BLACKLIST_HT_SIZE 64 | ||
45 | |||
46 | /** | ||
47 | * How many messages can we have pending for a given client process | ||
48 | * before we start to drop incoming messages? We typically should | ||
49 | * have only one client and so this would be the primary buffer for | ||
50 | * messages, so the number should be chosen rather generously. | ||
51 | * | ||
52 | * The expectation here is that most of the time the queue is large | ||
53 | * enough so that a drop is virtually never required. Note that | ||
54 | * this value must be about as large as 'TOTAL_MSGS' in the | ||
55 | * 'test_transport_api_reliability.c', otherwise that testcase may | ||
56 | * fail. | ||
57 | */ | ||
58 | #define MAX_PENDING (128 * 1024) | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Information we need for an asynchronous session kill. | ||
63 | */ | ||
64 | struct GNUNET_ATS_SessionKiller | ||
65 | { | ||
66 | /** | ||
67 | * Kept in a DLL. | ||
68 | */ | ||
69 | struct GNUNET_ATS_SessionKiller *next; | ||
70 | |||
71 | /** | ||
72 | * Kept in a DLL. | ||
73 | */ | ||
74 | struct GNUNET_ATS_SessionKiller *prev; | ||
75 | |||
76 | /** | ||
77 | * Session to kill. | ||
78 | */ | ||
79 | struct GNUNET_ATS_Session *session; | ||
80 | |||
81 | /** | ||
82 | * Plugin for the session. | ||
83 | */ | ||
84 | struct GNUNET_TRANSPORT_PluginFunctions *plugin; | ||
85 | |||
86 | /** | ||
87 | * The kill task. | ||
88 | */ | ||
89 | struct GNUNET_SCHEDULER_Task *task; | ||
90 | }; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * What type of client is the `struct TransportClient` about? | ||
95 | */ | ||
96 | enum ClientType | ||
97 | { | ||
98 | /** | ||
99 | * We do not know yet (client is fresh). | ||
100 | */ | ||
101 | CT_NONE = 0, | ||
102 | |||
103 | /** | ||
104 | * Is the CORE service, we need to forward traffic to it. | ||
105 | */ | ||
106 | CT_CORE = 1, | ||
107 | |||
108 | /** | ||
109 | * It is a monitor, forward monitor data. | ||
110 | */ | ||
111 | CT_MONITOR = 2, | ||
112 | |||
113 | /** | ||
114 | * It is a blacklist, query about allowed connections. | ||
115 | */ | ||
116 | CT_BLACKLIST = 3, | ||
117 | |||
118 | /** | ||
119 | * CORE client without any handlers. | ||
120 | */ | ||
121 | CT_CORE_NO_HANDLERS = 4 | ||
122 | }; | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Context we use when performing a blacklist check. | ||
127 | */ | ||
128 | struct GST_BlacklistCheck; | ||
129 | |||
130 | /** | ||
131 | * Client connected to the transport service. | ||
132 | */ | ||
133 | struct TransportClient | ||
134 | { | ||
135 | /** | ||
136 | * This is a doubly-linked list. | ||
137 | */ | ||
138 | struct TransportClient *next; | ||
139 | |||
140 | /** | ||
141 | * This is a doubly-linked list. | ||
142 | */ | ||
143 | struct TransportClient *prev; | ||
144 | |||
145 | /** | ||
146 | * Handle to the client. | ||
147 | */ | ||
148 | struct GNUNET_SERVICE_Client *client; | ||
149 | |||
150 | /** | ||
151 | * Message queue to the client. | ||
152 | */ | ||
153 | struct GNUNET_MQ_Handle *mq; | ||
154 | |||
155 | /** | ||
156 | * What type of client is this? | ||
157 | */ | ||
158 | enum ClientType type; | ||
159 | |||
160 | union | ||
161 | { | ||
162 | /** | ||
163 | * Peer identity to monitor the addresses of. | ||
164 | * Zero to monitor all neighbours. Valid if | ||
165 | * @e type is CT_MONITOR. | ||
166 | */ | ||
167 | struct GNUNET_PeerIdentity monitor_peer; | ||
168 | |||
169 | /** | ||
170 | * Additional details if @e type is CT_BLACKLIST. | ||
171 | */ | ||
172 | struct | ||
173 | { | ||
174 | /** | ||
175 | * Blacklist check that we're currently performing (or NULL | ||
176 | * if we're performing one that has been cancelled). | ||
177 | */ | ||
178 | struct GST_BlacklistCheck *bc; | ||
179 | |||
180 | /** | ||
181 | * Set to #GNUNET_YES if we're currently waiting for a reply. | ||
182 | */ | ||
183 | int waiting_for_reply; | ||
184 | |||
185 | /** | ||
186 | * #GNUNET_YES if we have to call receive_done for this client | ||
187 | */ | ||
188 | int call_receive_done; | ||
189 | } blacklist; | ||
190 | } details; | ||
191 | }; | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Context we use when performing a blacklist check. | ||
196 | */ | ||
197 | struct GST_BlacklistCheck | ||
198 | { | ||
199 | /** | ||
200 | * This is a linked list. | ||
201 | */ | ||
202 | struct GST_BlacklistCheck *next; | ||
203 | |||
204 | /** | ||
205 | * This is a linked list. | ||
206 | */ | ||
207 | struct GST_BlacklistCheck *prev; | ||
208 | |||
209 | /** | ||
210 | * Peer being checked. | ||
211 | */ | ||
212 | struct GNUNET_PeerIdentity peer; | ||
213 | |||
214 | /** | ||
215 | * Continuation to call with the result. | ||
216 | */ | ||
217 | GST_BlacklistTestContinuation cont; | ||
218 | |||
219 | /** | ||
220 | * Closure for @e cont. | ||
221 | */ | ||
222 | void *cont_cls; | ||
223 | |||
224 | /** | ||
225 | * Address for #GST_blacklist_abort_matching(), can be NULL. | ||
226 | */ | ||
227 | struct GNUNET_HELLO_Address *address; | ||
228 | |||
229 | /** | ||
230 | * Session for #GST_blacklist_abort_matching(), can be NULL. | ||
231 | */ | ||
232 | struct GNUNET_ATS_Session *session; | ||
233 | |||
234 | /** | ||
235 | * Our current position in the blacklisters list. | ||
236 | */ | ||
237 | struct TransportClient *bl_pos; | ||
238 | |||
239 | /** | ||
240 | * Current task performing the check. | ||
241 | */ | ||
242 | struct GNUNET_SCHEDULER_Task *task; | ||
243 | }; | ||
244 | |||
245 | |||
246 | /** | ||
247 | * Context for address to string operations | ||
248 | */ | ||
249 | struct AddressToStringContext | ||
250 | { | ||
251 | /** | ||
252 | * This is a doubly-linked list. | ||
253 | */ | ||
254 | struct AddressToStringContext *next; | ||
255 | |||
256 | /** | ||
257 | * This is a doubly-linked list. | ||
258 | */ | ||
259 | struct AddressToStringContext *prev; | ||
260 | |||
261 | /** | ||
262 | * Client that made the request. | ||
263 | */ | ||
264 | struct TransportClient *tc; | ||
265 | }; | ||
266 | |||
267 | |||
268 | /** | ||
269 | * Closure for #handle_send_transmit_continuation() | ||
270 | */ | ||
271 | struct SendTransmitContinuationContext | ||
272 | { | ||
273 | /** | ||
274 | * Client that made the request. | ||
275 | */ | ||
276 | struct TransportClient *tc; | ||
277 | |||
278 | /** | ||
279 | * Peer that was the target. | ||
280 | */ | ||
281 | struct GNUNET_PeerIdentity target; | ||
282 | |||
283 | /** | ||
284 | * At what time did we receive the message? | ||
285 | */ | ||
286 | struct GNUNET_TIME_Absolute send_time; | ||
287 | |||
288 | /** | ||
289 | * Unique ID, for logging. | ||
290 | */ | ||
291 | unsigned long long uuid; | ||
292 | |||
293 | /** | ||
294 | * Set to #GNUNET_YES if the connection for @e target goes | ||
295 | * down and we thus must no longer send the | ||
296 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK message. | ||
297 | */ | ||
298 | int down; | ||
299 | }; | ||
300 | |||
301 | |||
302 | /** | ||
303 | * Head of linked list of all clients to this service. | ||
304 | */ | ||
305 | static struct TransportClient *clients_head; | ||
306 | |||
307 | /** | ||
308 | * Tail of linked list of all clients to this service. | ||
309 | */ | ||
310 | static struct TransportClient *clients_tail; | ||
311 | |||
312 | /** | ||
313 | * Map of peer identities to active send transmit continuation | ||
314 | * contexts. Used to flag contexts as 'dead' when a connection goes | ||
315 | * down. Values are of type `struct SendTransmitContinuationContext | ||
316 | * *`. | ||
317 | */ | ||
318 | static struct GNUNET_CONTAINER_MultiPeerMap *active_stccs; | ||
319 | |||
320 | /** | ||
321 | * Head of linked list of all pending address iterations | ||
322 | */ | ||
323 | static struct AddressToStringContext *a2s_head; | ||
324 | |||
325 | /** | ||
326 | * Tail of linked list of all pending address iterations | ||
327 | */ | ||
328 | static struct AddressToStringContext *a2s_tail; | ||
329 | |||
330 | /** | ||
331 | * Head of DLL of active blacklisting queries. | ||
332 | */ | ||
333 | static struct GST_BlacklistCheck *bc_head; | ||
334 | |||
335 | /** | ||
336 | * Tail of DLL of active blacklisting queries. | ||
337 | */ | ||
338 | static struct GST_BlacklistCheck *bc_tail; | ||
339 | |||
340 | /** | ||
341 | * Hashmap of blacklisted peers. Values are of type 'char *' (transport names), | ||
342 | * can be NULL if we have no static blacklist. | ||
343 | */ | ||
344 | static struct GNUNET_CONTAINER_MultiPeerMap *blacklist; | ||
345 | |||
346 | /** | ||
347 | * Notification context, to send updates on changes to active plugin | ||
348 | * connections. | ||
349 | */ | ||
350 | static struct GNUNET_NotificationContext *plugin_nc; | ||
351 | |||
352 | /** | ||
353 | * Plugin monitoring client we are currently syncing, NULL if all | ||
354 | * monitoring clients are in sync. | ||
355 | */ | ||
356 | static struct TransportClient *sync_client; | ||
357 | |||
358 | /** | ||
359 | * Peer identity that is all zeros, used as a way to indicate | ||
360 | * "all peers". Used for comparisons. | ||
361 | */ | ||
362 | static struct GNUNET_PeerIdentity all_zeros; | ||
363 | |||
364 | /** | ||
365 | * Statistics handle. | ||
366 | */ | ||
367 | struct GNUNET_STATISTICS_Handle *GST_stats; | ||
368 | |||
369 | /** | ||
370 | * Configuration handle. | ||
371 | */ | ||
372 | const struct GNUNET_CONFIGURATION_Handle *GST_cfg; | ||
373 | |||
374 | /** | ||
375 | * Configuration handle. | ||
376 | */ | ||
377 | struct GNUNET_PeerIdentity GST_my_identity; | ||
378 | |||
379 | /** | ||
380 | * Handle to peerinfo service. | ||
381 | */ | ||
382 | struct GNUNET_PEERINFO_Handle *GST_peerinfo; | ||
383 | |||
384 | /** | ||
385 | * Our private key. | ||
386 | */ | ||
387 | struct GNUNET_CRYPTO_EddsaPrivateKey GST_my_private_key; | ||
388 | |||
389 | /** | ||
390 | * ATS scheduling handle. | ||
391 | */ | ||
392 | struct GNUNET_ATS_SchedulingHandle *GST_ats; | ||
393 | |||
394 | /** | ||
395 | * ATS connectivity handle. | ||
396 | */ | ||
397 | struct GNUNET_ATS_ConnectivityHandle *GST_ats_connect; | ||
398 | |||
399 | /** | ||
400 | * Hello address expiration | ||
401 | */ | ||
402 | struct GNUNET_TIME_Relative hello_expiration; | ||
403 | |||
404 | /** | ||
405 | * Head of DLL of asynchronous tasks to kill sessions. | ||
406 | */ | ||
407 | static struct GNUNET_ATS_SessionKiller *sk_head; | ||
408 | |||
409 | /** | ||
410 | * Tail of DLL of asynchronous tasks to kill sessions. | ||
411 | */ | ||
412 | static struct GNUNET_ATS_SessionKiller *sk_tail; | ||
413 | |||
414 | /** | ||
415 | * Interface scanner determines our LAN address range(s). | ||
416 | */ | ||
417 | struct GNUNET_NT_InterfaceScanner *GST_is; | ||
418 | |||
419 | /** | ||
420 | * Queue the given message for transmission to the given client | ||
421 | * | ||
422 | * @param tc target of the message | ||
423 | * @param msg message to transmit | ||
424 | * @param may_drop #GNUNET_YES if the message can be dropped | ||
425 | */ | ||
426 | static void | ||
427 | unicast (struct TransportClient *tc, | ||
428 | const struct GNUNET_MessageHeader *msg, | ||
429 | int may_drop) | ||
430 | { | ||
431 | struct GNUNET_MQ_Envelope *env; | ||
432 | |||
433 | if ((GNUNET_MQ_get_length (tc->mq) >= MAX_PENDING) && | ||
434 | (GNUNET_YES == may_drop)) | ||
435 | { | ||
436 | GNUNET_log ( | ||
437 | GNUNET_ERROR_TYPE_DEBUG, | ||
438 | "Dropping message of type %u and size %u, have %u/%u messages pending\n", | ||
439 | ntohs (msg->type), | ||
440 | ntohs (msg->size), | ||
441 | GNUNET_MQ_get_length (tc->mq), | ||
442 | MAX_PENDING); | ||
443 | GNUNET_STATISTICS_update (GST_stats, | ||
444 | gettext_noop ( | ||
445 | "# messages dropped due to slow client"), | ||
446 | 1, | ||
447 | GNUNET_NO); | ||
448 | return; | ||
449 | } | ||
450 | env = GNUNET_MQ_msg_copy (msg); | ||
451 | GNUNET_MQ_send (tc->mq, env); | ||
452 | } | ||
453 | |||
454 | |||
455 | /** | ||
456 | * Called whenever a client connects. Allocates our | ||
457 | * data structures associated with that client. | ||
458 | * | ||
459 | * @param cls closure, NULL | ||
460 | * @param client identification of the client | ||
461 | * @param mq message queue for the client | ||
462 | * @return our `struct TransportClient` | ||
463 | */ | ||
464 | static void * | ||
465 | client_connect_cb (void *cls, | ||
466 | struct GNUNET_SERVICE_Client *client, | ||
467 | struct GNUNET_MQ_Handle *mq) | ||
468 | { | ||
469 | struct TransportClient *tc; | ||
470 | |||
471 | tc = GNUNET_new (struct TransportClient); | ||
472 | tc->client = client; | ||
473 | tc->mq = mq; | ||
474 | GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc); | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc); | ||
476 | return tc; | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
481 | * Perform next action in the blacklist check. | ||
482 | * | ||
483 | * @param cls the `struct BlacklistCheck*` | ||
484 | */ | ||
485 | static void | ||
486 | do_blacklist_check (void *cls); | ||
487 | |||
488 | |||
489 | /** | ||
490 | * Mark the peer as down so we don't call the continuation | ||
491 | * context in the future. | ||
492 | * | ||
493 | * @param cls a `struct TransportClient` | ||
494 | * @param peer a peer we are sending to | ||
495 | * @param value a `struct SendTransmitContinuationContext` to mark | ||
496 | * @return #GNUNET_OK (continue to iterate) | ||
497 | */ | ||
498 | static int | ||
499 | mark_match_down (void *cls, const struct GNUNET_PeerIdentity *peer, void *value) | ||
500 | { | ||
501 | struct TransportClient *tc = cls; | ||
502 | struct SendTransmitContinuationContext *stcc = value; | ||
503 | |||
504 | if (tc == stcc->tc) | ||
505 | { | ||
506 | stcc->down = GNUNET_YES; | ||
507 | stcc->tc = NULL; | ||
508 | } | ||
509 | return GNUNET_OK; | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Called whenever a client is disconnected. Frees our | ||
515 | * resources associated with that client. | ||
516 | * | ||
517 | * @param cls closure, NULL | ||
518 | * @param client identification of the client | ||
519 | * @param app_ctx our `struct TransportClient` | ||
520 | */ | ||
521 | static void | ||
522 | client_disconnect_cb (void *cls, | ||
523 | struct GNUNET_SERVICE_Client *client, | ||
524 | void *app_ctx) | ||
525 | { | ||
526 | struct TransportClient *tc = app_ctx; | ||
527 | struct GST_BlacklistCheck *bc; | ||
528 | |||
529 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
530 | "Client %p disconnected, cleaning up.\n", | ||
531 | tc); | ||
532 | if (NULL != active_stccs) | ||
533 | GNUNET_CONTAINER_multipeermap_iterate (active_stccs, | ||
534 | &mark_match_down, | ||
535 | tc); | ||
536 | for (struct AddressToStringContext *cur = a2s_head; NULL != cur; | ||
537 | cur = cur->next) | ||
538 | { | ||
539 | if (cur->tc == tc) | ||
540 | cur->tc = NULL; | ||
541 | } | ||
542 | GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc); | ||
543 | switch (tc->type) | ||
544 | { | ||
545 | case CT_NONE: | ||
546 | break; | ||
547 | |||
548 | case CT_CORE: | ||
549 | break; | ||
550 | |||
551 | case CT_MONITOR: | ||
552 | break; | ||
553 | |||
554 | case CT_BLACKLIST: | ||
555 | for (bc = bc_head; NULL != bc; bc = bc->next) | ||
556 | { | ||
557 | if (bc->bl_pos != tc) | ||
558 | continue; | ||
559 | bc->bl_pos = tc->next; | ||
560 | if (NULL == bc->task) | ||
561 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
562 | } | ||
563 | break; | ||
564 | |||
565 | case CT_CORE_NO_HANDLERS: | ||
566 | break; | ||
567 | } | ||
568 | GNUNET_free (tc); | ||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Function called for each of our connected neighbours. Notify the | ||
574 | * client about the existing neighbour. | ||
575 | * | ||
576 | * @param cls the `struct TransportClient *` to notify | ||
577 | * @param peer identity of the neighbour | ||
578 | * @param address the address | ||
579 | * @param state the current state of the peer | ||
580 | * @param state_timeout the time out for the state | ||
581 | * @param bandwidth_in inbound bandwidth in NBO | ||
582 | * @param bandwidth_out outbound bandwidth in NBO | ||
583 | */ | ||
584 | static void | ||
585 | notify_client_about_neighbour (void *cls, | ||
586 | const struct GNUNET_PeerIdentity *peer, | ||
587 | const struct GNUNET_HELLO_Address *address, | ||
588 | enum GNUNET_TRANSPORT_PeerState state, | ||
589 | struct GNUNET_TIME_Absolute state_timeout, | ||
590 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
591 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
592 | { | ||
593 | struct TransportClient *tc = cls; | ||
594 | struct ConnectInfoMessage cim; | ||
595 | |||
596 | if (GNUNET_NO == GST_neighbours_test_connected (peer)) | ||
597 | return; | ||
598 | cim.header.size = htons (sizeof(struct ConnectInfoMessage)); | ||
599 | cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); | ||
600 | cim.id = *peer; | ||
601 | cim.quota_out = bandwidth_out; | ||
602 | unicast (tc, &cim.header, GNUNET_NO); | ||
603 | } | ||
604 | |||
605 | |||
606 | /** | ||
607 | * Initialize a normal client. We got a start message from this | ||
608 | * client, add it to the list of clients for broadcasting of inbound | ||
609 | * messages. | ||
610 | * | ||
611 | * @param cls the client | ||
612 | * @param start the start message that was sent | ||
613 | */ | ||
614 | static void | ||
615 | handle_client_start (void *cls, const struct StartMessage *start) | ||
616 | { | ||
617 | struct TransportClient *tc = cls; | ||
618 | const struct GNUNET_MessageHeader *hello; | ||
619 | uint32_t options; | ||
620 | |||
621 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p sent START\n", tc); | ||
622 | options = ntohl (start->options); | ||
623 | if ((0 != (1 & options)) && | ||
624 | (0 != memcmp (&start->self, | ||
625 | &GST_my_identity, | ||
626 | sizeof(struct GNUNET_PeerIdentity)))) | ||
627 | { | ||
628 | /* client thinks this is a different peer, reject */ | ||
629 | GNUNET_break (0); | ||
630 | GNUNET_SERVICE_client_drop (tc->client); | ||
631 | return; | ||
632 | } | ||
633 | if (CT_NONE != tc->type) | ||
634 | { | ||
635 | GNUNET_break (0); | ||
636 | GNUNET_SERVICE_client_drop (tc->client); | ||
637 | return; | ||
638 | } | ||
639 | if (0 != (2 & options)) | ||
640 | tc->type = CT_CORE; | ||
641 | else | ||
642 | tc->type = CT_CORE_NO_HANDLERS; | ||
643 | hello = GST_hello_get (); | ||
644 | if (NULL != hello) | ||
645 | unicast (tc, hello, GNUNET_NO); | ||
646 | GST_neighbours_iterate (¬ify_client_about_neighbour, tc); | ||
647 | GNUNET_SERVICE_client_continue (tc->client); | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Client sent us a HELLO. Check the request. | ||
653 | * | ||
654 | * @param cls the client | ||
655 | * @param message the HELLO message | ||
656 | */ | ||
657 | static int | ||
658 | check_client_hello (void *cls, const struct GNUNET_MessageHeader *message) | ||
659 | { | ||
660 | return GNUNET_OK; /* FIXME: check here? */ | ||
661 | } | ||
662 | |||
663 | |||
664 | /** | ||
665 | * Client sent us a HELLO. Process the request. | ||
666 | * | ||
667 | * @param cls the client | ||
668 | * @param message the HELLO message | ||
669 | */ | ||
670 | static void | ||
671 | handle_client_hello (void *cls, const struct GNUNET_MessageHeader *message) | ||
672 | { | ||
673 | struct TransportClient *tc = cls; | ||
674 | |||
675 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received HELLO message\n"); | ||
676 | GST_validation_handle_hello (message); | ||
677 | GNUNET_SERVICE_client_continue (tc->client); | ||
678 | } | ||
679 | |||
680 | |||
681 | /** | ||
682 | * Function called after the transmission is done. Notify the client that it is | ||
683 | * OK to send the next message. | ||
684 | * | ||
685 | * @param cls closure | ||
686 | * @param success #GNUNET_OK on success, #GNUNET_NO on failure, #GNUNET_SYSERR if we're not connected | ||
687 | * @param bytes_payload bytes payload sent | ||
688 | * @param bytes_on_wire bytes sent on wire | ||
689 | */ | ||
690 | static void | ||
691 | handle_send_transmit_continuation (void *cls, | ||
692 | int success, | ||
693 | size_t bytes_payload, | ||
694 | size_t bytes_on_wire) | ||
695 | { | ||
696 | struct SendTransmitContinuationContext *stcc = cls; | ||
697 | struct SendOkMessage send_ok_msg; | ||
698 | #ifdef ENABLE_TTD | ||
699 | struct GNUNET_TIME_Relative delay; | ||
700 | const struct GNUNET_HELLO_Address *addr; | ||
701 | |||
702 | delay = GNUNET_TIME_absolute_get_duration (stcc->send_time); | ||
703 | addr = GST_neighbour_get_current_address (&stcc->target); | ||
704 | |||
705 | if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) | ||
706 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
707 | "It took us %s to send %u/%u bytes to %s (%d, %s)\n", | ||
708 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), | ||
709 | (unsigned int) bytes_payload, | ||
710 | (unsigned int) bytes_on_wire, | ||
711 | GNUNET_i2s (&stcc->target), | ||
712 | success, | ||
713 | (NULL != addr) ? addr->transport_name : "%"); | ||
714 | else | ||
715 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
716 | "It took us %s to send %u/%u bytes to %s (%d, %s)\n", | ||
717 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES), | ||
718 | (unsigned int) bytes_payload, | ||
719 | (unsigned int) bytes_on_wire, | ||
720 | GNUNET_i2s (&stcc->target), | ||
721 | success, | ||
722 | (NULL != addr) ? addr->transport_name : "%"); | ||
723 | #endif | ||
724 | |||
725 | if (GNUNET_NO == stcc->down) | ||
726 | { | ||
727 | /* Only send confirmation if we are still connected */ | ||
728 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
729 | "Sending SEND_OK for transmission request %llu\n", | ||
730 | stcc->uuid); | ||
731 | send_ok_msg.header.size = htons (sizeof(send_ok_msg)); | ||
732 | send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); | ||
733 | send_ok_msg.bytes_msg = htons (bytes_payload); | ||
734 | send_ok_msg.bytes_physical = htonl (bytes_on_wire); | ||
735 | send_ok_msg.success = htons (success); | ||
736 | send_ok_msg.peer = stcc->target; | ||
737 | unicast (stcc->tc, &send_ok_msg.header, GNUNET_NO); | ||
738 | } | ||
739 | GNUNET_assert ( | ||
740 | GNUNET_OK == | ||
741 | GNUNET_CONTAINER_multipeermap_remove (active_stccs, &stcc->target, stcc)); | ||
742 | GNUNET_free (stcc); | ||
743 | } | ||
744 | |||
745 | |||
746 | /** | ||
747 | * Client asked for transmission to a peer. Process the request. | ||
748 | * | ||
749 | * @param cls the client | ||
750 | * @param obm the send message that was sent | ||
751 | */ | ||
752 | static int | ||
753 | check_client_send (void *cls, const struct OutboundMessage *obm) | ||
754 | { | ||
755 | uint16_t size; | ||
756 | const struct GNUNET_MessageHeader *obmm; | ||
757 | |||
758 | size = ntohs (obm->header.size) - sizeof(struct OutboundMessage); | ||
759 | if (size < sizeof(struct GNUNET_MessageHeader)) | ||
760 | { | ||
761 | GNUNET_break (0); | ||
762 | return GNUNET_SYSERR; | ||
763 | } | ||
764 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | ||
765 | if (size != ntohs (obmm->size)) | ||
766 | { | ||
767 | GNUNET_break (0); | ||
768 | return GNUNET_SYSERR; | ||
769 | } | ||
770 | return GNUNET_OK; | ||
771 | } | ||
772 | |||
773 | |||
774 | /** | ||
775 | * Client asked for transmission to a peer. Process the request. | ||
776 | * | ||
777 | * @param cls the client | ||
778 | * @param obm the send message that was sent | ||
779 | */ | ||
780 | static void | ||
781 | handle_client_send (void *cls, const struct OutboundMessage *obm) | ||
782 | { | ||
783 | static unsigned long long uuid_gen; | ||
784 | struct TransportClient *tc = cls; | ||
785 | const struct GNUNET_MessageHeader *obmm; | ||
786 | struct SendTransmitContinuationContext *stcc; | ||
787 | |||
788 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | ||
789 | if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) | ||
790 | { | ||
791 | /* not connected, not allowed to send; can happen due to asynchronous operations */ | ||
792 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
793 | "Could not send message to peer `%s': not connected\n", | ||
794 | GNUNET_i2s (&obm->peer)); | ||
795 | GNUNET_STATISTICS_update ( | ||
796 | GST_stats, | ||
797 | gettext_noop ("# bytes payload dropped (other peer was not connected)"), | ||
798 | ntohs (obmm->size), | ||
799 | GNUNET_NO); | ||
800 | GNUNET_SERVICE_client_continue (tc->client); | ||
801 | return; | ||
802 | } | ||
803 | GNUNET_log ( | ||
804 | GNUNET_ERROR_TYPE_DEBUG, | ||
805 | "Received SEND request %llu for `%s' and first message of type %u and total size %u\n", | ||
806 | uuid_gen, | ||
807 | GNUNET_i2s (&obm->peer), | ||
808 | ntohs (obmm->type), | ||
809 | ntohs (obmm->size)); | ||
810 | GNUNET_SERVICE_client_continue (tc->client); | ||
811 | |||
812 | stcc = GNUNET_new (struct SendTransmitContinuationContext); | ||
813 | stcc->target = obm->peer; | ||
814 | stcc->tc = tc; | ||
815 | stcc->send_time = GNUNET_TIME_absolute_get (); | ||
816 | stcc->uuid = uuid_gen++; | ||
817 | (void) GNUNET_CONTAINER_multipeermap_put ( | ||
818 | active_stccs, | ||
819 | &stcc->target, | ||
820 | stcc, | ||
821 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
822 | GST_manipulation_send (&obm->peer, | ||
823 | obmm, | ||
824 | ntohs (obmm->size), | ||
825 | GNUNET_TIME_relative_ntoh (obm->timeout), | ||
826 | &handle_send_transmit_continuation, | ||
827 | stcc); | ||
828 | } | ||
829 | |||
830 | |||
831 | /** | ||
832 | * Take the given address and append it to the set of results sent back to | ||
833 | * the client. This function may be called several times for a single | ||
834 | * conversion. The last invocation will be with a @a address of | ||
835 | * NULL and a @a res of #GNUNET_OK. Thus, to indicate conversion | ||
836 | * errors, the callback might be called first with @a address NULL and | ||
837 | * @a res being #GNUNET_SYSERR. In that case, there will still be a | ||
838 | * subsequent call later with @a address NULL and @a res #GNUNET_OK. | ||
839 | * | ||
840 | * @param cls the `struct AddressToStringContext` | ||
841 | * @param buf text to transmit (contains the human-readable address, or NULL) | ||
842 | * @param res #GNUNET_OK if conversion was successful, #GNUNET_SYSERR on error, | ||
843 | * never #GNUNET_NO | ||
844 | */ | ||
845 | static void | ||
846 | transmit_address_to_client (void *cls, const char *buf, int res) | ||
847 | { | ||
848 | struct AddressToStringContext *actx = cls; | ||
849 | struct GNUNET_MQ_Envelope *env; | ||
850 | struct AddressToStringResultMessage *atsm; | ||
851 | size_t slen; | ||
852 | |||
853 | GNUNET_assert ((GNUNET_OK == res) || (GNUNET_SYSERR == res)); | ||
854 | if (NULL == actx->tc) | ||
855 | return; | ||
856 | if (NULL == buf) | ||
857 | { | ||
858 | env = GNUNET_MQ_msg (atsm, | ||
859 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
860 | if (GNUNET_OK == res) | ||
861 | { | ||
862 | /* this was the last call, transmit */ | ||
863 | atsm->res = htonl (GNUNET_OK); | ||
864 | atsm->addr_len = htonl (0); | ||
865 | GNUNET_MQ_send (actx->tc->mq, env); | ||
866 | GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx); | ||
867 | GNUNET_free (actx); | ||
868 | return; | ||
869 | } | ||
870 | if (GNUNET_SYSERR == res) | ||
871 | { | ||
872 | /* address conversion failed, but there will be more callbacks */ | ||
873 | atsm->res = htonl (GNUNET_SYSERR); | ||
874 | atsm->addr_len = htonl (0); | ||
875 | GNUNET_MQ_send (actx->tc->mq, env); | ||
876 | return; | ||
877 | } | ||
878 | } | ||
879 | GNUNET_assert (GNUNET_OK == res); | ||
880 | /* successful conversion, append*/ | ||
881 | slen = strlen (buf) + 1; | ||
882 | env = | ||
883 | GNUNET_MQ_msg_extra (atsm, | ||
884 | slen, | ||
885 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
886 | atsm->res = htonl (GNUNET_YES); | ||
887 | atsm->addr_len = htonl (slen); | ||
888 | GNUNET_memcpy (&atsm[1], buf, slen); | ||
889 | GNUNET_MQ_send (actx->tc->mq, env); | ||
890 | } | ||
891 | |||
892 | |||
893 | /** | ||
894 | * Client asked to resolve an address. Check the request. | ||
895 | * | ||
896 | * @param cls the client | ||
897 | * @param alum the resolution request | ||
898 | * @return #GNUNET_OK if @a alum is well-formed | ||
899 | */ | ||
900 | static int | ||
901 | check_client_address_to_string (void *cls, | ||
902 | const struct AddressLookupMessage *alum) | ||
903 | { | ||
904 | const char *plugin_name; | ||
905 | const char *address; | ||
906 | uint32_t address_len; | ||
907 | uint16_t size; | ||
908 | |||
909 | size = ntohs (alum->header.size); | ||
910 | address_len = ntohs (alum->addrlen); | ||
911 | if (size <= sizeof(struct AddressLookupMessage) + address_len) | ||
912 | { | ||
913 | GNUNET_break (0); | ||
914 | return GNUNET_SYSERR; | ||
915 | } | ||
916 | address = (const char *) &alum[1]; | ||
917 | plugin_name = (const char *) &address[address_len]; | ||
918 | if ('\0' != plugin_name[size - sizeof(struct AddressLookupMessage) | ||
919 | - address_len - 1]) | ||
920 | { | ||
921 | GNUNET_break (0); | ||
922 | return GNUNET_SYSERR; | ||
923 | } | ||
924 | return GNUNET_OK; | ||
925 | } | ||
926 | |||
927 | |||
928 | /** | ||
929 | * Client asked to resolve an address. Process the request. | ||
930 | * | ||
931 | * @param cls the client | ||
932 | * @param alum the resolution request | ||
933 | */ | ||
934 | static void | ||
935 | handle_client_address_to_string (void *cls, | ||
936 | const struct AddressLookupMessage *alum) | ||
937 | { | ||
938 | struct TransportClient *tc = cls; | ||
939 | struct GNUNET_TRANSPORT_PluginFunctions *papi; | ||
940 | const char *plugin_name; | ||
941 | const char *address; | ||
942 | uint32_t address_len; | ||
943 | struct AddressToStringContext *actx; | ||
944 | struct GNUNET_MQ_Envelope *env; | ||
945 | struct AddressToStringResultMessage *atsm; | ||
946 | struct GNUNET_TIME_Relative rtimeout; | ||
947 | int32_t numeric; | ||
948 | |||
949 | address_len = ntohs (alum->addrlen); | ||
950 | address = (const char *) &alum[1]; | ||
951 | plugin_name = (const char *) &address[address_len]; | ||
952 | rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout); | ||
953 | numeric = ntohs (alum->numeric_only); | ||
954 | papi = GST_plugins_printer_find (plugin_name); | ||
955 | if (NULL == papi) | ||
956 | { | ||
957 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
958 | "Failed to find plugin `%s'\n", | ||
959 | plugin_name); | ||
960 | env = GNUNET_MQ_msg (atsm, | ||
961 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
962 | atsm->res = htonl (GNUNET_SYSERR); | ||
963 | atsm->addr_len = htonl (0); | ||
964 | GNUNET_MQ_send (tc->mq, env); | ||
965 | env = GNUNET_MQ_msg (atsm, | ||
966 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
967 | atsm->res = htonl (GNUNET_OK); | ||
968 | atsm->addr_len = htonl (0); | ||
969 | GNUNET_MQ_send (tc->mq, env); | ||
970 | return; | ||
971 | } | ||
972 | actx = GNUNET_new (struct AddressToStringContext); | ||
973 | actx->tc = tc; | ||
974 | GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx); | ||
975 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
976 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
977 | "Pretty-printing address of %u bytes using plugin `%s'\n", | ||
978 | address_len, | ||
979 | plugin_name); | ||
980 | papi->address_pretty_printer (papi->cls, | ||
981 | plugin_name, | ||
982 | address, | ||
983 | address_len, | ||
984 | numeric, | ||
985 | rtimeout, | ||
986 | &transmit_address_to_client, | ||
987 | actx); | ||
988 | } | ||
989 | |||
990 | |||
991 | /** | ||
992 | * Compose #PeerIterateResponseMessage using the given peer and address. | ||
993 | * | ||
994 | * @param peer identity of the peer | ||
995 | * @param address the address, NULL on disconnect | ||
996 | * @return composed message | ||
997 | */ | ||
998 | static struct PeerIterateResponseMessage * | ||
999 | compose_address_iterate_response_message ( | ||
1000 | const struct GNUNET_PeerIdentity *peer, | ||
1001 | const struct GNUNET_HELLO_Address *address) | ||
1002 | { | ||
1003 | struct PeerIterateResponseMessage *msg; | ||
1004 | size_t size; | ||
1005 | size_t tlen; | ||
1006 | size_t alen; | ||
1007 | char *addr; | ||
1008 | |||
1009 | GNUNET_assert (NULL != peer); | ||
1010 | if (NULL != address) | ||
1011 | { | ||
1012 | tlen = strlen (address->transport_name) + 1; | ||
1013 | alen = address->address_length; | ||
1014 | } | ||
1015 | else | ||
1016 | { | ||
1017 | tlen = 0; | ||
1018 | alen = 0; | ||
1019 | } | ||
1020 | size = (sizeof(struct PeerIterateResponseMessage) + alen + tlen); | ||
1021 | msg = GNUNET_malloc (size); | ||
1022 | msg->header.size = htons (size); | ||
1023 | msg->header.type = | ||
1024 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE); | ||
1025 | msg->reserved = htonl (0); | ||
1026 | msg->peer = *peer; | ||
1027 | msg->addrlen = htonl (alen); | ||
1028 | msg->pluginlen = htonl (tlen); | ||
1029 | |||
1030 | if (NULL != address) | ||
1031 | { | ||
1032 | msg->local_address_info = htonl ((uint32_t) address->local_info); | ||
1033 | addr = (char *) &msg[1]; | ||
1034 | GNUNET_memcpy (addr, address->address, alen); | ||
1035 | GNUNET_memcpy (&addr[alen], address->transport_name, tlen); | ||
1036 | } | ||
1037 | return msg; | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | /** | ||
1042 | * Context for #send_validation_information() and | ||
1043 | * #send_peer_information(). | ||
1044 | */ | ||
1045 | struct IterationContext | ||
1046 | { | ||
1047 | /** | ||
1048 | * Context to use for the transmission. | ||
1049 | */ | ||
1050 | struct TransportClient *tc; | ||
1051 | |||
1052 | /** | ||
1053 | * Which peers do we care about? | ||
1054 | */ | ||
1055 | struct GNUNET_PeerIdentity id; | ||
1056 | |||
1057 | /** | ||
1058 | * #GNUNET_YES if @e id should be ignored because we want all peers. | ||
1059 | */ | ||
1060 | int all; | ||
1061 | }; | ||
1062 | |||
1063 | |||
1064 | /** | ||
1065 | * Output information of neighbours to the given client. | ||
1066 | * | ||
1067 | * @param cls the `struct PeerIterationContext *` | ||
1068 | * @param peer identity of the neighbour | ||
1069 | * @param address the address | ||
1070 | * @param state current state this peer is in | ||
1071 | * @param state_timeout timeout for the current state of the peer | ||
1072 | * @param bandwidth_in inbound quota in NBO | ||
1073 | * @param bandwidth_out outbound quota in NBO | ||
1074 | */ | ||
1075 | static void | ||
1076 | send_peer_information (void *cls, | ||
1077 | const struct GNUNET_PeerIdentity *peer, | ||
1078 | const struct GNUNET_HELLO_Address *address, | ||
1079 | enum GNUNET_TRANSPORT_PeerState state, | ||
1080 | struct GNUNET_TIME_Absolute state_timeout, | ||
1081 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
1082 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
1083 | { | ||
1084 | struct IterationContext *pc = cls; | ||
1085 | struct GNUNET_MQ_Envelope *env; | ||
1086 | struct PeerIterateResponseMessage *msg; | ||
1087 | |||
1088 | if ((GNUNET_YES != pc->all) && (0 != memcmp (peer, &pc->id, sizeof(pc->id)))) | ||
1089 | return; | ||
1090 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1091 | "Sending information about `%s' using address `%s' in state `%s'\n", | ||
1092 | GNUNET_i2s (peer), | ||
1093 | (NULL != address) ? GST_plugins_a2s (address) : "<none>", | ||
1094 | GNUNET_TRANSPORT_ps2s (state)); | ||
1095 | msg = compose_address_iterate_response_message (peer, address); | ||
1096 | msg->state = htonl (state); | ||
1097 | msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout); | ||
1098 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1099 | GNUNET_free (msg); | ||
1100 | GNUNET_MQ_send (pc->tc->mq, env); | ||
1101 | } | ||
1102 | |||
1103 | |||
1104 | /** | ||
1105 | * Client asked to obtain information about a specific or all peers | ||
1106 | * Process the request. | ||
1107 | * | ||
1108 | * @param cls the client | ||
1109 | * @param msg the peer address information request | ||
1110 | */ | ||
1111 | static void | ||
1112 | handle_client_monitor_peers (void *cls, const struct PeerMonitorMessage *msg) | ||
1113 | { | ||
1114 | struct TransportClient *tc = cls; | ||
1115 | struct IterationContext pc; | ||
1116 | |||
1117 | if (CT_NONE != tc->type) | ||
1118 | { | ||
1119 | GNUNET_break (0); | ||
1120 | GNUNET_SERVICE_client_drop (tc->client); | ||
1121 | return; | ||
1122 | } | ||
1123 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
1124 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
1125 | |||
1126 | /* Send initial list */ | ||
1127 | pc.tc = tc; | ||
1128 | if (0 == memcmp (&msg->peer, &all_zeros, sizeof(struct GNUNET_PeerIdentity))) | ||
1129 | { | ||
1130 | /* iterate over all neighbours */ | ||
1131 | pc.all = GNUNET_YES; | ||
1132 | pc.id = msg->peer; | ||
1133 | } | ||
1134 | else | ||
1135 | { | ||
1136 | /* just return one neighbour */ | ||
1137 | pc.all = GNUNET_NO; | ||
1138 | pc.id = msg->peer; | ||
1139 | } | ||
1140 | GST_neighbours_iterate (&send_peer_information, &pc); | ||
1141 | |||
1142 | if (GNUNET_YES != ntohl (msg->one_shot)) | ||
1143 | { | ||
1144 | tc->details.monitor_peer = msg->peer; | ||
1145 | tc->type = CT_MONITOR; | ||
1146 | if (0 != | ||
1147 | memcmp (&msg->peer, &all_zeros, sizeof(struct GNUNET_PeerIdentity))) | ||
1148 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1149 | "Client %p started monitoring of the peer `%s'\n", | ||
1150 | tc, | ||
1151 | GNUNET_i2s (&msg->peer)); | ||
1152 | else | ||
1153 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1154 | "Client %p started monitoring all peers\n", | ||
1155 | tc); | ||
1156 | } | ||
1157 | else | ||
1158 | { | ||
1159 | struct GNUNET_MessageHeader *msg; | ||
1160 | struct GNUNET_MQ_Envelope *env; | ||
1161 | |||
1162 | env = | ||
1163 | GNUNET_MQ_msg (msg, | ||
1164 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE_END); | ||
1165 | GNUNET_MQ_send (tc->mq, env); | ||
1166 | } | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1171 | * Function called by the plugin with information about the | ||
1172 | * current sessions managed by the plugin (for monitoring). | ||
1173 | * | ||
1174 | * @param cls closure | ||
1175 | * @param session session handle this information is about, | ||
1176 | * NULL to indicate that we are "in sync" (initial | ||
1177 | * iteration complete) | ||
1178 | * @param info information about the state of the session, | ||
1179 | * NULL if @a session is also NULL and we are | ||
1180 | * merely signalling that the initial iteration is over | ||
1181 | */ | ||
1182 | static void | ||
1183 | plugin_session_info_cb (void *cls, | ||
1184 | struct GNUNET_ATS_Session *session, | ||
1185 | const struct GNUNET_TRANSPORT_SessionInfo *info) | ||
1186 | { | ||
1187 | struct GNUNET_MQ_Envelope *env; | ||
1188 | struct TransportPluginMonitorMessage *msg; | ||
1189 | struct GNUNET_MessageHeader *sync; | ||
1190 | size_t size; | ||
1191 | size_t slen; | ||
1192 | uint16_t alen; | ||
1193 | char *name; | ||
1194 | char *addr; | ||
1195 | |||
1196 | if (0 == GNUNET_notification_context_get_size (plugin_nc)) | ||
1197 | { | ||
1198 | GST_plugins_monitor_subscribe (NULL, NULL); | ||
1199 | return; | ||
1200 | } | ||
1201 | if ((NULL == info) && (NULL == session)) | ||
1202 | { | ||
1203 | /* end of initial iteration */ | ||
1204 | if (NULL != sync_client) | ||
1205 | { | ||
1206 | env = | ||
1207 | GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_SYNC); | ||
1208 | GNUNET_MQ_send (sync_client->mq, env); | ||
1209 | sync_client = NULL; | ||
1210 | } | ||
1211 | return; | ||
1212 | } | ||
1213 | GNUNET_assert (NULL != info); | ||
1214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1215 | "Plugin event for peer %s on transport %s\n", | ||
1216 | GNUNET_i2s (&info->address->peer), | ||
1217 | info->address->transport_name); | ||
1218 | slen = strlen (info->address->transport_name) + 1; | ||
1219 | alen = info->address->address_length; | ||
1220 | size = sizeof(struct TransportPluginMonitorMessage) + slen + alen; | ||
1221 | if (size > UINT16_MAX) | ||
1222 | { | ||
1223 | GNUNET_break (0); | ||
1224 | return; | ||
1225 | } | ||
1226 | msg = GNUNET_malloc (size); | ||
1227 | msg->header.size = htons (size); | ||
1228 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_EVENT); | ||
1229 | msg->session_state = htons ((uint16_t) info->state); | ||
1230 | msg->is_inbound = htons ((int16_t) info->is_inbound); | ||
1231 | msg->msgs_pending = htonl (info->num_msg_pending); | ||
1232 | msg->bytes_pending = htonl (info->num_bytes_pending); | ||
1233 | msg->timeout = GNUNET_TIME_absolute_hton (info->session_timeout); | ||
1234 | msg->delay = GNUNET_TIME_absolute_hton (info->receive_delay); | ||
1235 | msg->peer = info->address->peer; | ||
1236 | msg->session_id = (uint64_t) (intptr_t) session; | ||
1237 | msg->plugin_name_len = htons (slen); | ||
1238 | msg->plugin_address_len = htons (alen); | ||
1239 | name = (char *) &msg[1]; | ||
1240 | GNUNET_memcpy (name, info->address->transport_name, slen); | ||
1241 | addr = &name[slen]; | ||
1242 | GNUNET_memcpy (addr, info->address->address, alen); | ||
1243 | if (NULL != sync_client) | ||
1244 | { | ||
1245 | struct GNUNET_MQ_Envelope *env; | ||
1246 | |||
1247 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1248 | GNUNET_MQ_send (sync_client->mq, env); | ||
1249 | } | ||
1250 | else | ||
1251 | { | ||
1252 | GNUNET_notification_context_broadcast (plugin_nc, &msg->header, GNUNET_NO); | ||
1253 | } | ||
1254 | GNUNET_free (msg); | ||
1255 | } | ||
1256 | |||
1257 | |||
1258 | /** | ||
1259 | * Client asked to obtain information about all plugin connections. | ||
1260 | * | ||
1261 | * @param cls the client | ||
1262 | * @param message the peer address information request | ||
1263 | */ | ||
1264 | static void | ||
1265 | handle_client_monitor_plugins (void *cls, | ||
1266 | const struct GNUNET_MessageHeader *message) | ||
1267 | { | ||
1268 | struct TransportClient *tc = cls; | ||
1269 | |||
1270 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
1271 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
1272 | GNUNET_notification_context_add (plugin_nc, tc->mq); | ||
1273 | GNUNET_assert (NULL == sync_client); | ||
1274 | sync_client = tc; | ||
1275 | GST_plugins_monitor_subscribe (&plugin_session_info_cb, NULL); | ||
1276 | } | ||
1277 | |||
1278 | |||
1279 | /** | ||
1280 | * Broadcast the given message to all of our clients. | ||
1281 | * | ||
1282 | * @param msg message to broadcast | ||
1283 | * @param may_drop #GNUNET_YES if the message can be dropped / is payload | ||
1284 | */ | ||
1285 | void | ||
1286 | GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop) | ||
1287 | { | ||
1288 | int done; | ||
1289 | |||
1290 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "Asked to broadcast message of type %u with %u bytes\n", | ||
1292 | (unsigned int) ntohs (msg->type), | ||
1293 | (unsigned int) ntohs (msg->size)); | ||
1294 | done = GNUNET_NO; | ||
1295 | for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next) | ||
1296 | { | ||
1297 | if (CT_NONE == tc->type) | ||
1298 | continue; /* client not yet ready */ | ||
1299 | if ((GNUNET_YES == may_drop) && (CT_CORE != tc->type)) | ||
1300 | continue; /* skip, this client does not care about payload */ | ||
1301 | unicast (tc, msg, may_drop); | ||
1302 | done = GNUNET_YES; | ||
1303 | } | ||
1304 | if (GNUNET_NO == done) | ||
1305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1306 | "Message of type %u not delivered, is CORE service up?\n", | ||
1307 | ntohs (msg->type)); | ||
1308 | } | ||
1309 | |||
1310 | |||
1311 | /** | ||
1312 | * Broadcast the new active address to all clients monitoring the peer. | ||
1313 | * | ||
1314 | * @param peer peer this update is about (never NULL) | ||
1315 | * @param address address, NULL on disconnect | ||
1316 | * @param state the current state of the peer | ||
1317 | * @param state_timeout the time out for the state | ||
1318 | */ | ||
1319 | void | ||
1320 | GST_clients_broadcast_peer_notification ( | ||
1321 | const struct GNUNET_PeerIdentity *peer, | ||
1322 | const struct GNUNET_HELLO_Address *address, | ||
1323 | enum GNUNET_TRANSPORT_PeerState state, | ||
1324 | struct GNUNET_TIME_Absolute state_timeout) | ||
1325 | { | ||
1326 | struct GNUNET_MQ_Envelope *env; | ||
1327 | struct PeerIterateResponseMessage *msg; | ||
1328 | |||
1329 | msg = compose_address_iterate_response_message (peer, address); | ||
1330 | msg->state = htonl (state); | ||
1331 | msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout); | ||
1332 | for (struct TransportClient *tc = clients_head; NULL != tc; tc = tc->next) | ||
1333 | { | ||
1334 | if (CT_MONITOR != tc->type) | ||
1335 | continue; | ||
1336 | if ((0 == memcmp (&tc->details.monitor_peer, | ||
1337 | &all_zeros, | ||
1338 | sizeof(struct GNUNET_PeerIdentity))) || | ||
1339 | (0 == memcmp (&tc->details.monitor_peer, | ||
1340 | peer, | ||
1341 | sizeof(struct GNUNET_PeerIdentity)))) | ||
1342 | { | ||
1343 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1344 | GNUNET_MQ_send (tc->mq, env); | ||
1345 | } | ||
1346 | } | ||
1347 | GNUNET_free (msg); | ||
1348 | } | ||
1349 | |||
1350 | |||
1351 | /** | ||
1352 | * Mark the peer as down so we don't call the continuation | ||
1353 | * context in the future. | ||
1354 | * | ||
1355 | * @param cls NULL | ||
1356 | * @param peer peer that got disconnected | ||
1357 | * @param value a `struct SendTransmitContinuationContext` to mark | ||
1358 | * @return #GNUNET_OK (continue to iterate) | ||
1359 | */ | ||
1360 | static int | ||
1361 | mark_peer_down (void *cls, const struct GNUNET_PeerIdentity *peer, void *value) | ||
1362 | { | ||
1363 | struct SendTransmitContinuationContext *stcc = value; | ||
1364 | |||
1365 | stcc->down = GNUNET_YES; | ||
1366 | return GNUNET_OK; | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * Notify all clients about a disconnect, and cancel | ||
1372 | * pending SEND_OK messages for this peer. | ||
1373 | * | ||
1374 | * @param peer peer that disconnected | ||
1375 | */ | ||
1376 | void | ||
1377 | GST_clients_broadcast_disconnect (const struct GNUNET_PeerIdentity *peer) | ||
1378 | { | ||
1379 | struct DisconnectInfoMessage disconnect_msg; | ||
1380 | |||
1381 | GNUNET_CONTAINER_multipeermap_get_multiple (active_stccs, | ||
1382 | peer, | ||
1383 | &mark_peer_down, | ||
1384 | NULL); | ||
1385 | disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage)); | ||
1386 | disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT); | ||
1387 | disconnect_msg.reserved = htonl (0); | ||
1388 | disconnect_msg.peer = *peer; | ||
1389 | GST_clients_broadcast (&disconnect_msg.header, GNUNET_NO); | ||
1390 | } | ||
1391 | |||
1392 | |||
1393 | /** | ||
1394 | * Transmit our HELLO message to the given (connected) neighbour. | ||
1395 | * | ||
1396 | * @param cls the 'HELLO' message | ||
1397 | * @param peer identity of the peer | ||
1398 | * @param address the address | ||
1399 | * @param state current state this peer is in | ||
1400 | * @param state_timeout timeout for the current state of the peer | ||
1401 | * @param bandwidth_in inbound quota in NBO | ||
1402 | * @param bandwidth_out outbound quota in NBO | ||
1403 | */ | ||
1404 | static void | ||
1405 | transmit_our_hello (void *cls, | ||
1406 | const struct GNUNET_PeerIdentity *peer, | ||
1407 | const struct GNUNET_HELLO_Address *address, | ||
1408 | enum GNUNET_TRANSPORT_PeerState state, | ||
1409 | struct GNUNET_TIME_Absolute state_timeout, | ||
1410 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
1411 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
1412 | { | ||
1413 | const struct GNUNET_MessageHeader *hello = cls; | ||
1414 | |||
1415 | if (0 == memcmp (peer, &GST_my_identity, sizeof(struct GNUNET_PeerIdentity))) | ||
1416 | return; /* not to ourselves */ | ||
1417 | if (GNUNET_NO == GST_neighbours_test_connected (peer)) | ||
1418 | return; | ||
1419 | |||
1420 | GST_neighbours_send (peer, | ||
1421 | hello, | ||
1422 | ntohs (hello->size), | ||
1423 | hello_expiration, | ||
1424 | NULL, | ||
1425 | NULL); | ||
1426 | } | ||
1427 | |||
1428 | |||
1429 | /** | ||
1430 | * My HELLO has changed. Tell everyone who should know. | ||
1431 | * | ||
1432 | * @param cls unused | ||
1433 | * @param hello new HELLO | ||
1434 | */ | ||
1435 | static void | ||
1436 | process_hello_update (void *cls, const struct GNUNET_MessageHeader *hello) | ||
1437 | { | ||
1438 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Broadcasting HELLO to clients\n"); | ||
1439 | GST_clients_broadcast (hello, GNUNET_NO); | ||
1440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Broadcasting HELLO to neighbours\n"); | ||
1441 | GST_neighbours_iterate (&transmit_our_hello, (void *) hello); | ||
1442 | } | ||
1443 | |||
1444 | |||
1445 | /** | ||
1446 | * We received some payload. Prepare to pass it on to our clients. | ||
1447 | * | ||
1448 | * @param address address and (claimed) identity of the other peer | ||
1449 | * @param session identifier used for this session (NULL for plugins | ||
1450 | * that do not offer bi-directional communication to the sender | ||
1451 | * using the same "connection") | ||
1452 | * @param message the message to process | ||
1453 | * @return how long the plugin should wait until receiving more data | ||
1454 | */ | ||
1455 | static struct GNUNET_TIME_Relative | ||
1456 | process_payload (const struct GNUNET_HELLO_Address *address, | ||
1457 | struct GNUNET_ATS_Session *session, | ||
1458 | const struct GNUNET_MessageHeader *message) | ||
1459 | { | ||
1460 | struct GNUNET_TIME_Relative ret; | ||
1461 | int do_forward; | ||
1462 | struct InboundMessage *im; | ||
1463 | size_t msg_size = ntohs (message->size); | ||
1464 | size_t size = sizeof(struct InboundMessage) + msg_size; | ||
1465 | char buf[size] GNUNET_ALIGN; | ||
1466 | |||
1467 | do_forward = GNUNET_SYSERR; | ||
1468 | ret = GST_neighbours_calculate_receive_delay (&address->peer, | ||
1469 | msg_size, | ||
1470 | &do_forward); | ||
1471 | if (! GST_neighbours_test_connected (&address->peer)) | ||
1472 | { | ||
1473 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1474 | "Discarded %u bytes type %u payload from peer `%s'\n", | ||
1475 | (unsigned int) msg_size, | ||
1476 | ntohs (message->type), | ||
1477 | GNUNET_i2s (&address->peer)); | ||
1478 | GNUNET_STATISTICS_update ( | ||
1479 | GST_stats, | ||
1480 | gettext_noop ("# bytes payload discarded due to not connected peer"), | ||
1481 | msg_size, | ||
1482 | GNUNET_NO); | ||
1483 | return ret; | ||
1484 | } | ||
1485 | |||
1486 | if (GNUNET_YES != do_forward) | ||
1487 | return ret; | ||
1488 | im = (struct InboundMessage *) buf; | ||
1489 | im->header.size = htons (size); | ||
1490 | im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); | ||
1491 | im->peer = address->peer; | ||
1492 | GNUNET_memcpy (&im[1], message, ntohs (message->size)); | ||
1493 | GST_clients_broadcast (&im->header, GNUNET_YES); | ||
1494 | return ret; | ||
1495 | } | ||
1496 | |||
1497 | |||
1498 | /** | ||
1499 | * Task to asynchronously terminate a session. | ||
1500 | * | ||
1501 | * @param cls the `struct GNUNET_ATS_SessionKiller` with the information for the kill | ||
1502 | */ | ||
1503 | static void | ||
1504 | kill_session_task (void *cls) | ||
1505 | { | ||
1506 | struct GNUNET_ATS_SessionKiller *sk = cls; | ||
1507 | |||
1508 | sk->task = NULL; | ||
1509 | GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk); | ||
1510 | sk->plugin->disconnect_session (sk->plugin->cls, sk->session); | ||
1511 | GNUNET_free (sk); | ||
1512 | } | ||
1513 | |||
1514 | |||
1515 | /** | ||
1516 | * Force plugin to terminate session due to communication | ||
1517 | * issue. | ||
1518 | * | ||
1519 | * @param plugin_name name of the plugin | ||
1520 | * @param session session to termiante | ||
1521 | */ | ||
1522 | static void | ||
1523 | kill_session (const char *plugin_name, struct GNUNET_ATS_Session *session) | ||
1524 | { | ||
1525 | struct GNUNET_TRANSPORT_PluginFunctions *plugin; | ||
1526 | struct GNUNET_ATS_SessionKiller *sk; | ||
1527 | |||
1528 | for (sk = sk_head; NULL != sk; sk = sk->next) | ||
1529 | if (sk->session == session) | ||
1530 | return; | ||
1531 | plugin = GST_plugins_find (plugin_name); | ||
1532 | if (NULL == plugin) | ||
1533 | { | ||
1534 | GNUNET_break (0); | ||
1535 | return; | ||
1536 | } | ||
1537 | /* need to issue disconnect asynchronously */ | ||
1538 | sk = GNUNET_new (struct GNUNET_ATS_SessionKiller); | ||
1539 | sk->session = session; | ||
1540 | sk->plugin = plugin; | ||
1541 | sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, sk); | ||
1542 | GNUNET_CONTAINER_DLL_insert (sk_head, sk_tail, sk); | ||
1543 | } | ||
1544 | |||
1545 | |||
1546 | /** | ||
1547 | * Black list check result for try_connect call | ||
1548 | * If connection to the peer is allowed request address and ??? | ||
1549 | * | ||
1550 | * @param cls the message | ||
1551 | * @param peer the peer | ||
1552 | * @param address the address | ||
1553 | * @param session the session | ||
1554 | * @param result the result | ||
1555 | */ | ||
1556 | static void | ||
1557 | connect_bl_check_cont (void *cls, | ||
1558 | const struct GNUNET_PeerIdentity *peer, | ||
1559 | const struct GNUNET_HELLO_Address *address, | ||
1560 | struct GNUNET_ATS_Session *session, | ||
1561 | int result) | ||
1562 | { | ||
1563 | struct GNUNET_MessageHeader *msg = cls; | ||
1564 | |||
1565 | if (GNUNET_OK == result) | ||
1566 | { | ||
1567 | /* Blacklist allows to speak to this peer, forward SYN to neighbours */ | ||
1568 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1569 | "Received SYN message from peer `%s' at `%s'\n", | ||
1570 | GNUNET_i2s (peer), | ||
1571 | GST_plugins_a2s (address)); | ||
1572 | if (GNUNET_OK != GST_neighbours_handle_session_syn (msg, peer)) | ||
1573 | { | ||
1574 | GST_blacklist_abort_matching (address, session); | ||
1575 | kill_session (address->transport_name, session); | ||
1576 | } | ||
1577 | GNUNET_free (msg); | ||
1578 | return; | ||
1579 | } | ||
1580 | GNUNET_free (msg); | ||
1581 | if (GNUNET_SYSERR == result) | ||
1582 | return; /* check was aborted, session destroyed */ | ||
1583 | /* Blacklist denies to speak to this peer */ | ||
1584 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1585 | "Discarding SYN message from `%s' due to denied blacklist check\n", | ||
1586 | GNUNET_i2s (peer)); | ||
1587 | kill_session (address->transport_name, session); | ||
1588 | } | ||
1589 | |||
1590 | |||
1591 | /** | ||
1592 | * Function called by the transport for each received message. | ||
1593 | * | ||
1594 | * @param cls closure, const char* with the name of the plugin we received the message from | ||
1595 | * @param address address and (claimed) identity of the other peer | ||
1596 | * @param message the message, NULL if we only care about | ||
1597 | * learning about the delay until we should receive again | ||
1598 | * @param session identifier used for this session (NULL for plugins | ||
1599 | * that do not offer bi-directional communication to the sender | ||
1600 | * using the same "connection") | ||
1601 | * @return how long the plugin should wait until receiving more data | ||
1602 | * (plugins that do not support this, can ignore the return value) | ||
1603 | */ | ||
1604 | struct GNUNET_TIME_Relative | ||
1605 | GST_receive_callback (void *cls, | ||
1606 | const struct GNUNET_HELLO_Address *address, | ||
1607 | struct GNUNET_ATS_Session *session, | ||
1608 | const struct GNUNET_MessageHeader *message) | ||
1609 | { | ||
1610 | const char *plugin_name = cls; | ||
1611 | struct GNUNET_TIME_Relative ret; | ||
1612 | uint16_t type; | ||
1613 | |||
1614 | ret = GNUNET_TIME_UNIT_ZERO; | ||
1615 | if (NULL == message) | ||
1616 | goto end; | ||
1617 | type = ntohs (message->type); | ||
1618 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1619 | "Received message with type %u from peer `%s' at %s\n", | ||
1620 | type, | ||
1621 | GNUNET_i2s (&address->peer), | ||
1622 | GST_plugins_a2s (address)); | ||
1623 | |||
1624 | GNUNET_STATISTICS_update (GST_stats, | ||
1625 | gettext_noop ("# bytes total received"), | ||
1626 | ntohs (message->size), | ||
1627 | GNUNET_NO); | ||
1628 | GST_neighbours_notify_data_recv (address, message); | ||
1629 | switch (type) | ||
1630 | { | ||
1631 | case GNUNET_MESSAGE_TYPE_HELLO_URI: | ||
1632 | /* Future HELLO message, discard */ | ||
1633 | return ret; | ||
1634 | |||
1635 | case GNUNET_MESSAGE_TYPE_HELLO: | ||
1636 | if (GNUNET_OK != GST_validation_handle_hello (message)) | ||
1637 | { | ||
1638 | GNUNET_break_op (0); | ||
1639 | GST_blacklist_abort_matching (address, session); | ||
1640 | } | ||
1641 | return ret; | ||
1642 | |||
1643 | case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: | ||
1644 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1645 | "Processing PING from `%s'\n", | ||
1646 | GST_plugins_a2s (address)); | ||
1647 | if (GNUNET_OK != | ||
1648 | GST_validation_handle_ping (&address->peer, message, address, session)) | ||
1649 | { | ||
1650 | GST_blacklist_abort_matching (address, session); | ||
1651 | kill_session (plugin_name, session); | ||
1652 | } | ||
1653 | break; | ||
1654 | |||
1655 | case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: | ||
1656 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1657 | "Processing PONG from `%s'\n", | ||
1658 | GST_plugins_a2s (address)); | ||
1659 | if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message)) | ||
1660 | { | ||
1661 | GNUNET_break_op (0); | ||
1662 | GST_blacklist_abort_matching (address, session); | ||
1663 | kill_session (plugin_name, session); | ||
1664 | } | ||
1665 | break; | ||
1666 | |||
1667 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN: | ||
1668 | /* Do blacklist check if communication with this peer is allowed */ | ||
1669 | (void) GST_blacklist_test_allowed (&address->peer, | ||
1670 | NULL, | ||
1671 | &connect_bl_check_cont, | ||
1672 | GNUNET_copy_message (message), | ||
1673 | address, | ||
1674 | session); | ||
1675 | break; | ||
1676 | |||
1677 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK: | ||
1678 | if (GNUNET_OK != | ||
1679 | GST_neighbours_handle_session_syn_ack (message, address, session)) | ||
1680 | { | ||
1681 | GST_blacklist_abort_matching (address, session); | ||
1682 | kill_session (plugin_name, session); | ||
1683 | } | ||
1684 | break; | ||
1685 | |||
1686 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: | ||
1687 | if (GNUNET_OK != | ||
1688 | GST_neighbours_handle_session_ack (message, address, session)) | ||
1689 | { | ||
1690 | GNUNET_break_op (0); | ||
1691 | GST_blacklist_abort_matching (address, session); | ||
1692 | kill_session (plugin_name, session); | ||
1693 | } | ||
1694 | break; | ||
1695 | |||
1696 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: | ||
1697 | GST_neighbours_handle_disconnect_message (&address->peer, message); | ||
1698 | break; | ||
1699 | |||
1700 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA: | ||
1701 | GST_neighbours_handle_quota_message (&address->peer, message); | ||
1702 | break; | ||
1703 | |||
1704 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE: | ||
1705 | GST_neighbours_keepalive (&address->peer, message); | ||
1706 | break; | ||
1707 | |||
1708 | case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE: | ||
1709 | GST_neighbours_keepalive_response (&address->peer, message); | ||
1710 | break; | ||
1711 | |||
1712 | default: | ||
1713 | /* should be payload */ | ||
1714 | GNUNET_STATISTICS_update (GST_stats, | ||
1715 | gettext_noop ("# bytes payload received"), | ||
1716 | ntohs (message->size), | ||
1717 | GNUNET_NO); | ||
1718 | ret = process_payload (address, session, message); | ||
1719 | break; | ||
1720 | } | ||
1721 | end: | ||
1722 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1723 | "Allowing receive from peer %s to continue in %s\n", | ||
1724 | GNUNET_i2s (&address->peer), | ||
1725 | GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); | ||
1726 | return ret; | ||
1727 | } | ||
1728 | |||
1729 | |||
1730 | /** | ||
1731 | * Function that will be called for each address the transport | ||
1732 | * is aware that it might be reachable under. Update our HELLO. | ||
1733 | * | ||
1734 | * @param cls name of the plugin (const char*) | ||
1735 | * @param add_remove should the address added (YES) or removed (NO) from the | ||
1736 | * set of valid addresses? | ||
1737 | * @param address the address to add or remove | ||
1738 | */ | ||
1739 | static void | ||
1740 | plugin_env_address_change_notification ( | ||
1741 | void *cls, | ||
1742 | int add_remove, | ||
1743 | const struct GNUNET_HELLO_Address *address) | ||
1744 | { | ||
1745 | static int addresses = 0; | ||
1746 | |||
1747 | if (GNUNET_YES == add_remove) | ||
1748 | { | ||
1749 | addresses++; | ||
1750 | GNUNET_STATISTICS_update (GST_stats, "# transport addresses", 1, GNUNET_NO); | ||
1751 | } | ||
1752 | else if (GNUNET_NO == add_remove) | ||
1753 | { | ||
1754 | if (0 == addresses) | ||
1755 | { | ||
1756 | GNUNET_break (0); | ||
1757 | } | ||
1758 | else | ||
1759 | { | ||
1760 | addresses--; | ||
1761 | GNUNET_STATISTICS_update (GST_stats, | ||
1762 | "# transport addresses", | ||
1763 | -1, | ||
1764 | GNUNET_NO); | ||
1765 | } | ||
1766 | } | ||
1767 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1768 | "Transport now has %u addresses to communicate\n", | ||
1769 | addresses); | ||
1770 | GST_hello_modify_addresses (add_remove, address); | ||
1771 | } | ||
1772 | |||
1773 | |||
1774 | /** | ||
1775 | * Function that will be called whenever the plugin internally | ||
1776 | * cleans up a session pointer and hence the service needs to | ||
1777 | * discard all of those sessions as well. Plugins that do not | ||
1778 | * use sessions can simply omit calling this function and always | ||
1779 | * use NULL wherever a session pointer is needed. This function | ||
1780 | * should be called BEFORE a potential "TransmitContinuation" | ||
1781 | * from the "TransmitFunction". | ||
1782 | * | ||
1783 | * @param cls closure | ||
1784 | * @param address which address was the session for | ||
1785 | * @param session which session is being destroyed | ||
1786 | */ | ||
1787 | static void | ||
1788 | plugin_env_session_end (void *cls, | ||
1789 | const struct GNUNET_HELLO_Address *address, | ||
1790 | struct GNUNET_ATS_Session *session) | ||
1791 | { | ||
1792 | struct GNUNET_ATS_SessionKiller *sk; | ||
1793 | |||
1794 | if (NULL == address) | ||
1795 | { | ||
1796 | GNUNET_break (0); | ||
1797 | return; | ||
1798 | } | ||
1799 | if (NULL == session) | ||
1800 | { | ||
1801 | GNUNET_break (0); | ||
1802 | return; | ||
1803 | } | ||
1804 | GNUNET_assert (strlen (address->transport_name) > 0); | ||
1805 | |||
1806 | GNUNET_log ( | ||
1807 | GNUNET_ERROR_TYPE_DEBUG, | ||
1808 | "Notification from plugin about terminated session %p from peer `%s' address `%s'\n", | ||
1809 | session, | ||
1810 | GNUNET_i2s (&address->peer), | ||
1811 | GST_plugins_a2s (address)); | ||
1812 | |||
1813 | GST_neighbours_session_terminated (&address->peer, session); | ||
1814 | GST_ats_del_session (address, session); | ||
1815 | GST_blacklist_abort_matching (address, session); | ||
1816 | |||
1817 | for (sk = sk_head; NULL != sk; sk = sk->next) | ||
1818 | { | ||
1819 | if (sk->session == session) | ||
1820 | { | ||
1821 | GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk); | ||
1822 | GNUNET_SCHEDULER_cancel (sk->task); | ||
1823 | GNUNET_free (sk); | ||
1824 | break; | ||
1825 | } | ||
1826 | } | ||
1827 | } | ||
1828 | |||
1829 | |||
1830 | /** | ||
1831 | * Black list check result from blacklist check triggered when a | ||
1832 | * plugin gave us a new session in #plugin_env_session_start(). If | ||
1833 | * connection to the peer is disallowed, kill the session. | ||
1834 | * | ||
1835 | * @param cls NULL | ||
1836 | * @param peer the peer | ||
1837 | * @param address address associated with the request | ||
1838 | * @param session session associated with the request | ||
1839 | * @param result the result | ||
1840 | */ | ||
1841 | static void | ||
1842 | plugin_env_session_start_bl_check_cont ( | ||
1843 | void *cls, | ||
1844 | const struct GNUNET_PeerIdentity *peer, | ||
1845 | const struct GNUNET_HELLO_Address *address, | ||
1846 | struct GNUNET_ATS_Session *session, | ||
1847 | int result) | ||
1848 | { | ||
1849 | if (GNUNET_OK != result) | ||
1850 | { | ||
1851 | kill_session (address->transport_name, session); | ||
1852 | return; | ||
1853 | } | ||
1854 | if (GNUNET_YES != | ||
1855 | GNUNET_HELLO_address_check_option (address, | ||
1856 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | ||
1857 | { | ||
1858 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1859 | "Informing verifier about inbound session's address `%s'\n", | ||
1860 | GST_plugins_a2s (address)); | ||
1861 | GST_validation_handle_address (address); | ||
1862 | } | ||
1863 | } | ||
1864 | |||
1865 | |||
1866 | /** | ||
1867 | * Plugin tells transport service about a new inbound session | ||
1868 | * | ||
1869 | * @param cls unused | ||
1870 | * @param address the address | ||
1871 | * @param session the new session | ||
1872 | * @param scope network scope information | ||
1873 | */ | ||
1874 | static void | ||
1875 | plugin_env_session_start (void *cls, | ||
1876 | const struct GNUNET_HELLO_Address *address, | ||
1877 | struct GNUNET_ATS_Session *session, | ||
1878 | enum GNUNET_NetworkType scope) | ||
1879 | { | ||
1880 | struct GNUNET_ATS_Properties prop; | ||
1881 | |||
1882 | if (NULL == address) | ||
1883 | { | ||
1884 | GNUNET_break (0); | ||
1885 | return; | ||
1886 | } | ||
1887 | if (NULL == session) | ||
1888 | { | ||
1889 | GNUNET_break (0); | ||
1890 | return; | ||
1891 | } | ||
1892 | GNUNET_log ( | ||
1893 | GNUNET_ERROR_TYPE_INFO, | ||
1894 | "Notification from plugin `%s' about new session from peer `%s' address `%s'\n", | ||
1895 | address->transport_name, | ||
1896 | GNUNET_i2s (&address->peer), | ||
1897 | GST_plugins_a2s (address)); | ||
1898 | if (GNUNET_YES == | ||
1899 | GNUNET_HELLO_address_check_option (address, | ||
1900 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | ||
1901 | { | ||
1902 | /* inbound is always new, but outbound MAY already be known, but | ||
1903 | for example for UNIX, we have symmetric connections and thus we | ||
1904 | may not know the address yet; add if necessary! */ | ||
1905 | /* FIXME: maybe change API here so we just pass scope? */ | ||
1906 | memset (&prop, 0, sizeof(prop)); | ||
1907 | GNUNET_break (GNUNET_NT_UNSPECIFIED != scope); | ||
1908 | prop.scope = scope; | ||
1909 | GST_ats_add_inbound_address (address, session, &prop); | ||
1910 | } | ||
1911 | /* Do blacklist check if communication with this peer is allowed */ | ||
1912 | (void) GST_blacklist_test_allowed (&address->peer, | ||
1913 | address->transport_name, | ||
1914 | &plugin_env_session_start_bl_check_cont, | ||
1915 | NULL, | ||
1916 | address, | ||
1917 | session); | ||
1918 | } | ||
1919 | |||
1920 | |||
1921 | /** | ||
1922 | * Function called by ATS to notify the callee that the | ||
1923 | * assigned bandwidth or address for a given peer was changed. If the | ||
1924 | * callback is called with address/bandwidth assignments of zero, the | ||
1925 | * ATS disconnect function will still be called once the disconnect | ||
1926 | * actually happened. | ||
1927 | * | ||
1928 | * @param cls closure | ||
1929 | * @param peer the peer this address is intended for | ||
1930 | * @param address address to use (for peer given in address) | ||
1931 | * @param session session to use (if available) | ||
1932 | * @param bandwidth_out assigned outbound bandwidth for the connection in NBO, | ||
1933 | * 0 to disconnect from peer | ||
1934 | * @param bandwidth_in assigned inbound bandwidth for the connection in NBO, | ||
1935 | * 0 to disconnect from peer | ||
1936 | * @param ats ATS information | ||
1937 | * @param ats_count number of @a ats elements | ||
1938 | */ | ||
1939 | static void | ||
1940 | ats_request_address_change (void *cls, | ||
1941 | const struct GNUNET_PeerIdentity *peer, | ||
1942 | const struct GNUNET_HELLO_Address *address, | ||
1943 | struct GNUNET_ATS_Session *session, | ||
1944 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
1945 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in) | ||
1946 | { | ||
1947 | uint32_t bw_in = ntohl (bandwidth_in.value__); | ||
1948 | uint32_t bw_out = ntohl (bandwidth_out.value__); | ||
1949 | |||
1950 | if (NULL == peer) | ||
1951 | { | ||
1952 | /* ATS service died, all suggestions become invalid! | ||
1953 | (but we'll keep using the allocations for a little | ||
1954 | while, to keep going while ATS restarts) */ | ||
1955 | /* FIXME: We should drop all | ||
1956 | connections now, as ATS won't explicitly tell | ||
1957 | us and be unaware of ongoing resource allocations! */ | ||
1958 | return; | ||
1959 | } | ||
1960 | /* ATS tells me to disconnect from peer */ | ||
1961 | if ((0 == bw_in) && (0 == bw_out)) | ||
1962 | { | ||
1963 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1964 | "ATS tells me to disconnect from peer `%s'\n", | ||
1965 | GNUNET_i2s (peer)); | ||
1966 | GST_neighbours_force_disconnect (peer); | ||
1967 | return; | ||
1968 | } | ||
1969 | GNUNET_assert (NULL != address); | ||
1970 | GNUNET_STATISTICS_update (GST_stats, | ||
1971 | "# ATS suggestions received", | ||
1972 | 1, | ||
1973 | GNUNET_NO); | ||
1974 | GST_neighbours_switch_to_address (address, | ||
1975 | session, | ||
1976 | bandwidth_in, | ||
1977 | bandwidth_out); | ||
1978 | } | ||
1979 | |||
1980 | |||
1981 | /** | ||
1982 | * Closure for #test_connection_ok(). | ||
1983 | */ | ||
1984 | struct TestConnectionContext | ||
1985 | { | ||
1986 | /** | ||
1987 | * Is this the first neighbour we're checking? | ||
1988 | */ | ||
1989 | int first; | ||
1990 | |||
1991 | /** | ||
1992 | * Handle to the blacklisting client we need to ask. | ||
1993 | */ | ||
1994 | struct TransportClient *tc; | ||
1995 | }; | ||
1996 | |||
1997 | |||
1998 | /** | ||
1999 | * Got the result about an existing connection from a new blacklister. | ||
2000 | * Shutdown the neighbour if necessary. | ||
2001 | * | ||
2002 | * @param cls unused | ||
2003 | * @param peer the neighbour that was investigated | ||
2004 | * @param address address associated with the request | ||
2005 | * @param session session associated with the request | ||
2006 | * @param allowed #GNUNET_OK if we can keep it, | ||
2007 | * #GNUNET_NO if we must shutdown the connection | ||
2008 | */ | ||
2009 | static void | ||
2010 | confirm_or_drop_neighbour (void *cls, | ||
2011 | const struct GNUNET_PeerIdentity *peer, | ||
2012 | const struct GNUNET_HELLO_Address *address, | ||
2013 | struct GNUNET_ATS_Session *session, | ||
2014 | int allowed) | ||
2015 | { | ||
2016 | if (GNUNET_OK == allowed) | ||
2017 | return; /* we're done */ | ||
2018 | GNUNET_STATISTICS_update (GST_stats, | ||
2019 | gettext_noop ("# disconnects due to blacklist"), | ||
2020 | 1, | ||
2021 | GNUNET_NO); | ||
2022 | GST_neighbours_force_disconnect (peer); | ||
2023 | } | ||
2024 | |||
2025 | |||
2026 | /** | ||
2027 | * Test if an existing connection is still acceptable given a new | ||
2028 | * blacklisting client. | ||
2029 | * | ||
2030 | * @param cls the `struct TestConnectionContext *` | ||
2031 | * @param peer identity of the peer | ||
2032 | * @param address the address | ||
2033 | * @param state current state this peer is in | ||
2034 | * @param state_timeout timeout for the current state of the peer | ||
2035 | * @param bandwidth_in bandwidth assigned inbound | ||
2036 | * @param bandwidth_out bandwidth assigned outbound | ||
2037 | */ | ||
2038 | static void | ||
2039 | test_connection_ok (void *cls, | ||
2040 | const struct GNUNET_PeerIdentity *peer, | ||
2041 | const struct GNUNET_HELLO_Address *address, | ||
2042 | enum GNUNET_TRANSPORT_PeerState state, | ||
2043 | struct GNUNET_TIME_Absolute state_timeout, | ||
2044 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
2045 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
2046 | { | ||
2047 | struct TestConnectionContext *tcc = cls; | ||
2048 | struct GST_BlacklistCheck *bc; | ||
2049 | |||
2050 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
2051 | GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); | ||
2052 | bc->peer = *peer; | ||
2053 | bc->address = GNUNET_HELLO_address_copy (address); | ||
2054 | bc->cont = &confirm_or_drop_neighbour; | ||
2055 | bc->cont_cls = NULL; | ||
2056 | bc->bl_pos = tcc->tc; | ||
2057 | if (GNUNET_YES == tcc->first) | ||
2058 | { | ||
2059 | /* all would wait for the same client, no need to | ||
2060 | * create more than just the first task right now */ | ||
2061 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
2062 | tcc->first = GNUNET_NO; | ||
2063 | } | ||
2064 | } | ||
2065 | |||
2066 | |||
2067 | /** | ||
2068 | * Initialize a blacklisting client. We got a blacklist-init | ||
2069 | * message from this client, add it to the list of clients | ||
2070 | * to query for blacklisting. | ||
2071 | * | ||
2072 | * @param cls the client | ||
2073 | * @param message the blacklist-init message that was sent | ||
2074 | */ | ||
2075 | static void | ||
2076 | handle_client_blacklist_init (void *cls, | ||
2077 | const struct GNUNET_MessageHeader *message) | ||
2078 | { | ||
2079 | struct TransportClient *tc = cls; | ||
2080 | struct TestConnectionContext tcc; | ||
2081 | |||
2082 | if (CT_NONE != tc->type) | ||
2083 | { | ||
2084 | GNUNET_break (0); | ||
2085 | GNUNET_SERVICE_client_drop (tc->client); | ||
2086 | return; | ||
2087 | } | ||
2088 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
2089 | tc->type = CT_BLACKLIST; | ||
2090 | tc->details.blacklist.call_receive_done = GNUNET_YES; | ||
2091 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New blacklist client %p\n", tc); | ||
2092 | /* confirm that all existing connections are OK! */ | ||
2093 | tcc.tc = tc; | ||
2094 | tcc.first = GNUNET_YES; | ||
2095 | GST_neighbours_iterate (&test_connection_ok, &tcc); | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | /** | ||
2100 | * Free the given entry in the blacklist. | ||
2101 | * | ||
2102 | * @param cls unused | ||
2103 | * @param key host identity (unused) | ||
2104 | * @param value the blacklist entry | ||
2105 | * @return #GNUNET_OK (continue to iterate) | ||
2106 | */ | ||
2107 | static int | ||
2108 | free_blacklist_entry (void *cls, | ||
2109 | const struct GNUNET_PeerIdentity *key, | ||
2110 | void *value) | ||
2111 | { | ||
2112 | char *be = value; | ||
2113 | |||
2114 | GNUNET_free (be); | ||
2115 | return GNUNET_OK; | ||
2116 | } | ||
2117 | |||
2118 | |||
2119 | /** | ||
2120 | * Set traffic metric to manipulate | ||
2121 | * | ||
2122 | * @param cls closure | ||
2123 | * @param message containing information | ||
2124 | */ | ||
2125 | static void | ||
2126 | handle_client_set_metric (void *cls, const struct TrafficMetricMessage *tm) | ||
2127 | { | ||
2128 | struct TransportClient *tc = cls; | ||
2129 | |||
2130 | GST_manipulation_set_metric (tm); | ||
2131 | GNUNET_SERVICE_client_continue (tc->client); | ||
2132 | } | ||
2133 | |||
2134 | |||
2135 | /** | ||
2136 | * Function called when the service shuts down. Unloads our plugins | ||
2137 | * and cancels pending validations. | ||
2138 | * | ||
2139 | * @param cls closure, unused | ||
2140 | */ | ||
2141 | static void | ||
2142 | shutdown_task (void *cls) | ||
2143 | { | ||
2144 | struct AddressToStringContext *cur; | ||
2145 | |||
2146 | GST_neighbours_stop (); | ||
2147 | GST_plugins_unload (); | ||
2148 | GST_validation_stop (); | ||
2149 | GST_ats_done (); | ||
2150 | GNUNET_ATS_scheduling_done (GST_ats); | ||
2151 | GST_ats = NULL; | ||
2152 | GNUNET_ATS_connectivity_done (GST_ats_connect); | ||
2153 | GST_ats_connect = NULL; | ||
2154 | GNUNET_NT_scanner_done (GST_is); | ||
2155 | GST_is = NULL; | ||
2156 | while (NULL != (cur = a2s_head)) | ||
2157 | { | ||
2158 | GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur); | ||
2159 | GNUNET_free (cur); | ||
2160 | } | ||
2161 | if (NULL != plugin_nc) | ||
2162 | { | ||
2163 | GNUNET_notification_context_destroy (plugin_nc); | ||
2164 | plugin_nc = NULL; | ||
2165 | } | ||
2166 | GNUNET_CONTAINER_multipeermap_destroy (active_stccs); | ||
2167 | active_stccs = NULL; | ||
2168 | if (NULL != blacklist) | ||
2169 | { | ||
2170 | GNUNET_CONTAINER_multipeermap_iterate (blacklist, | ||
2171 | &free_blacklist_entry, | ||
2172 | NULL); | ||
2173 | GNUNET_CONTAINER_multipeermap_destroy (blacklist); | ||
2174 | blacklist = NULL; | ||
2175 | } | ||
2176 | GST_hello_stop (); | ||
2177 | GST_manipulation_stop (); | ||
2178 | |||
2179 | if (NULL != GST_peerinfo) | ||
2180 | { | ||
2181 | GNUNET_PEERINFO_disconnect (GST_peerinfo); | ||
2182 | GST_peerinfo = NULL; | ||
2183 | } | ||
2184 | if (NULL != GST_stats) | ||
2185 | { | ||
2186 | GNUNET_STATISTICS_destroy (GST_stats, GNUNET_NO); | ||
2187 | GST_stats = NULL; | ||
2188 | } | ||
2189 | } | ||
2190 | |||
2191 | |||
2192 | /** | ||
2193 | * Perform next action in the blacklist check. | ||
2194 | * | ||
2195 | * @param cls the `struct GST_BlacklistCheck *` | ||
2196 | */ | ||
2197 | static void | ||
2198 | do_blacklist_check (void *cls) | ||
2199 | { | ||
2200 | struct GST_BlacklistCheck *bc = cls; | ||
2201 | struct TransportClient *tc; | ||
2202 | struct GNUNET_MQ_Envelope *env; | ||
2203 | struct BlacklistMessage *bm; | ||
2204 | |||
2205 | bc->task = NULL; | ||
2206 | while (NULL != (tc = bc->bl_pos)) | ||
2207 | { | ||
2208 | if (CT_BLACKLIST == tc->type) | ||
2209 | break; | ||
2210 | bc->bl_pos = tc->next; | ||
2211 | } | ||
2212 | if (NULL == tc) | ||
2213 | { | ||
2214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2215 | "No other blacklist clients active, will allow neighbour `%s'\n", | ||
2216 | GNUNET_i2s (&bc->peer)); | ||
2217 | |||
2218 | bc->cont (bc->cont_cls, &bc->peer, bc->address, bc->session, GNUNET_OK); | ||
2219 | GST_blacklist_test_cancel (bc); | ||
2220 | return; | ||
2221 | } | ||
2222 | if ((NULL != tc->details.blacklist.bc) || | ||
2223 | (GNUNET_NO != tc->details.blacklist.waiting_for_reply)) | ||
2224 | return; /* someone else busy with this client */ | ||
2225 | tc->details.blacklist.bc = bc; | ||
2226 | env = GNUNET_MQ_msg (bm, GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); | ||
2227 | bm->is_allowed = htonl (0); | ||
2228 | bm->peer = bc->peer; | ||
2229 | GNUNET_MQ_send (tc->mq, env); | ||
2230 | if (GNUNET_YES == tc->details.blacklist.call_receive_done) | ||
2231 | { | ||
2232 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2233 | GNUNET_SERVICE_client_continue (tc->client); | ||
2234 | } | ||
2235 | tc->details.blacklist.waiting_for_reply = GNUNET_YES; | ||
2236 | } | ||
2237 | |||
2238 | |||
2239 | /** | ||
2240 | * A blacklisting client has sent us reply. Process it. | ||
2241 | * | ||
2242 | * @param cls the client | ||
2243 | * @param msg the blacklist-reply message that was sent | ||
2244 | */ | ||
2245 | static void | ||
2246 | handle_client_blacklist_reply (void *cls, const struct BlacklistMessage *msg) | ||
2247 | { | ||
2248 | struct TransportClient *tc = cls; | ||
2249 | struct GST_BlacklistCheck *bc; | ||
2250 | |||
2251 | if (CT_BLACKLIST != tc->type) | ||
2252 | { | ||
2253 | GNUNET_break (0); | ||
2254 | GNUNET_SERVICE_client_drop (tc->client); | ||
2255 | return; | ||
2256 | } | ||
2257 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2258 | "Blacklist client %p sent reply for `%s'\n", | ||
2259 | tc, | ||
2260 | GNUNET_i2s (&msg->peer)); | ||
2261 | bc = tc->details.blacklist.bc; | ||
2262 | tc->details.blacklist.bc = NULL; | ||
2263 | tc->details.blacklist.waiting_for_reply = GNUNET_NO; | ||
2264 | tc->details.blacklist.call_receive_done = GNUNET_YES; | ||
2265 | if (NULL != bc) | ||
2266 | { | ||
2267 | /* only run this if the blacklist check has not been | ||
2268 | * cancelled in the meantime... */ | ||
2269 | GNUNET_assert (bc->bl_pos == tc); | ||
2270 | if (ntohl (msg->is_allowed) == GNUNET_SYSERR) | ||
2271 | { | ||
2272 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2273 | "Blacklist check failed, peer not allowed\n"); | ||
2274 | /* For the duration of the continuation, make the ongoing | ||
2275 | check invisible (to avoid double-cancellation); then | ||
2276 | add it back again so we can re-use GST_blacklist_test_cancel() */ | ||
2277 | GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); | ||
2278 | bc->cont (bc->cont_cls, &bc->peer, bc->address, bc->session, GNUNET_NO); | ||
2279 | GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); | ||
2280 | GST_blacklist_test_cancel (bc); | ||
2281 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2282 | GNUNET_SERVICE_client_continue (tc->client); | ||
2283 | return; | ||
2284 | } | ||
2285 | else | ||
2286 | { | ||
2287 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2288 | "Blacklist check succeeded, continuing with checks\n"); | ||
2289 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2290 | GNUNET_SERVICE_client_continue (tc->client); | ||
2291 | bc->bl_pos = tc->next; | ||
2292 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
2293 | } | ||
2294 | } | ||
2295 | /* check if any other blacklist checks are waiting for this blacklister */ | ||
2296 | for (bc = bc_head; bc != NULL; bc = bc->next) | ||
2297 | if ((bc->bl_pos == tc) && (NULL == bc->task)) | ||
2298 | { | ||
2299 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
2300 | break; | ||
2301 | } | ||
2302 | } | ||
2303 | |||
2304 | |||
2305 | /** | ||
2306 | * Add the given peer to the blacklist (for the given transport). | ||
2307 | * | ||
2308 | * @param peer peer to blacklist | ||
2309 | * @param transport_name transport to blacklist for this peer, NULL for all | ||
2310 | */ | ||
2311 | void | ||
2312 | GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, | ||
2313 | const char *transport_name) | ||
2314 | { | ||
2315 | char *transport = NULL; | ||
2316 | |||
2317 | if (NULL != transport_name) | ||
2318 | { | ||
2319 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2320 | "Adding peer `%s' with plugin `%s' to blacklist\n", | ||
2321 | GNUNET_i2s (peer), | ||
2322 | transport_name); | ||
2323 | transport = GNUNET_strdup (transport_name); | ||
2324 | } | ||
2325 | else | ||
2326 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2327 | "Adding peer `%s' with all plugins to blacklist\n", | ||
2328 | GNUNET_i2s (peer)); | ||
2329 | if (NULL == blacklist) | ||
2330 | blacklist = | ||
2331 | GNUNET_CONTAINER_multipeermap_create (TRANSPORT_BLACKLIST_HT_SIZE, | ||
2332 | GNUNET_NO); | ||
2333 | |||
2334 | GNUNET_CONTAINER_multipeermap_put (blacklist, | ||
2335 | peer, | ||
2336 | transport, | ||
2337 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
2338 | } | ||
2339 | |||
2340 | |||
2341 | /** | ||
2342 | * Abort blacklist if @a address and @a session match. | ||
2343 | * | ||
2344 | * @param address address used to abort matching checks | ||
2345 | * @param session session used to abort matching checks | ||
2346 | */ | ||
2347 | void | ||
2348 | GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address, | ||
2349 | struct GNUNET_ATS_Session *session) | ||
2350 | { | ||
2351 | struct GST_BlacklistCheck *bc; | ||
2352 | struct GST_BlacklistCheck *n; | ||
2353 | |||
2354 | n = bc_head; | ||
2355 | while (NULL != (bc = n)) | ||
2356 | { | ||
2357 | n = bc->next; | ||
2358 | if ((bc->session == session) && | ||
2359 | (0 == GNUNET_HELLO_address_cmp (bc->address, address))) | ||
2360 | { | ||
2361 | bc->cont (bc->cont_cls, | ||
2362 | &bc->peer, | ||
2363 | bc->address, | ||
2364 | bc->session, | ||
2365 | GNUNET_SYSERR); | ||
2366 | GST_blacklist_test_cancel (bc); | ||
2367 | } | ||
2368 | } | ||
2369 | } | ||
2370 | |||
2371 | |||
2372 | /** | ||
2373 | * Test if the given blacklist entry matches. If so, | ||
2374 | * abort the iteration. | ||
2375 | * | ||
2376 | * @param cls the transport name to match (const char*) | ||
2377 | * @param key the key (unused) | ||
2378 | * @param value the 'char *' (name of a blacklisted transport) | ||
2379 | * @return #GNUNET_OK if the entry does not match, #GNUNET_NO if it matches | ||
2380 | */ | ||
2381 | static int | ||
2382 | test_blacklisted (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
2383 | { | ||
2384 | const char *transport_name = cls; | ||
2385 | char *be = value; | ||
2386 | |||
2387 | /* Blacklist entry be: | ||
2388 | * (NULL == be): peer is blacklisted with all plugins | ||
2389 | * (NULL != be): peer is blacklisted for a specific plugin | ||
2390 | * | ||
2391 | * If (NULL != transport_name) we look for a transport specific entry: | ||
2392 | * if (transport_name == be) forbidden | ||
2393 | * | ||
2394 | */GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2395 | "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n", | ||
2396 | GNUNET_i2s (key), | ||
2397 | (NULL == transport_name) ? "unspecified" : transport_name, | ||
2398 | (NULL == be) ? "all plugins" : be); | ||
2399 | /* all plugins for this peer were blacklisted: disallow */ | ||
2400 | if (NULL == value) | ||
2401 | return GNUNET_NO; | ||
2402 | |||
2403 | /* blacklist check for specific transport */ | ||
2404 | if ((NULL != transport_name) && (NULL != value)) | ||
2405 | { | ||
2406 | if (0 == strcmp (transport_name, be)) | ||
2407 | return GNUNET_NO; /* plugin is blacklisted! */ | ||
2408 | } | ||
2409 | return GNUNET_OK; | ||
2410 | } | ||
2411 | |||
2412 | |||
2413 | /** | ||
2414 | * Test if a peer/transport combination is blacklisted. | ||
2415 | * | ||
2416 | * @param peer the identity of the peer to test | ||
2417 | * @param transport_name name of the transport to test, never NULL | ||
2418 | * @param cont function to call with result | ||
2419 | * @param cont_cls closure for @a cont | ||
2420 | * @param address address to pass back to @a cont, can be NULL | ||
2421 | * @param session session to pass back to @a cont, can be NULL | ||
2422 | * @return handle to the blacklist check, NULL if the decision | ||
2423 | * was made instantly and @a cont was already called | ||
2424 | */ | ||
2425 | struct GST_BlacklistCheck * | ||
2426 | GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, | ||
2427 | const char *transport_name, | ||
2428 | GST_BlacklistTestContinuation cont, | ||
2429 | void *cont_cls, | ||
2430 | const struct GNUNET_HELLO_Address *address, | ||
2431 | struct GNUNET_ATS_Session *session) | ||
2432 | { | ||
2433 | struct GST_BlacklistCheck *bc; | ||
2434 | struct TransportClient *tc; | ||
2435 | |||
2436 | GNUNET_assert (NULL != peer); | ||
2437 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2438 | "Blacklist check for peer `%s':%s\n", | ||
2439 | GNUNET_i2s (peer), | ||
2440 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
2441 | |||
2442 | /* Check local blacklist by iterating over hashmap | ||
2443 | * If iteration is aborted, we found a matching blacklist entry */ | ||
2444 | if ((NULL != blacklist) && | ||
2445 | (GNUNET_SYSERR == | ||
2446 | GNUNET_CONTAINER_multipeermap_get_multiple (blacklist, | ||
2447 | peer, | ||
2448 | &test_blacklisted, | ||
2449 | (void *) transport_name))) | ||
2450 | { | ||
2451 | /* Disallowed by config, disapprove instantly */ | ||
2452 | GNUNET_STATISTICS_update (GST_stats, | ||
2453 | gettext_noop ("# disconnects due to blacklist"), | ||
2454 | 1, | ||
2455 | GNUNET_NO); | ||
2456 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2457 | _ ("Disallowing connection to peer `%s' on transport %s\n"), | ||
2458 | GNUNET_i2s (peer), | ||
2459 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
2460 | if (NULL != cont) | ||
2461 | cont (cont_cls, peer, address, session, GNUNET_NO); | ||
2462 | return NULL; | ||
2463 | } | ||
2464 | |||
2465 | for (tc = clients_head; NULL != tc; tc = tc->next) | ||
2466 | if (CT_BLACKLIST == tc->type) | ||
2467 | break; | ||
2468 | if (NULL == tc) | ||
2469 | { | ||
2470 | /* no blacklist clients, approve instantly */ | ||
2471 | if (NULL != cont) | ||
2472 | cont (cont_cls, peer, address, session, GNUNET_OK); | ||
2473 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2474 | "Allowing connection to peer `%s' %s\n", | ||
2475 | GNUNET_i2s (peer), | ||
2476 | (NULL != transport_name) ? transport_name : ""); | ||
2477 | return NULL; | ||
2478 | } | ||
2479 | |||
2480 | /* need to query blacklist clients */ | ||
2481 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
2482 | GNUNET_CONTAINER_DLL_insert (bc_head, bc_tail, bc); | ||
2483 | bc->peer = *peer; | ||
2484 | bc->address = GNUNET_HELLO_address_copy (address); | ||
2485 | bc->session = session; | ||
2486 | bc->cont = cont; | ||
2487 | bc->cont_cls = cont_cls; | ||
2488 | bc->bl_pos = tc; | ||
2489 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc); | ||
2490 | return bc; | ||
2491 | } | ||
2492 | |||
2493 | |||
2494 | /** | ||
2495 | * Cancel a blacklist check. | ||
2496 | * | ||
2497 | * @param bc check to cancel | ||
2498 | */ | ||
2499 | void | ||
2500 | GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc) | ||
2501 | { | ||
2502 | GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc); | ||
2503 | if (NULL != bc->bl_pos) | ||
2504 | { | ||
2505 | if ((CT_BLACKLIST == bc->bl_pos->type) && | ||
2506 | (bc->bl_pos->details.blacklist.bc == bc)) | ||
2507 | { | ||
2508 | /* we're at the head of the queue, remove us! */ | ||
2509 | bc->bl_pos->details.blacklist.bc = NULL; | ||
2510 | } | ||
2511 | } | ||
2512 | if (NULL != bc->task) | ||
2513 | { | ||
2514 | GNUNET_SCHEDULER_cancel (bc->task); | ||
2515 | bc->task = NULL; | ||
2516 | } | ||
2517 | GNUNET_free (bc->address); | ||
2518 | GNUNET_free (bc); | ||
2519 | } | ||
2520 | |||
2521 | |||
2522 | /** | ||
2523 | * Function to iterate over options in the blacklisting section for a peer. | ||
2524 | * | ||
2525 | * @param cls closure | ||
2526 | * @param section name of the section | ||
2527 | * @param option name of the option | ||
2528 | * @param value value of the option | ||
2529 | */ | ||
2530 | static void | ||
2531 | blacklist_cfg_iter (void *cls, | ||
2532 | const char *section, | ||
2533 | const char *option, | ||
2534 | const char *value) | ||
2535 | { | ||
2536 | unsigned int *res = cls; | ||
2537 | struct GNUNET_PeerIdentity peer; | ||
2538 | char *plugs; | ||
2539 | char *pos; | ||
2540 | |||
2541 | if (GNUNET_OK != | ||
2542 | GNUNET_CRYPTO_eddsa_public_key_from_string (option, | ||
2543 | strlen (option), | ||
2544 | &peer.public_key)) | ||
2545 | return; | ||
2546 | |||
2547 | if ((NULL == value) || (0 == strcmp (value, ""))) | ||
2548 | { | ||
2549 | /* Blacklist whole peer */ | ||
2550 | GST_blacklist_add_peer (&peer, NULL); | ||
2551 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2552 | _ ("Adding blacklisting entry for peer `%s'\n"), | ||
2553 | GNUNET_i2s (&peer)); | ||
2554 | } | ||
2555 | else | ||
2556 | { | ||
2557 | plugs = GNUNET_strdup (value); | ||
2558 | for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) | ||
2559 | { | ||
2560 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2561 | _ ("Adding blacklisting entry for peer `%s':`%s'\n"), | ||
2562 | GNUNET_i2s (&peer), | ||
2563 | pos); | ||
2564 | GST_blacklist_add_peer (&peer, pos); | ||
2565 | } | ||
2566 | GNUNET_free (plugs); | ||
2567 | } | ||
2568 | (*res)++; | ||
2569 | } | ||
2570 | |||
2571 | |||
2572 | /** | ||
2573 | * Read blacklist configuration | ||
2574 | * | ||
2575 | * @param cfg the configuration handle | ||
2576 | * @param my_id my peer identity | ||
2577 | */ | ||
2578 | static void | ||
2579 | read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2580 | const struct GNUNET_PeerIdentity *my_id) | ||
2581 | { | ||
2582 | char cfg_sect[512]; | ||
2583 | unsigned int res = 0; | ||
2584 | |||
2585 | GNUNET_snprintf (cfg_sect, | ||
2586 | sizeof(cfg_sect), | ||
2587 | "transport-blacklist-%s", | ||
2588 | GNUNET_i2s_full (my_id)); | ||
2589 | GNUNET_CONFIGURATION_iterate_section_values (cfg, | ||
2590 | cfg_sect, | ||
2591 | &blacklist_cfg_iter, | ||
2592 | &res); | ||
2593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2594 | "Loaded %u blacklisting entries from configuration\n", | ||
2595 | res); | ||
2596 | } | ||
2597 | |||
2598 | |||
2599 | /** | ||
2600 | * Initiate transport service. | ||
2601 | * | ||
2602 | * @param cls closure | ||
2603 | * @param c configuration to use | ||
2604 | * @param service the initialized service | ||
2605 | */ | ||
2606 | static void | ||
2607 | run (void *cls, | ||
2608 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
2609 | struct GNUNET_SERVICE_Handle *service) | ||
2610 | { | ||
2611 | char *keyfile; | ||
2612 | long long unsigned int max_fd_cfg; | ||
2613 | int max_fd_rlimit; | ||
2614 | int max_fd; | ||
2615 | int friend_only; | ||
2616 | |||
2617 | /* setup globals */ | ||
2618 | GST_cfg = c; | ||
2619 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, | ||
2620 | "PEER", | ||
2621 | "PRIVATE_KEY", | ||
2622 | &keyfile)) | ||
2623 | { | ||
2624 | GNUNET_log ( | ||
2625 | GNUNET_ERROR_TYPE_ERROR, | ||
2626 | _ ( | ||
2627 | "Transport service is lacking key configuration settings. Exiting.\n")); | ||
2628 | GNUNET_SCHEDULER_shutdown (); | ||
2629 | return; | ||
2630 | } | ||
2631 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, | ||
2632 | "transport", | ||
2633 | "HELLO_EXPIRATION", | ||
2634 | &hello_expiration)) | ||
2635 | { | ||
2636 | hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; | ||
2637 | } | ||
2638 | if (GNUNET_SYSERR == | ||
2639 | GNUNET_CRYPTO_eddsa_key_from_file (keyfile, | ||
2640 | GNUNET_YES, | ||
2641 | &GST_my_private_key)) | ||
2642 | { | ||
2643 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2644 | "Failed to setup peer's private key\n"); | ||
2645 | GNUNET_SCHEDULER_shutdown (); | ||
2646 | GNUNET_free (keyfile); | ||
2647 | return; | ||
2648 | } | ||
2649 | GNUNET_free (keyfile); | ||
2650 | GST_stats = GNUNET_STATISTICS_create ("transport", GST_cfg); | ||
2651 | GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg); | ||
2652 | GNUNET_CRYPTO_eddsa_key_get_public (&GST_my_private_key, | ||
2653 | &GST_my_identity.public_key); | ||
2654 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2655 | "My identity is `%s'\n", | ||
2656 | GNUNET_i2s_full (&GST_my_identity)); | ||
2657 | |||
2658 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
2659 | if (NULL == GST_peerinfo) | ||
2660 | { | ||
2661 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
2662 | _ ("Could not access PEERINFO service. Exiting.\n")); | ||
2663 | GNUNET_SCHEDULER_shutdown (); | ||
2664 | return; | ||
2665 | } | ||
2666 | |||
2667 | max_fd_rlimit = 0; | ||
2668 | #if HAVE_GETRLIMIT | ||
2669 | { | ||
2670 | struct rlimit r_file; | ||
2671 | |||
2672 | if (0 == getrlimit (RLIMIT_NOFILE, &r_file)) | ||
2673 | { | ||
2674 | max_fd_rlimit = r_file.rlim_cur; | ||
2675 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2676 | "Maximum number of open files was: %u/%u\n", | ||
2677 | (unsigned int) r_file.rlim_cur, | ||
2678 | (unsigned int) r_file.rlim_max); | ||
2679 | } | ||
2680 | max_fd_rlimit = | ||
2681 | (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */ | ||
2682 | } | ||
2683 | #endif | ||
2684 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (GST_cfg, | ||
2685 | "transport", | ||
2686 | "MAX_FD", | ||
2687 | &max_fd_cfg)) | ||
2688 | max_fd_cfg = max_fd_rlimit; | ||
2689 | |||
2690 | if (max_fd_cfg > max_fd_rlimit) | ||
2691 | max_fd = max_fd_cfg; | ||
2692 | else | ||
2693 | max_fd = max_fd_rlimit; | ||
2694 | if (max_fd < DEFAULT_MAX_FDS) | ||
2695 | max_fd = DEFAULT_MAX_FDS; | ||
2696 | |||
2697 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2698 | "Limiting number of sockets to %u: validation %u, neighbors: %u\n", | ||
2699 | max_fd, | ||
2700 | (max_fd / 3), | ||
2701 | (max_fd / 3) * 2); | ||
2702 | |||
2703 | friend_only = | ||
2704 | GNUNET_CONFIGURATION_get_value_yesno (GST_cfg, "topology", "FRIENDS-ONLY"); | ||
2705 | if (GNUNET_SYSERR == friend_only) | ||
2706 | friend_only = GNUNET_NO; /* According to topology defaults */ | ||
2707 | /* start subsystems */ | ||
2708 | /* Disable DSTJ peer */ | ||
2709 | { | ||
2710 | struct GNUNET_PeerIdentity dstj; | ||
2711 | const char *ds = "DSTJBRRKZ8TBW3FGK6B0M5QXWT9WYNZ45H5MCV4HY7ST64Q8T9F0"; | ||
2712 | |||
2713 | GNUNET_assert ( | ||
2714 | GNUNET_OK == | ||
2715 | GNUNET_CRYPTO_eddsa_public_key_from_string (ds, | ||
2716 | strlen (ds), | ||
2717 | &dstj.public_key)); | ||
2718 | GST_blacklist_add_peer (&dstj, NULL); | ||
2719 | } | ||
2720 | read_blacklist_configuration (GST_cfg, &GST_my_identity); | ||
2721 | GST_is = GNUNET_NT_scanner_init (); | ||
2722 | GST_ats_connect = GNUNET_ATS_connectivity_init (GST_cfg); | ||
2723 | GST_ats = | ||
2724 | GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL); | ||
2725 | GST_ats_init (); | ||
2726 | GST_manipulation_init (); | ||
2727 | GST_plugins_load (&GST_manipulation_recv, | ||
2728 | &plugin_env_address_change_notification, | ||
2729 | &plugin_env_session_start, | ||
2730 | &plugin_env_session_end); | ||
2731 | GST_hello_start (friend_only, &process_hello_update, NULL); | ||
2732 | GST_neighbours_start ((max_fd / 3) * 2); | ||
2733 | active_stccs = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); | ||
2734 | plugin_nc = GNUNET_notification_context_create (0); | ||
2735 | GST_validation_start ((max_fd / 3)); | ||
2736 | } | ||
2737 | |||
2738 | |||
2739 | /** | ||
2740 | * Define "main" method using service macro. | ||
2741 | */ | ||
2742 | GNUNET_SERVICE_MAIN ( | ||
2743 | "transport", | ||
2744 | GNUNET_SERVICE_OPTION_NONE, | ||
2745 | &run, | ||
2746 | &client_connect_cb, | ||
2747 | &client_disconnect_cb, | ||
2748 | NULL, | ||
2749 | GNUNET_MQ_hd_fixed_size (client_start, | ||
2750 | GNUNET_MESSAGE_TYPE_TRANSPORT_START, | ||
2751 | struct StartMessage, | ||
2752 | NULL), | ||
2753 | GNUNET_MQ_hd_var_size (client_hello, | ||
2754 | GNUNET_MESSAGE_TYPE_HELLO, | ||
2755 | struct GNUNET_MessageHeader, | ||
2756 | NULL), | ||
2757 | GNUNET_MQ_hd_var_size (client_send, | ||
2758 | GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, | ||
2759 | struct OutboundMessage, | ||
2760 | NULL), | ||
2761 | GNUNET_MQ_hd_var_size (client_address_to_string, | ||
2762 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, | ||
2763 | struct AddressLookupMessage, | ||
2764 | NULL), | ||
2765 | GNUNET_MQ_hd_fixed_size (client_monitor_peers, | ||
2766 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST, | ||
2767 | struct PeerMonitorMessage, | ||
2768 | NULL), | ||
2769 | GNUNET_MQ_hd_fixed_size (client_blacklist_init, | ||
2770 | GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, | ||
2771 | struct GNUNET_MessageHeader, | ||
2772 | NULL), | ||
2773 | GNUNET_MQ_hd_fixed_size (client_blacklist_reply, | ||
2774 | GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, | ||
2775 | struct BlacklistMessage, | ||
2776 | NULL), | ||
2777 | GNUNET_MQ_hd_fixed_size (client_set_metric, | ||
2778 | GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, | ||
2779 | struct TrafficMetricMessage, | ||
2780 | NULL), | ||
2781 | GNUNET_MQ_hd_fixed_size (client_monitor_plugins, | ||
2782 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_START, | ||
2783 | struct GNUNET_MessageHeader, | ||
2784 | NULL), | ||
2785 | GNUNET_MQ_handler_end ()); | ||
2786 | |||
2787 | |||
2788 | /* end of file gnunet-service-transport.c */ | ||