diff options
Diffstat (limited to 'src/transport/gnunet-service-transport.c')
-rw-r--r-- | src/transport/gnunet-service-transport.c | 2103 |
1 files changed, 2043 insertions, 60 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index a21ddabd6..e7b221344 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2010-2015 GNUnet e.V. | 3 | Copyright (C) 2010-2016 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -31,8 +31,6 @@ | |||
31 | #include "gnunet_ats_service.h" | 31 | #include "gnunet_ats_service.h" |
32 | #include "gnunet-service-transport.h" | 32 | #include "gnunet-service-transport.h" |
33 | #include "gnunet-service-transport_ats.h" | 33 | #include "gnunet-service-transport_ats.h" |
34 | #include "gnunet-service-transport_blacklist.h" | ||
35 | #include "gnunet-service-transport_clients.h" | ||
36 | #include "gnunet-service-transport_hello.h" | 34 | #include "gnunet-service-transport_hello.h" |
37 | #include "gnunet-service-transport_neighbours.h" | 35 | #include "gnunet-service-transport_neighbours.h" |
38 | #include "gnunet-service-transport_plugins.h" | 36 | #include "gnunet-service-transport_plugins.h" |
@@ -40,6 +38,25 @@ | |||
40 | #include "gnunet-service-transport_manipulation.h" | 38 | #include "gnunet-service-transport_manipulation.h" |
41 | #include "transport.h" | 39 | #include "transport.h" |
42 | 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 | |||
43 | 60 | ||
44 | /** | 61 | /** |
45 | * Information we need for an asynchronous session kill. | 62 | * Information we need for an asynchronous session kill. |
@@ -73,7 +90,279 @@ struct GNUNET_ATS_SessionKiller | |||
73 | }; | 90 | }; |
74 | 91 | ||
75 | 92 | ||
76 | /* globals */ | 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 | |||
120 | /** | ||
121 | * Context we use when performing a blacklist check. | ||
122 | */ | ||
123 | struct GST_BlacklistCheck; | ||
124 | |||
125 | /** | ||
126 | * Client connected to the transport service. | ||
127 | */ | ||
128 | struct TransportClient | ||
129 | { | ||
130 | |||
131 | /** | ||
132 | * This is a doubly-linked list. | ||
133 | */ | ||
134 | struct TransportClient *next; | ||
135 | |||
136 | /** | ||
137 | * This is a doubly-linked list. | ||
138 | */ | ||
139 | struct TransportClient *prev; | ||
140 | |||
141 | /** | ||
142 | * Handle to the client. | ||
143 | */ | ||
144 | struct GNUNET_SERVICE_Client *client; | ||
145 | |||
146 | /** | ||
147 | * Message queue to the client. | ||
148 | */ | ||
149 | struct GNUNET_MQ_Handle *mq; | ||
150 | |||
151 | /** | ||
152 | * What type of client is this? | ||
153 | */ | ||
154 | enum ClientType type; | ||
155 | |||
156 | union { | ||
157 | |||
158 | /** | ||
159 | * Peer identity to monitor the addresses of. | ||
160 | * Zero to monitor all neighbours. Valid if | ||
161 | * @e type is CT_MONITOR. | ||
162 | */ | ||
163 | struct GNUNET_PeerIdentity monitor_peer; | ||
164 | |||
165 | /** | ||
166 | * Additional details if @e type is CT_BLACKLIST. | ||
167 | */ | ||
168 | struct { | ||
169 | |||
170 | /** | ||
171 | * Blacklist check that we're currently performing (or NULL | ||
172 | * if we're performing one that has been cancelled). | ||
173 | */ | ||
174 | struct GST_BlacklistCheck *bc; | ||
175 | |||
176 | /** | ||
177 | * Set to #GNUNET_YES if we're currently waiting for a reply. | ||
178 | */ | ||
179 | int waiting_for_reply; | ||
180 | |||
181 | /** | ||
182 | * #GNUNET_YES if we have to call receive_done for this client | ||
183 | */ | ||
184 | int call_receive_done; | ||
185 | |||
186 | } blacklist; | ||
187 | |||
188 | } details; | ||
189 | |||
190 | }; | ||
191 | |||
192 | |||
193 | |||
194 | /** | ||
195 | * Context we use when performing a blacklist check. | ||
196 | */ | ||
197 | struct GST_BlacklistCheck | ||
198 | { | ||
199 | |||
200 | /** | ||
201 | * This is a linked list. | ||
202 | */ | ||
203 | struct GST_BlacklistCheck *next; | ||
204 | |||
205 | /** | ||
206 | * This is a linked list. | ||
207 | */ | ||
208 | struct GST_BlacklistCheck *prev; | ||
209 | |||
210 | /** | ||
211 | * Peer being checked. | ||
212 | */ | ||
213 | struct GNUNET_PeerIdentity peer; | ||
214 | |||
215 | /** | ||
216 | * Continuation to call with the result. | ||
217 | */ | ||
218 | GST_BlacklistTestContinuation cont; | ||
219 | |||
220 | /** | ||
221 | * Closure for @e cont. | ||
222 | */ | ||
223 | void *cont_cls; | ||
224 | |||
225 | /** | ||
226 | * Address for #GST_blacklist_abort_matching(), can be NULL. | ||
227 | */ | ||
228 | struct GNUNET_HELLO_Address *address; | ||
229 | |||
230 | /** | ||
231 | * Session for #GST_blacklist_abort_matching(), can be NULL. | ||
232 | */ | ||
233 | struct GNUNET_ATS_Session *session; | ||
234 | |||
235 | /** | ||
236 | * Our current position in the blacklisters list. | ||
237 | */ | ||
238 | struct TransportClient *bl_pos; | ||
239 | |||
240 | /** | ||
241 | * Current task performing the check. | ||
242 | */ | ||
243 | struct GNUNET_SCHEDULER_Task *task; | ||
244 | |||
245 | }; | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Context for address to string operations | ||
250 | */ | ||
251 | struct AddressToStringContext | ||
252 | { | ||
253 | /** | ||
254 | * This is a doubly-linked list. | ||
255 | */ | ||
256 | struct AddressToStringContext *next; | ||
257 | |||
258 | /** | ||
259 | * This is a doubly-linked list. | ||
260 | */ | ||
261 | struct AddressToStringContext *prev; | ||
262 | |||
263 | /** | ||
264 | * Client that made the request. | ||
265 | */ | ||
266 | struct TransportClient* tc; | ||
267 | }; | ||
268 | |||
269 | |||
270 | /** | ||
271 | * Closure for #handle_send_transmit_continuation() | ||
272 | */ | ||
273 | struct SendTransmitContinuationContext | ||
274 | { | ||
275 | |||
276 | /** | ||
277 | * Client that made the request. | ||
278 | */ | ||
279 | struct TransportClient *tc; | ||
280 | |||
281 | /** | ||
282 | * Peer that was the target. | ||
283 | */ | ||
284 | struct GNUNET_PeerIdentity target; | ||
285 | |||
286 | /** | ||
287 | * At what time did we receive the message? | ||
288 | */ | ||
289 | struct GNUNET_TIME_Absolute send_time; | ||
290 | |||
291 | /** | ||
292 | * Unique ID, for logging. | ||
293 | */ | ||
294 | unsigned long long uuid; | ||
295 | |||
296 | /** | ||
297 | * Set to #GNUNET_YES if the connection for @e target goes | ||
298 | * down and we thus must no longer send the | ||
299 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK message. | ||
300 | */ | ||
301 | int down; | ||
302 | }; | ||
303 | |||
304 | |||
305 | /** | ||
306 | * Head of linked list of all clients to this service. | ||
307 | */ | ||
308 | static struct TransportClient *clients_head; | ||
309 | |||
310 | /** | ||
311 | * Tail of linked list of all clients to this service. | ||
312 | */ | ||
313 | static struct TransportClient *clients_tail; | ||
314 | |||
315 | /** | ||
316 | * Map of peer identities to active send transmit continuation | ||
317 | * contexts. Used to flag contexts as 'dead' when a connection goes | ||
318 | * down. Values are of type `struct SendTransmitContinuationContext | ||
319 | * *`. | ||
320 | */ | ||
321 | static struct GNUNET_CONTAINER_MultiPeerMap *active_stccs; | ||
322 | |||
323 | /** | ||
324 | * Head of linked list of all pending address iterations | ||
325 | */ | ||
326 | static struct AddressToStringContext *a2s_head; | ||
327 | |||
328 | /** | ||
329 | * Tail of linked list of all pending address iterations | ||
330 | */ | ||
331 | static struct AddressToStringContext *a2s_tail; | ||
332 | |||
333 | /** | ||
334 | * Head of DLL of active blacklisting queries. | ||
335 | */ | ||
336 | static struct GST_BlacklistCheck *bc_head; | ||
337 | |||
338 | /** | ||
339 | * Tail of DLL of active blacklisting queries. | ||
340 | */ | ||
341 | static struct GST_BlacklistCheck *bc_tail; | ||
342 | |||
343 | /** | ||
344 | * Hashmap of blacklisted peers. Values are of type 'char *' (transport names), | ||
345 | * can be NULL if we have no static blacklist. | ||
346 | */ | ||
347 | static struct GNUNET_CONTAINER_MultiPeerMap *blacklist; | ||
348 | |||
349 | /** | ||
350 | * Notification context, to send updates on changes to active plugin | ||
351 | * connections. | ||
352 | */ | ||
353 | static struct GNUNET_NotificationContext *plugin_nc; | ||
354 | |||
355 | /** | ||
356 | * Plugin monitoring client we are currently syncing, NULL if all | ||
357 | * monitoring clients are in sync. | ||
358 | */ | ||
359 | static struct TransportClient *sync_client; | ||
360 | |||
361 | /** | ||
362 | * Peer identity that is all zeros, used as a way to indicate | ||
363 | * "all peers". Used for comparissons. | ||
364 | */ | ||
365 | static struct GNUNET_PeerIdentity all_zeros; | ||
77 | 366 | ||
78 | /** | 367 | /** |
79 | * Statistics handle. | 368 | * Statistics handle. |
@@ -96,11 +385,6 @@ struct GNUNET_PeerIdentity GST_my_identity; | |||
96 | struct GNUNET_PEERINFO_Handle *GST_peerinfo; | 385 | struct GNUNET_PEERINFO_Handle *GST_peerinfo; |
97 | 386 | ||
98 | /** | 387 | /** |
99 | * Handle to our service's server. | ||
100 | */ | ||
101 | static struct GNUNET_SERVER_Handle *GST_server; | ||
102 | |||
103 | /** | ||
104 | * Our private key. | 388 | * Our private key. |
105 | */ | 389 | */ |
106 | struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; | 390 | struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; |
@@ -137,6 +421,1029 @@ struct GNUNET_ATS_InterfaceScanner *GST_is; | |||
137 | 421 | ||
138 | 422 | ||
139 | /** | 423 | /** |
424 | * Queue the given message for transmission to the given client | ||
425 | * | ||
426 | * @param tc target of the message | ||
427 | * @param msg message to transmit | ||
428 | * @param may_drop #GNUNET_YES if the message can be dropped | ||
429 | */ | ||
430 | static void | ||
431 | unicast (struct TransportClient *tc, | ||
432 | const struct GNUNET_MessageHeader *msg, | ||
433 | int may_drop) | ||
434 | { | ||
435 | struct GNUNET_MQ_Envelope *env; | ||
436 | |||
437 | if ( (GNUNET_MQ_get_length (tc->mq) >= MAX_PENDING) && | ||
438 | (GNUNET_YES == may_drop) ) | ||
439 | { | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
441 | "Dropping message of type %u and size %u, have %u/%u messages pending\n", | ||
442 | ntohs (msg->type), | ||
443 | ntohs (msg->size), | ||
444 | GNUNET_MQ_get_length (tc->mq), | ||
445 | MAX_PENDING); | ||
446 | GNUNET_STATISTICS_update (GST_stats, | ||
447 | gettext_noop | ||
448 | ("# messages dropped due to slow client"), 1, | ||
449 | GNUNET_NO); | ||
450 | return; | ||
451 | } | ||
452 | env = GNUNET_MQ_msg_copy (msg); | ||
453 | GNUNET_MQ_send (tc->mq, | ||
454 | env); | ||
455 | } | ||
456 | |||
457 | |||
458 | /** | ||
459 | * Called whenever a client connects. Allocates our | ||
460 | * data structures associated with that client. | ||
461 | * | ||
462 | * @param cls closure, NULL | ||
463 | * @param client identification of the client | ||
464 | * @param mq message queue for the client | ||
465 | * @return our `struct TransportClient` | ||
466 | */ | ||
467 | static void * | ||
468 | client_connect_cb (void *cls, | ||
469 | struct GNUNET_SERVICE_Client *client, | ||
470 | struct GNUNET_MQ_Handle *mq) | ||
471 | { | ||
472 | struct TransportClient *tc; | ||
473 | |||
474 | tc = GNUNET_new (struct TransportClient); | ||
475 | tc->client = client; | ||
476 | tc->mq = mq; | ||
477 | GNUNET_CONTAINER_DLL_insert (clients_head, | ||
478 | clients_tail, | ||
479 | tc); | ||
480 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
481 | "Client %p connected\n", | ||
482 | tc); | ||
483 | return tc; | ||
484 | } | ||
485 | |||
486 | |||
487 | /** | ||
488 | * Perform next action in the blacklist check. | ||
489 | * | ||
490 | * @param cls the `struct BlacklistCheck*` | ||
491 | */ | ||
492 | static void | ||
493 | do_blacklist_check (void *cls); | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Mark the peer as down so we don't call the continuation | ||
498 | * context in the future. | ||
499 | * | ||
500 | * @param cls a `struct TransportClient` | ||
501 | * @param peer a peer we are sending to | ||
502 | * @param value a `struct SendTransmitContinuationContext` to mark | ||
503 | * @return #GNUNET_OK (continue to iterate) | ||
504 | */ | ||
505 | static int | ||
506 | mark_match_down (void *cls, | ||
507 | const struct GNUNET_PeerIdentity *peer, | ||
508 | void *value) | ||
509 | { | ||
510 | struct TransportClient *tc = cls; | ||
511 | struct SendTransmitContinuationContext *stcc = value; | ||
512 | |||
513 | if (tc == stcc->tc) | ||
514 | { | ||
515 | stcc->down = GNUNET_YES; | ||
516 | stcc->tc = NULL; | ||
517 | } | ||
518 | return GNUNET_OK; | ||
519 | } | ||
520 | |||
521 | |||
522 | /** | ||
523 | * Called whenever a client is disconnected. Frees our | ||
524 | * resources associated with that client. | ||
525 | * | ||
526 | * @param cls closure, NULL | ||
527 | * @param client identification of the client | ||
528 | * @param app_ctx our `struct TransportClient` | ||
529 | */ | ||
530 | static void | ||
531 | client_disconnect_cb (void *cls, | ||
532 | struct GNUNET_SERVICE_Client *client, | ||
533 | void *app_ctx) | ||
534 | { | ||
535 | struct TransportClient *tc = app_ctx; | ||
536 | struct GST_BlacklistCheck *bc; | ||
537 | |||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Client %p disconnected, cleaning up.\n", | ||
540 | tc); | ||
541 | GNUNET_CONTAINER_multipeermap_iterate (active_stccs, | ||
542 | &mark_match_down, | ||
543 | tc); | ||
544 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
545 | clients_tail, | ||
546 | tc); | ||
547 | switch (tc->type) | ||
548 | { | ||
549 | case CT_NONE: | ||
550 | break; | ||
551 | case CT_CORE: | ||
552 | break; | ||
553 | case CT_MONITOR: | ||
554 | break; | ||
555 | case CT_BLACKLIST: | ||
556 | for (bc = bc_head; NULL != bc; bc = bc->next) | ||
557 | { | ||
558 | if (bc->bl_pos != tc) | ||
559 | continue; | ||
560 | bc->bl_pos = tc->next; | ||
561 | if (NULL == bc->task) | ||
562 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
563 | bc); | ||
564 | } | ||
565 | break; | ||
566 | } | ||
567 | GNUNET_free (tc); | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * Function called for each of our connected neighbours. Notify the | ||
573 | * client about the existing neighbour. | ||
574 | * | ||
575 | * @param cls the `struct TransportClient *` to notify | ||
576 | * @param peer identity of the neighbour | ||
577 | * @param address the address | ||
578 | * @param state the current state of the peer | ||
579 | * @param state_timeout the time out for the state | ||
580 | * @param bandwidth_in inbound bandwidth in NBO | ||
581 | * @param bandwidth_out outbound bandwidth in NBO | ||
582 | */ | ||
583 | static void | ||
584 | notify_client_about_neighbour (void *cls, | ||
585 | const struct GNUNET_PeerIdentity *peer, | ||
586 | const struct GNUNET_HELLO_Address *address, | ||
587 | enum GNUNET_TRANSPORT_PeerState state, | ||
588 | struct GNUNET_TIME_Absolute state_timeout, | ||
589 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
590 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
591 | { | ||
592 | struct TransportClient *tc = cls; | ||
593 | struct ConnectInfoMessage cim; | ||
594 | |||
595 | if (GNUNET_NO == GST_neighbours_test_connected (peer)) | ||
596 | return; | ||
597 | cim.header.size = htons (sizeof (struct ConnectInfoMessage)); | ||
598 | cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT); | ||
599 | cim.id = *peer; | ||
600 | cim.quota_in = bandwidth_in; | ||
601 | cim.quota_out = bandwidth_out; | ||
602 | unicast (tc, | ||
603 | &cim.header, | ||
604 | GNUNET_NO); | ||
605 | } | ||
606 | |||
607 | |||
608 | /** | ||
609 | * Initialize a normal client. We got a start message from this | ||
610 | * client, add him to the list of clients for broadcasting of inbound | ||
611 | * messages. | ||
612 | * | ||
613 | * @param cls the client | ||
614 | * @param start the start message that was sent | ||
615 | */ | ||
616 | static void | ||
617 | handle_client_start (void *cls, | ||
618 | const struct StartMessage *start) | ||
619 | { | ||
620 | struct TransportClient *tc = cls; | ||
621 | const struct GNUNET_MessageHeader *hello; | ||
622 | uint32_t options; | ||
623 | |||
624 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
625 | "Client %p sent START\n", | ||
626 | tc); | ||
627 | options = ntohl (start->options); | ||
628 | if ((0 != (1 & options)) && | ||
629 | (0 != | ||
630 | memcmp (&start->self, | ||
631 | &GST_my_identity, | ||
632 | sizeof (struct GNUNET_PeerIdentity)))) | ||
633 | { | ||
634 | /* client thinks this is a different peer, reject */ | ||
635 | GNUNET_break (0); | ||
636 | GNUNET_SERVICE_client_drop (tc->client); | ||
637 | return; | ||
638 | } | ||
639 | if (CT_NONE != tc->type) | ||
640 | { | ||
641 | GNUNET_break (0); | ||
642 | GNUNET_SERVICE_client_drop (tc->client); | ||
643 | return; | ||
644 | } | ||
645 | if (0 != (2 & options)) | ||
646 | tc->type = CT_CORE; | ||
647 | hello = GST_hello_get (); | ||
648 | if (NULL != hello) | ||
649 | unicast (tc, | ||
650 | hello, | ||
651 | GNUNET_NO); | ||
652 | GST_neighbours_iterate (¬ify_client_about_neighbour, | ||
653 | tc); | ||
654 | GNUNET_SERVICE_client_continue (tc->client); | ||
655 | } | ||
656 | |||
657 | |||
658 | /** | ||
659 | * Client sent us a HELLO. Check the request. | ||
660 | * | ||
661 | * @param cls the client | ||
662 | * @param message the HELLO message | ||
663 | */ | ||
664 | static int | ||
665 | check_client_hello (void *cls, | ||
666 | const struct GNUNET_MessageHeader *message) | ||
667 | { | ||
668 | return GNUNET_OK; /* FIXME: check here? */ | ||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
673 | * Client sent us a HELLO. Process the request. | ||
674 | * | ||
675 | * @param cls the client | ||
676 | * @param message the HELLO message | ||
677 | */ | ||
678 | static void | ||
679 | handle_client_hello (void *cls, | ||
680 | const struct GNUNET_MessageHeader *message) | ||
681 | { | ||
682 | struct TransportClient *tc = cls; | ||
683 | |||
684 | GST_validation_handle_hello (message); | ||
685 | GNUNET_SERVICE_client_continue (tc->client); | ||
686 | } | ||
687 | |||
688 | |||
689 | /** | ||
690 | * Function called after the transmission is done. Notify the client that it is | ||
691 | * OK to send the next message. | ||
692 | * | ||
693 | * @param cls closure | ||
694 | * @param success #GNUNET_OK on success, #GNUNET_NO on failure, #GNUNET_SYSERR if we're not connected | ||
695 | * @param bytes_payload bytes payload sent | ||
696 | * @param bytes_on_wire bytes sent on wire | ||
697 | */ | ||
698 | static void | ||
699 | handle_send_transmit_continuation (void *cls, | ||
700 | int success, | ||
701 | size_t bytes_payload, | ||
702 | size_t bytes_on_wire) | ||
703 | { | ||
704 | struct SendTransmitContinuationContext *stcc = cls; | ||
705 | struct SendOkMessage send_ok_msg; | ||
706 | struct GNUNET_TIME_Relative delay; | ||
707 | const struct GNUNET_HELLO_Address *addr; | ||
708 | |||
709 | delay = GNUNET_TIME_absolute_get_duration (stcc->send_time); | ||
710 | addr = GST_neighbour_get_current_address (&stcc->target); | ||
711 | if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us) | ||
712 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
713 | "It took us %s to send %u/%u bytes to %s (%d, %s)\n", | ||
714 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
715 | GNUNET_YES), | ||
716 | (unsigned int) bytes_payload, | ||
717 | (unsigned int) bytes_on_wire, | ||
718 | GNUNET_i2s (&stcc->target), | ||
719 | success, | ||
720 | (NULL != addr) ? addr->transport_name : "%"); | ||
721 | else | ||
722 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
723 | "It took us %s to send %u/%u bytes to %s (%d, %s)\n", | ||
724 | GNUNET_STRINGS_relative_time_to_string (delay, | ||
725 | GNUNET_YES), | ||
726 | (unsigned int) bytes_payload, | ||
727 | (unsigned int) bytes_on_wire, | ||
728 | GNUNET_i2s (&stcc->target), | ||
729 | success, | ||
730 | (NULL != addr) ? addr->transport_name : "%"); | ||
731 | |||
732 | if (GNUNET_NO == stcc->down) | ||
733 | { | ||
734 | /* Only send confirmation if we are still connected */ | ||
735 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Sending SEND_OK for transmission request %llu\n", | ||
737 | stcc->uuid); | ||
738 | send_ok_msg.header.size = htons (sizeof (send_ok_msg)); | ||
739 | send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); | ||
740 | send_ok_msg.bytes_msg = htonl (bytes_payload); | ||
741 | send_ok_msg.bytes_physical = htonl (bytes_on_wire); | ||
742 | send_ok_msg.success = htonl (success); | ||
743 | send_ok_msg.peer = stcc->target; | ||
744 | unicast (stcc->tc, | ||
745 | &send_ok_msg.header, | ||
746 | GNUNET_NO); | ||
747 | } | ||
748 | GNUNET_assert (GNUNET_OK == | ||
749 | GNUNET_CONTAINER_multipeermap_remove (active_stccs, | ||
750 | &stcc->target, | ||
751 | stcc)); | ||
752 | GNUNET_free (stcc); | ||
753 | } | ||
754 | |||
755 | |||
756 | /** | ||
757 | * Client asked for transmission to a peer. Process the request. | ||
758 | * | ||
759 | * @param cls the client | ||
760 | * @param obm the send message that was sent | ||
761 | */ | ||
762 | static int | ||
763 | check_client_send (void *cls, | ||
764 | const struct OutboundMessage *obm) | ||
765 | { | ||
766 | uint16_t size; | ||
767 | const struct GNUNET_MessageHeader *obmm; | ||
768 | |||
769 | size = ntohs (obm->header.size) - sizeof (struct OutboundMessage); | ||
770 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
771 | { | ||
772 | GNUNET_break (0); | ||
773 | return GNUNET_SYSERR; | ||
774 | } | ||
775 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | ||
776 | if (size != ntohs (obmm->size)) | ||
777 | { | ||
778 | GNUNET_break (0); | ||
779 | return GNUNET_SYSERR; | ||
780 | } | ||
781 | return GNUNET_OK; | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | ||
786 | * Client asked for transmission to a peer. Process the request. | ||
787 | * | ||
788 | * @param cls the client | ||
789 | * @param obm the send message that was sent | ||
790 | */ | ||
791 | static void | ||
792 | handle_client_send (void *cls, | ||
793 | const struct OutboundMessage *obm) | ||
794 | { | ||
795 | static unsigned long long uuid_gen; | ||
796 | struct TransportClient *tc = cls; | ||
797 | const struct GNUNET_MessageHeader *obmm; | ||
798 | struct SendTransmitContinuationContext *stcc; | ||
799 | |||
800 | obmm = (const struct GNUNET_MessageHeader *) &obm[1]; | ||
801 | if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer)) | ||
802 | { | ||
803 | /* not connected, not allowed to send; can happen due to asynchronous operations */ | ||
804 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
805 | "Could not send message to peer `%s': not connected\n", | ||
806 | GNUNET_i2s (&obm->peer)); | ||
807 | GNUNET_STATISTICS_update (GST_stats, | ||
808 | gettext_noop | ||
809 | ("# bytes payload dropped (other peer was not connected)"), | ||
810 | ntohs (obmm->size), | ||
811 | GNUNET_NO); | ||
812 | GNUNET_SERVICE_client_continue (tc->client); | ||
813 | return; | ||
814 | } | ||
815 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
816 | "Received SEND request %llu for `%s' and first message of type %u and total size %u\n", | ||
817 | uuid_gen, | ||
818 | GNUNET_i2s (&obm->peer), | ||
819 | ntohs (obmm->type), | ||
820 | ntohs (obmm->size)); | ||
821 | GNUNET_SERVICE_client_continue (tc->client); | ||
822 | |||
823 | stcc = GNUNET_new (struct SendTransmitContinuationContext); | ||
824 | stcc->target = obm->peer; | ||
825 | stcc->tc = tc; | ||
826 | stcc->send_time = GNUNET_TIME_absolute_get (); | ||
827 | stcc->uuid = uuid_gen++; | ||
828 | (void) GNUNET_CONTAINER_multipeermap_put (active_stccs, | ||
829 | &stcc->target, | ||
830 | stcc, | ||
831 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
832 | GST_manipulation_send (&obm->peer, | ||
833 | obmm, | ||
834 | ntohs (obmm->size), | ||
835 | GNUNET_TIME_relative_ntoh (obm->timeout), | ||
836 | &handle_send_transmit_continuation, | ||
837 | stcc); | ||
838 | } | ||
839 | |||
840 | |||
841 | /** | ||
842 | * Take the given address and append it to the set of results sent back to | ||
843 | * the client. This function may be called serveral times for a single | ||
844 | * conversion. The last invocation will be with a @a address of | ||
845 | * NULL and a @a res of #GNUNET_OK. Thus, to indicate conversion | ||
846 | * errors, the callback might be called first with @a address NULL and | ||
847 | * @a res being #GNUNET_SYSERR. In that case, there will still be a | ||
848 | * subsequent call later with @a address NULL and @a res #GNUNET_OK. | ||
849 | * | ||
850 | * @param cls the `struct AddressToStringContext` | ||
851 | * @param buf text to transmit (contains the human-readable address, or NULL) | ||
852 | * @param res #GNUNET_OK if conversion was successful, #GNUNET_SYSERR on error, | ||
853 | * never #GNUNET_NO | ||
854 | */ | ||
855 | static void | ||
856 | transmit_address_to_client (void *cls, | ||
857 | const char *buf, | ||
858 | int res) | ||
859 | { | ||
860 | struct AddressToStringContext *actx = cls; | ||
861 | struct GNUNET_MQ_Envelope *env; | ||
862 | struct AddressToStringResultMessage *atsm; | ||
863 | size_t slen; | ||
864 | |||
865 | GNUNET_assert ( (GNUNET_OK == res) || | ||
866 | (GNUNET_SYSERR == res) ); | ||
867 | if (NULL == buf) | ||
868 | { | ||
869 | env = GNUNET_MQ_msg (atsm, | ||
870 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
871 | if (GNUNET_OK == res) | ||
872 | { | ||
873 | /* this was the last call, transmit */ | ||
874 | atsm->res = htonl (GNUNET_OK); | ||
875 | atsm->addr_len = htonl (0); | ||
876 | GNUNET_MQ_send (actx->tc->mq, | ||
877 | env); | ||
878 | GNUNET_CONTAINER_DLL_remove (a2s_head, | ||
879 | a2s_tail, | ||
880 | actx); | ||
881 | return; | ||
882 | } | ||
883 | if (GNUNET_SYSERR == res) | ||
884 | { | ||
885 | /* address conversion failed, but there will be more callbacks */ | ||
886 | atsm->res = htonl (GNUNET_SYSERR); | ||
887 | atsm->addr_len = htonl (0); | ||
888 | GNUNET_MQ_send (actx->tc->mq, | ||
889 | env); | ||
890 | return; | ||
891 | } | ||
892 | } | ||
893 | GNUNET_assert (GNUNET_OK == res); | ||
894 | /* succesful conversion, append*/ | ||
895 | slen = strlen (buf) + 1; | ||
896 | env = GNUNET_MQ_msg_extra (atsm, | ||
897 | slen, | ||
898 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
899 | atsm->res = htonl (GNUNET_YES); | ||
900 | atsm->addr_len = htonl (slen); | ||
901 | GNUNET_memcpy (&atsm[1], | ||
902 | buf, | ||
903 | slen); | ||
904 | GNUNET_MQ_send (actx->tc->mq, | ||
905 | env); | ||
906 | } | ||
907 | |||
908 | |||
909 | /** | ||
910 | * Client asked to resolve an address. Check the request. | ||
911 | * | ||
912 | * @param cls the client | ||
913 | * @param alum the resolution request | ||
914 | * @return #GNUNET_OK if @a alum is well-formed | ||
915 | */ | ||
916 | static int | ||
917 | check_client_address_to_string (void *cls, | ||
918 | const struct AddressLookupMessage *alum) | ||
919 | { | ||
920 | const char *plugin_name; | ||
921 | const char *address; | ||
922 | uint32_t address_len; | ||
923 | uint16_t size; | ||
924 | |||
925 | size = ntohs (alum->header.size); | ||
926 | address_len = ntohs (alum->addrlen); | ||
927 | if (size <= sizeof (struct AddressLookupMessage) + address_len) | ||
928 | { | ||
929 | GNUNET_break (0); | ||
930 | return GNUNET_SYSERR; | ||
931 | } | ||
932 | address = (const char *) &alum[1]; | ||
933 | plugin_name = (const char *) &address[address_len]; | ||
934 | if ('\0' != plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1]) | ||
935 | { | ||
936 | GNUNET_break (0); | ||
937 | return GNUNET_SYSERR; | ||
938 | } | ||
939 | return GNUNET_OK; | ||
940 | } | ||
941 | |||
942 | |||
943 | /** | ||
944 | * Client asked to resolve an address. Process the request. | ||
945 | * | ||
946 | * @param cls the client | ||
947 | * @param alum the resolution request | ||
948 | */ | ||
949 | static void | ||
950 | handle_client_address_to_string (void *cls, | ||
951 | const struct AddressLookupMessage *alum) | ||
952 | { | ||
953 | struct TransportClient *tc = cls; | ||
954 | struct GNUNET_TRANSPORT_PluginFunctions *papi; | ||
955 | const char *plugin_name; | ||
956 | const char *address; | ||
957 | uint32_t address_len; | ||
958 | struct AddressToStringContext *actx; | ||
959 | struct GNUNET_MQ_Envelope *env; | ||
960 | struct AddressToStringResultMessage *atsm; | ||
961 | struct GNUNET_TIME_Relative rtimeout; | ||
962 | int32_t numeric; | ||
963 | |||
964 | address_len = ntohs (alum->addrlen); | ||
965 | address = (const char *) &alum[1]; | ||
966 | plugin_name = (const char *) &address[address_len]; | ||
967 | rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout); | ||
968 | numeric = ntohs (alum->numeric_only); | ||
969 | papi = GST_plugins_printer_find (plugin_name); | ||
970 | if (NULL == papi) | ||
971 | { | ||
972 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
973 | "Failed to find plugin `%s'\n", | ||
974 | plugin_name); | ||
975 | env = GNUNET_MQ_msg (atsm, | ||
976 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
977 | atsm->res = htonl (GNUNET_SYSERR); | ||
978 | atsm->addr_len = htonl (0); | ||
979 | GNUNET_MQ_send (tc->mq, | ||
980 | env); | ||
981 | env = GNUNET_MQ_msg (atsm, | ||
982 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY); | ||
983 | atsm->res = htonl (GNUNET_OK); | ||
984 | atsm->addr_len = htonl (0); | ||
985 | GNUNET_MQ_send (tc->mq, | ||
986 | env); | ||
987 | return; | ||
988 | } | ||
989 | actx = GNUNET_new (struct AddressToStringContext); | ||
990 | actx->tc = tc; | ||
991 | GNUNET_CONTAINER_DLL_insert (a2s_head, | ||
992 | a2s_tail, | ||
993 | actx); | ||
994 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
995 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
996 | "Pretty-printing address of %u bytes using plugin `%s'\n", | ||
997 | address_len, | ||
998 | plugin_name); | ||
999 | papi->address_pretty_printer (papi->cls, | ||
1000 | plugin_name, | ||
1001 | address, | ||
1002 | address_len, | ||
1003 | numeric, | ||
1004 | rtimeout, | ||
1005 | &transmit_address_to_client, | ||
1006 | actx); | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * Compose #PeerIterateResponseMessage using the given peer and address. | ||
1012 | * | ||
1013 | * @param peer identity of the peer | ||
1014 | * @param address the address, NULL on disconnect | ||
1015 | * @return composed message | ||
1016 | */ | ||
1017 | static struct PeerIterateResponseMessage * | ||
1018 | compose_address_iterate_response_message (const struct GNUNET_PeerIdentity *peer, | ||
1019 | const struct GNUNET_HELLO_Address *address) | ||
1020 | { | ||
1021 | struct PeerIterateResponseMessage *msg; | ||
1022 | size_t size; | ||
1023 | size_t tlen; | ||
1024 | size_t alen; | ||
1025 | char *addr; | ||
1026 | |||
1027 | GNUNET_assert (NULL != peer); | ||
1028 | if (NULL != address) | ||
1029 | { | ||
1030 | tlen = strlen (address->transport_name) + 1; | ||
1031 | alen = address->address_length; | ||
1032 | } | ||
1033 | else | ||
1034 | { | ||
1035 | tlen = 0; | ||
1036 | alen = 0; | ||
1037 | } | ||
1038 | size = (sizeof (struct PeerIterateResponseMessage) + alen + tlen); | ||
1039 | msg = GNUNET_malloc (size); | ||
1040 | msg->header.size = htons (size); | ||
1041 | msg->header.type | ||
1042 | = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE); | ||
1043 | msg->reserved = htonl (0); | ||
1044 | msg->peer = *peer; | ||
1045 | msg->addrlen = htonl (alen); | ||
1046 | msg->pluginlen = htonl (tlen); | ||
1047 | |||
1048 | if (NULL != address) | ||
1049 | { | ||
1050 | msg->local_address_info = htonl((uint32_t) address->local_info); | ||
1051 | addr = (char *) &msg[1]; | ||
1052 | GNUNET_memcpy (addr, | ||
1053 | address->address, | ||
1054 | alen); | ||
1055 | GNUNET_memcpy (&addr[alen], | ||
1056 | address->transport_name, | ||
1057 | tlen); | ||
1058 | } | ||
1059 | return msg; | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /** | ||
1064 | * Context for #send_validation_information() and | ||
1065 | * #send_peer_information(). | ||
1066 | */ | ||
1067 | struct IterationContext | ||
1068 | { | ||
1069 | /** | ||
1070 | * Context to use for the transmission. | ||
1071 | */ | ||
1072 | struct TransportClient *tc; | ||
1073 | |||
1074 | /** | ||
1075 | * Which peers do we care about? | ||
1076 | */ | ||
1077 | struct GNUNET_PeerIdentity id; | ||
1078 | |||
1079 | /** | ||
1080 | * #GNUNET_YES if @e id should be ignored because we want all peers. | ||
1081 | */ | ||
1082 | int all; | ||
1083 | }; | ||
1084 | |||
1085 | |||
1086 | /** | ||
1087 | * Output information of neighbours to the given client. | ||
1088 | * | ||
1089 | * @param cls the `struct PeerIterationContext *` | ||
1090 | * @param peer identity of the neighbour | ||
1091 | * @param address the address | ||
1092 | * @param state current state this peer is in | ||
1093 | * @param state_timeout timeout for the current state of the peer | ||
1094 | * @param bandwidth_in inbound quota in NBO | ||
1095 | * @param bandwidth_out outbound quota in NBO | ||
1096 | */ | ||
1097 | static void | ||
1098 | send_peer_information (void *cls, | ||
1099 | const struct GNUNET_PeerIdentity *peer, | ||
1100 | const struct GNUNET_HELLO_Address *address, | ||
1101 | enum GNUNET_TRANSPORT_PeerState state, | ||
1102 | struct GNUNET_TIME_Absolute state_timeout, | ||
1103 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
1104 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
1105 | { | ||
1106 | struct IterationContext *pc = cls; | ||
1107 | struct GNUNET_MQ_Envelope *env; | ||
1108 | struct PeerIterateResponseMessage *msg; | ||
1109 | |||
1110 | if ( (GNUNET_YES != pc->all) && | ||
1111 | (0 != memcmp (peer, | ||
1112 | &pc->id, | ||
1113 | sizeof (pc->id))) ) | ||
1114 | return; | ||
1115 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1116 | "Sending information about `%s' using address `%s' in state `%s'\n", | ||
1117 | GNUNET_i2s(peer), | ||
1118 | (NULL != address) ? GST_plugins_a2s (address) : "<none>", | ||
1119 | GNUNET_TRANSPORT_ps2s (state)); | ||
1120 | msg = compose_address_iterate_response_message (peer, | ||
1121 | address); | ||
1122 | msg->state = htonl (state); | ||
1123 | msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout); | ||
1124 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1125 | GNUNET_free (msg); | ||
1126 | GNUNET_MQ_send (pc->tc->mq, | ||
1127 | env); | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /** | ||
1132 | * Client asked to obtain information about a specific or all peers | ||
1133 | * Process the request. | ||
1134 | * | ||
1135 | * @param cls the client | ||
1136 | * @param msg the peer address information request | ||
1137 | */ | ||
1138 | static void | ||
1139 | handle_client_monitor_peers (void *cls, | ||
1140 | const struct PeerMonitorMessage *msg) | ||
1141 | { | ||
1142 | struct TransportClient *tc = cls; | ||
1143 | struct IterationContext pc; | ||
1144 | |||
1145 | if (CT_NONE != tc->type) | ||
1146 | { | ||
1147 | GNUNET_break (0); | ||
1148 | GNUNET_SERVICE_client_drop (tc->client); | ||
1149 | return; | ||
1150 | } | ||
1151 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
1152 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
1153 | |||
1154 | /* Send initial list */ | ||
1155 | pc.tc = tc; | ||
1156 | if (0 == memcmp (&msg->peer, | ||
1157 | &all_zeros, | ||
1158 | sizeof (struct GNUNET_PeerIdentity))) | ||
1159 | { | ||
1160 | /* iterate over all neighbours */ | ||
1161 | pc.all = GNUNET_YES; | ||
1162 | pc.id = msg->peer; | ||
1163 | } | ||
1164 | else | ||
1165 | { | ||
1166 | /* just return one neighbour */ | ||
1167 | pc.all = GNUNET_NO; | ||
1168 | pc.id = msg->peer; | ||
1169 | } | ||
1170 | GST_neighbours_iterate (&send_peer_information, | ||
1171 | &pc); | ||
1172 | |||
1173 | if (GNUNET_YES != ntohl (msg->one_shot)) | ||
1174 | { | ||
1175 | tc->details.monitor_peer = msg->peer; | ||
1176 | tc->type = CT_MONITOR; | ||
1177 | if (0 != memcmp (&msg->peer, | ||
1178 | &all_zeros, | ||
1179 | sizeof (struct GNUNET_PeerIdentity))) | ||
1180 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1181 | "Client %p started monitoring of the peer `%s'\n", | ||
1182 | tc, | ||
1183 | GNUNET_i2s (&msg->peer)); | ||
1184 | else | ||
1185 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1186 | "Client %p started monitoring all peers\n", | ||
1187 | tc); | ||
1188 | } | ||
1189 | else | ||
1190 | { | ||
1191 | struct GNUNET_MessageHeader *msg; | ||
1192 | struct GNUNET_MQ_Envelope *env; | ||
1193 | |||
1194 | env = GNUNET_MQ_msg (msg, | ||
1195 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE_END); | ||
1196 | GNUNET_MQ_send (tc->mq, | ||
1197 | env); | ||
1198 | } | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Function called by the plugin with information about the | ||
1204 | * current sessions managed by the plugin (for monitoring). | ||
1205 | * | ||
1206 | * @param cls closure | ||
1207 | * @param session session handle this information is about, | ||
1208 | * NULL to indicate that we are "in sync" (initial | ||
1209 | * iteration complete) | ||
1210 | * @param info information about the state of the session, | ||
1211 | * NULL if @a session is also NULL and we are | ||
1212 | * merely signalling that the initial iteration is over | ||
1213 | */ | ||
1214 | static void | ||
1215 | plugin_session_info_cb (void *cls, | ||
1216 | struct GNUNET_ATS_Session *session, | ||
1217 | const struct GNUNET_TRANSPORT_SessionInfo *info) | ||
1218 | { | ||
1219 | struct GNUNET_MQ_Envelope *env; | ||
1220 | struct TransportPluginMonitorMessage *msg; | ||
1221 | struct GNUNET_MessageHeader *sync; | ||
1222 | size_t size; | ||
1223 | size_t slen; | ||
1224 | uint16_t alen; | ||
1225 | char *name; | ||
1226 | char *addr; | ||
1227 | |||
1228 | if (0 == GNUNET_notification_context_get_size (plugin_nc)) | ||
1229 | { | ||
1230 | GST_plugins_monitor_subscribe (NULL, | ||
1231 | NULL); | ||
1232 | return; | ||
1233 | } | ||
1234 | if ( (NULL == info) && | ||
1235 | (NULL == session) ) | ||
1236 | { | ||
1237 | /* end of initial iteration */ | ||
1238 | if (NULL != sync_client) | ||
1239 | { | ||
1240 | env = GNUNET_MQ_msg (sync, | ||
1241 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_SYNC); | ||
1242 | GNUNET_MQ_send (sync_client->mq, | ||
1243 | env); | ||
1244 | sync_client = NULL; | ||
1245 | } | ||
1246 | return; | ||
1247 | } | ||
1248 | GNUNET_assert (NULL != info); | ||
1249 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1250 | "Plugin event for peer %s on transport %s\n", | ||
1251 | GNUNET_i2s (&info->address->peer), | ||
1252 | info->address->transport_name); | ||
1253 | slen = strlen (info->address->transport_name) + 1; | ||
1254 | alen = info->address->address_length; | ||
1255 | size = sizeof (struct TransportPluginMonitorMessage) + slen + alen; | ||
1256 | if (size > UINT16_MAX) | ||
1257 | { | ||
1258 | GNUNET_break (0); | ||
1259 | return; | ||
1260 | } | ||
1261 | msg = GNUNET_malloc (size); | ||
1262 | msg->header.size = htons (size); | ||
1263 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_EVENT); | ||
1264 | msg->session_state = htons ((uint16_t) info->state); | ||
1265 | msg->is_inbound = htons ((int16_t) info->is_inbound); | ||
1266 | msg->msgs_pending = htonl (info->num_msg_pending); | ||
1267 | msg->bytes_pending = htonl (info->num_bytes_pending); | ||
1268 | msg->timeout = GNUNET_TIME_absolute_hton (info->session_timeout); | ||
1269 | msg->delay = GNUNET_TIME_absolute_hton (info->receive_delay); | ||
1270 | msg->peer = info->address->peer; | ||
1271 | msg->session_id = (uint64_t) (intptr_t) session; | ||
1272 | msg->plugin_name_len = htons (slen); | ||
1273 | msg->plugin_address_len = htons (alen); | ||
1274 | name = (char *) &msg[1]; | ||
1275 | GNUNET_memcpy (name, | ||
1276 | info->address->transport_name, | ||
1277 | slen); | ||
1278 | addr = &name[slen]; | ||
1279 | GNUNET_memcpy (addr, | ||
1280 | info->address->address, | ||
1281 | alen); | ||
1282 | if (NULL != sync_client) | ||
1283 | { | ||
1284 | struct GNUNET_MQ_Envelope *env; | ||
1285 | |||
1286 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1287 | GNUNET_MQ_send (sync_client->mq, | ||
1288 | env); | ||
1289 | } | ||
1290 | else | ||
1291 | { | ||
1292 | GNUNET_notification_context_broadcast (plugin_nc, | ||
1293 | &msg->header, | ||
1294 | GNUNET_NO); | ||
1295 | } | ||
1296 | GNUNET_free (msg); | ||
1297 | } | ||
1298 | |||
1299 | |||
1300 | /** | ||
1301 | * Client asked to obtain information about all plugin connections. | ||
1302 | * | ||
1303 | * @param cls the client | ||
1304 | * @param message the peer address information request | ||
1305 | */ | ||
1306 | static void | ||
1307 | handle_client_monitor_plugins (void *cls, | ||
1308 | const struct GNUNET_MessageHeader *message) | ||
1309 | { | ||
1310 | struct TransportClient *tc = cls; | ||
1311 | |||
1312 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
1313 | GNUNET_SERVICE_client_disable_continue_warning (tc->client); | ||
1314 | GNUNET_notification_context_add (plugin_nc, | ||
1315 | tc->mq); | ||
1316 | GNUNET_assert (NULL == sync_client); | ||
1317 | sync_client = tc; | ||
1318 | GST_plugins_monitor_subscribe (&plugin_session_info_cb, | ||
1319 | NULL); | ||
1320 | } | ||
1321 | |||
1322 | |||
1323 | /** | ||
1324 | * Broadcast the given message to all of our clients. | ||
1325 | * | ||
1326 | * @param msg message to broadcast | ||
1327 | * @param may_drop #GNUNET_YES if the message can be dropped / is payload | ||
1328 | */ | ||
1329 | void | ||
1330 | GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, | ||
1331 | int may_drop) | ||
1332 | { | ||
1333 | struct TransportClient *tc; | ||
1334 | int done; | ||
1335 | |||
1336 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1337 | "Asked to broadcast message of type %u with %u bytes\n", | ||
1338 | (unsigned int) ntohs (msg->type), | ||
1339 | (unsigned int) ntohs (msg->size)); | ||
1340 | done = GNUNET_NO; | ||
1341 | for (tc = clients_head; NULL != tc; tc = tc->next) | ||
1342 | { | ||
1343 | if ( (GNUNET_YES == may_drop) && | ||
1344 | (CT_CORE != tc->type) ) | ||
1345 | continue; /* skip, this client does not care about payload */ | ||
1346 | unicast (tc, | ||
1347 | msg, | ||
1348 | may_drop); | ||
1349 | done = GNUNET_YES; | ||
1350 | } | ||
1351 | if (GNUNET_NO == done) | ||
1352 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1353 | "Message of type %u not delivered, is CORE service up?\n", | ||
1354 | ntohs (msg->type)); | ||
1355 | } | ||
1356 | |||
1357 | |||
1358 | /** | ||
1359 | * Broadcast the new active address to all clients monitoring the peer. | ||
1360 | * | ||
1361 | * @param peer peer this update is about (never NULL) | ||
1362 | * @param address address, NULL on disconnect | ||
1363 | * @param state the current state of the peer | ||
1364 | * @param state_timeout the time out for the state | ||
1365 | */ | ||
1366 | void | ||
1367 | GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer, | ||
1368 | const struct GNUNET_HELLO_Address *address, | ||
1369 | enum GNUNET_TRANSPORT_PeerState state, | ||
1370 | struct GNUNET_TIME_Absolute state_timeout) | ||
1371 | { | ||
1372 | struct GNUNET_MQ_Envelope *env; | ||
1373 | struct PeerIterateResponseMessage *msg; | ||
1374 | struct TransportClient *tc; | ||
1375 | |||
1376 | msg = compose_address_iterate_response_message (peer, | ||
1377 | address); | ||
1378 | msg->state = htonl (state); | ||
1379 | msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout); | ||
1380 | for (tc = clients_head; NULL != tc; tc = tc->next) | ||
1381 | { | ||
1382 | if (CT_MONITOR != tc->type) | ||
1383 | continue; | ||
1384 | if ((0 == memcmp (&tc->details.monitor_peer, | ||
1385 | &all_zeros, | ||
1386 | sizeof (struct GNUNET_PeerIdentity))) || | ||
1387 | (0 == memcmp (&tc->details.monitor_peer, | ||
1388 | peer, | ||
1389 | sizeof (struct GNUNET_PeerIdentity)))) | ||
1390 | { | ||
1391 | env = GNUNET_MQ_msg_copy (&msg->header); | ||
1392 | GNUNET_MQ_send (tc->mq, | ||
1393 | env); | ||
1394 | } | ||
1395 | } | ||
1396 | GNUNET_free (msg); | ||
1397 | } | ||
1398 | |||
1399 | |||
1400 | /** | ||
1401 | * Mark the peer as down so we don't call the continuation | ||
1402 | * context in the future. | ||
1403 | * | ||
1404 | * @param cls NULL | ||
1405 | * @param peer peer that got disconnected | ||
1406 | * @param value a `struct SendTransmitContinuationContext` to mark | ||
1407 | * @return #GNUNET_OK (continue to iterate) | ||
1408 | */ | ||
1409 | static int | ||
1410 | mark_peer_down (void *cls, | ||
1411 | const struct GNUNET_PeerIdentity *peer, | ||
1412 | void *value) | ||
1413 | { | ||
1414 | struct SendTransmitContinuationContext *stcc = value; | ||
1415 | |||
1416 | stcc->down = GNUNET_YES; | ||
1417 | return GNUNET_OK; | ||
1418 | } | ||
1419 | |||
1420 | |||
1421 | /** | ||
1422 | * Notify all clients about a disconnect, and cancel | ||
1423 | * pending SEND_OK messages for this peer. | ||
1424 | * | ||
1425 | * @param peer peer that disconnected | ||
1426 | */ | ||
1427 | void | ||
1428 | GST_clients_broadcast_disconnect (const struct GNUNET_PeerIdentity *peer) | ||
1429 | { | ||
1430 | struct DisconnectInfoMessage disconnect_msg; | ||
1431 | |||
1432 | GNUNET_CONTAINER_multipeermap_get_multiple (active_stccs, | ||
1433 | peer, | ||
1434 | &mark_peer_down, | ||
1435 | NULL); | ||
1436 | disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage)); | ||
1437 | disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT); | ||
1438 | disconnect_msg.reserved = htonl (0); | ||
1439 | disconnect_msg.peer = *peer; | ||
1440 | GST_clients_broadcast (&disconnect_msg.header, | ||
1441 | GNUNET_NO); | ||
1442 | |||
1443 | } | ||
1444 | |||
1445 | |||
1446 | /** | ||
140 | * Transmit our HELLO message to the given (connected) neighbour. | 1447 | * Transmit our HELLO message to the given (connected) neighbour. |
141 | * | 1448 | * |
142 | * @param cls the 'HELLO' message | 1449 | * @param cls the 'HELLO' message |
@@ -170,7 +1477,8 @@ transmit_our_hello (void *cls, | |||
170 | hello, | 1477 | hello, |
171 | ntohs (hello->size), | 1478 | ntohs (hello->size), |
172 | hello_expiration, | 1479 | hello_expiration, |
173 | NULL, NULL); | 1480 | NULL, |
1481 | NULL); | ||
174 | } | 1482 | } |
175 | 1483 | ||
176 | 1484 | ||
@@ -240,8 +1548,11 @@ process_payload (const struct GNUNET_HELLO_Address *address, | |||
240 | im->header.size = htons (size); | 1548 | im->header.size = htons (size); |
241 | im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); | 1549 | im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV); |
242 | im->peer = address->peer; | 1550 | im->peer = address->peer; |
243 | GNUNET_memcpy (&im[1], message, ntohs (message->size)); | 1551 | GNUNET_memcpy (&im[1], |
244 | GST_clients_broadcast (&im->header, GNUNET_YES); | 1552 | message, |
1553 | ntohs (message->size)); | ||
1554 | GST_clients_broadcast (&im->header, | ||
1555 | GNUNET_YES); | ||
245 | return ret; | 1556 | return ret; |
246 | } | 1557 | } |
247 | 1558 | ||
@@ -257,8 +1568,11 @@ kill_session_task (void *cls) | |||
257 | struct GNUNET_ATS_SessionKiller *sk = cls; | 1568 | struct GNUNET_ATS_SessionKiller *sk = cls; |
258 | 1569 | ||
259 | sk->task = NULL; | 1570 | sk->task = NULL; |
260 | GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk); | 1571 | GNUNET_CONTAINER_DLL_remove (sk_head, |
261 | sk->plugin->disconnect_session (sk->plugin->cls, sk->session); | 1572 | sk_tail, |
1573 | sk); | ||
1574 | sk->plugin->disconnect_session (sk->plugin->cls, | ||
1575 | sk->session); | ||
262 | GNUNET_free(sk); | 1576 | GNUNET_free(sk); |
263 | } | 1577 | } |
264 | 1578 | ||
@@ -290,7 +1604,8 @@ kill_session (const char *plugin_name, | |||
290 | sk = GNUNET_new (struct GNUNET_ATS_SessionKiller); | 1604 | sk = GNUNET_new (struct GNUNET_ATS_SessionKiller); |
291 | sk->session = session; | 1605 | sk->session = session; |
292 | sk->plugin = plugin; | 1606 | sk->plugin = plugin; |
293 | sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, sk); | 1607 | sk->task = GNUNET_SCHEDULER_add_now (&kill_session_task, |
1608 | sk); | ||
294 | GNUNET_CONTAINER_DLL_insert (sk_head, | 1609 | GNUNET_CONTAINER_DLL_insert (sk_head, |
295 | sk_tail, | 1610 | sk_tail, |
296 | sk); | 1611 | sk); |
@@ -418,7 +1733,9 @@ GST_receive_callback (void *cls, | |||
418 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 1733 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
419 | "Processing PONG from `%s'\n", | 1734 | "Processing PONG from `%s'\n", |
420 | GST_plugins_a2s (address)); | 1735 | GST_plugins_a2s (address)); |
421 | if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message)) | 1736 | if (GNUNET_OK != |
1737 | GST_validation_handle_pong (&address->peer, | ||
1738 | message)) | ||
422 | { | 1739 | { |
423 | GNUNET_break_op (0); | 1740 | GNUNET_break_op (0); |
424 | GST_blacklist_abort_matching (address, | 1741 | GST_blacklist_abort_matching (address, |
@@ -508,12 +1825,11 @@ plugin_env_address_change_notification (void *cls, | |||
508 | const struct GNUNET_HELLO_Address *address) | 1825 | const struct GNUNET_HELLO_Address *address) |
509 | { | 1826 | { |
510 | static int addresses = 0; | 1827 | static int addresses = 0; |
511 | struct GNUNET_STATISTICS_Handle *cfg = GST_stats; | ||
512 | 1828 | ||
513 | if (GNUNET_YES == add_remove) | 1829 | if (GNUNET_YES == add_remove) |
514 | { | 1830 | { |
515 | addresses ++; | 1831 | addresses ++; |
516 | GNUNET_STATISTICS_update (cfg, | 1832 | GNUNET_STATISTICS_update (GST_stats, |
517 | "# transport addresses", | 1833 | "# transport addresses", |
518 | 1, | 1834 | 1, |
519 | GNUNET_NO); | 1835 | GNUNET_NO); |
@@ -527,7 +1843,7 @@ plugin_env_address_change_notification (void *cls, | |||
527 | else | 1843 | else |
528 | { | 1844 | { |
529 | addresses --; | 1845 | addresses --; |
530 | GNUNET_STATISTICS_update (cfg, | 1846 | GNUNET_STATISTICS_update (GST_stats, |
531 | "# transport addresses", | 1847 | "# transport addresses", |
532 | -1, | 1848 | -1, |
533 | GNUNET_NO); | 1849 | GNUNET_NO); |
@@ -579,16 +1895,20 @@ plugin_env_session_end (void *cls, | |||
579 | GNUNET_i2s (&address->peer), | 1895 | GNUNET_i2s (&address->peer), |
580 | GST_plugins_a2s (address)); | 1896 | GST_plugins_a2s (address)); |
581 | 1897 | ||
582 | GST_neighbours_session_terminated (&address->peer, session); | 1898 | GST_neighbours_session_terminated (&address->peer, |
1899 | session); | ||
583 | GST_ats_del_session (address, | 1900 | GST_ats_del_session (address, |
584 | session); | 1901 | session); |
585 | GST_blacklist_abort_matching (address, session); | 1902 | GST_blacklist_abort_matching (address, |
1903 | session); | ||
586 | 1904 | ||
587 | for (sk = sk_head; NULL != sk; sk = sk->next) | 1905 | for (sk = sk_head; NULL != sk; sk = sk->next) |
588 | { | 1906 | { |
589 | if (sk->session == session) | 1907 | if (sk->session == session) |
590 | { | 1908 | { |
591 | GNUNET_CONTAINER_DLL_remove (sk_head, sk_tail, sk); | 1909 | GNUNET_CONTAINER_DLL_remove (sk_head, |
1910 | sk_tail, | ||
1911 | sk); | ||
592 | GNUNET_SCHEDULER_cancel (sk->task); | 1912 | GNUNET_SCHEDULER_cancel (sk->task); |
593 | GNUNET_free(sk); | 1913 | GNUNET_free(sk); |
594 | break; | 1914 | break; |
@@ -672,7 +1992,9 @@ plugin_env_session_start (void *cls, | |||
672 | for example for UNIX, we have symmetric connections and thus we | 1992 | for example for UNIX, we have symmetric connections and thus we |
673 | may not know the address yet; add if necessary! */ | 1993 | may not know the address yet; add if necessary! */ |
674 | /* FIXME: maybe change API here so we just pass scope? */ | 1994 | /* FIXME: maybe change API here so we just pass scope? */ |
675 | memset (&prop, 0, sizeof (prop)); | 1995 | memset (&prop, |
1996 | 0, | ||
1997 | sizeof (prop)); | ||
676 | GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != scope); | 1998 | GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != scope); |
677 | prop.scope = scope; | 1999 | prop.scope = scope; |
678 | GST_ats_add_inbound_address (address, | 2000 | GST_ats_add_inbound_address (address, |
@@ -750,6 +2072,167 @@ ats_request_address_change (void *cls, | |||
750 | 2072 | ||
751 | 2073 | ||
752 | /** | 2074 | /** |
2075 | * Closure for #test_connection_ok(). | ||
2076 | */ | ||
2077 | struct TestConnectionContext | ||
2078 | { | ||
2079 | /** | ||
2080 | * Is this the first neighbour we're checking? | ||
2081 | */ | ||
2082 | int first; | ||
2083 | |||
2084 | /** | ||
2085 | * Handle to the blacklisting client we need to ask. | ||
2086 | */ | ||
2087 | struct TransportClient *tc; | ||
2088 | }; | ||
2089 | |||
2090 | |||
2091 | /** | ||
2092 | * Got the result about an existing connection from a new blacklister. | ||
2093 | * Shutdown the neighbour if necessary. | ||
2094 | * | ||
2095 | * @param cls unused | ||
2096 | * @param peer the neighbour that was investigated | ||
2097 | * @param address address associated with the request | ||
2098 | * @param session session associated with the request | ||
2099 | * @param allowed #GNUNET_OK if we can keep it, | ||
2100 | * #GNUNET_NO if we must shutdown the connection | ||
2101 | */ | ||
2102 | static void | ||
2103 | confirm_or_drop_neighbour (void *cls, | ||
2104 | const struct GNUNET_PeerIdentity *peer, | ||
2105 | const struct GNUNET_HELLO_Address *address, | ||
2106 | struct GNUNET_ATS_Session *session, | ||
2107 | int allowed) | ||
2108 | { | ||
2109 | if (GNUNET_OK == allowed) | ||
2110 | return; /* we're done */ | ||
2111 | GNUNET_STATISTICS_update (GST_stats, | ||
2112 | gettext_noop ("# disconnects due to blacklist"), | ||
2113 | 1, | ||
2114 | GNUNET_NO); | ||
2115 | GST_neighbours_force_disconnect (peer); | ||
2116 | } | ||
2117 | |||
2118 | |||
2119 | /** | ||
2120 | * Test if an existing connection is still acceptable given a new | ||
2121 | * blacklisting client. | ||
2122 | * | ||
2123 | * @param cls the `struct TestConnectionContext *` | ||
2124 | * @param peer identity of the peer | ||
2125 | * @param address the address | ||
2126 | * @param state current state this peer is in | ||
2127 | * @param state_timeout timeout for the current state of the peer | ||
2128 | * @param bandwidth_in bandwidth assigned inbound | ||
2129 | * @param bandwidth_out bandwidth assigned outbound | ||
2130 | */ | ||
2131 | static void | ||
2132 | test_connection_ok (void *cls, | ||
2133 | const struct GNUNET_PeerIdentity *peer, | ||
2134 | const struct GNUNET_HELLO_Address *address, | ||
2135 | enum GNUNET_TRANSPORT_PeerState state, | ||
2136 | struct GNUNET_TIME_Absolute state_timeout, | ||
2137 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
2138 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out) | ||
2139 | { | ||
2140 | struct TestConnectionContext *tcc = cls; | ||
2141 | struct GST_BlacklistCheck *bc; | ||
2142 | |||
2143 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
2144 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
2145 | bc_tail, | ||
2146 | bc); | ||
2147 | bc->peer = *peer; | ||
2148 | bc->address = GNUNET_HELLO_address_copy (address); | ||
2149 | bc->cont = &confirm_or_drop_neighbour; | ||
2150 | bc->cont_cls = NULL; | ||
2151 | bc->bl_pos = tcc->tc; | ||
2152 | if (GNUNET_YES == tcc->first) | ||
2153 | { | ||
2154 | /* all would wait for the same client, no need to | ||
2155 | * create more than just the first task right now */ | ||
2156 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
2157 | bc); | ||
2158 | tcc->first = GNUNET_NO; | ||
2159 | } | ||
2160 | } | ||
2161 | |||
2162 | |||
2163 | /** | ||
2164 | * Initialize a blacklisting client. We got a blacklist-init | ||
2165 | * message from this client, add him to the list of clients | ||
2166 | * to query for blacklisting. | ||
2167 | * | ||
2168 | * @param cls the client | ||
2169 | * @param message the blacklist-init message that was sent | ||
2170 | */ | ||
2171 | static void | ||
2172 | handle_client_blacklist_init (void *cls, | ||
2173 | const struct GNUNET_MessageHeader *message) | ||
2174 | { | ||
2175 | struct TransportClient *tc = cls; | ||
2176 | struct TestConnectionContext tcc; | ||
2177 | |||
2178 | if (CT_NONE != tc->type) | ||
2179 | { | ||
2180 | GNUNET_break (0); | ||
2181 | GNUNET_SERVICE_client_drop (tc->client); | ||
2182 | return; | ||
2183 | } | ||
2184 | GNUNET_SERVICE_client_mark_monitor (tc->client); | ||
2185 | tc->type = CT_BLACKLIST; | ||
2186 | tc->details.blacklist.call_receive_done = GNUNET_YES; | ||
2187 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2188 | "New blacklist client %p\n", | ||
2189 | tc); | ||
2190 | /* confirm that all existing connections are OK! */ | ||
2191 | tcc.tc = tc; | ||
2192 | tcc.first = GNUNET_YES; | ||
2193 | GST_neighbours_iterate (&test_connection_ok, | ||
2194 | &tcc); | ||
2195 | } | ||
2196 | |||
2197 | |||
2198 | /** | ||
2199 | * Free the given entry in the blacklist. | ||
2200 | * | ||
2201 | * @param cls unused | ||
2202 | * @param key host identity (unused) | ||
2203 | * @param value the blacklist entry | ||
2204 | * @return #GNUNET_OK (continue to iterate) | ||
2205 | */ | ||
2206 | static int | ||
2207 | free_blacklist_entry (void *cls, | ||
2208 | const struct GNUNET_PeerIdentity *key, | ||
2209 | void *value) | ||
2210 | { | ||
2211 | char *be = value; | ||
2212 | |||
2213 | GNUNET_free_non_null (be); | ||
2214 | return GNUNET_OK; | ||
2215 | } | ||
2216 | |||
2217 | |||
2218 | /** | ||
2219 | * Set traffic metric to manipulate | ||
2220 | * | ||
2221 | * @param cls closure | ||
2222 | * @param message containing information | ||
2223 | */ | ||
2224 | static void | ||
2225 | handle_client_set_metric (void *cls, | ||
2226 | const struct TrafficMetricMessage *tm) | ||
2227 | { | ||
2228 | struct TransportClient *tc = cls; | ||
2229 | |||
2230 | GST_manipulation_set_metric (tm); | ||
2231 | GNUNET_SERVICE_client_continue (tc->client); | ||
2232 | } | ||
2233 | |||
2234 | |||
2235 | /** | ||
753 | * Function called when the service shuts down. Unloads our plugins | 2236 | * Function called when the service shuts down. Unloads our plugins |
754 | * and cancels pending validations. | 2237 | * and cancels pending validations. |
755 | * | 2238 | * |
@@ -758,6 +2241,8 @@ ats_request_address_change (void *cls, | |||
758 | static void | 2241 | static void |
759 | shutdown_task (void *cls) | 2242 | shutdown_task (void *cls) |
760 | { | 2243 | { |
2244 | struct AddressToStringContext *cur; | ||
2245 | |||
761 | GST_neighbours_stop (); | 2246 | GST_neighbours_stop (); |
762 | GST_plugins_unload (); | 2247 | GST_plugins_unload (); |
763 | GST_validation_stop (); | 2248 | GST_validation_stop (); |
@@ -768,8 +2253,28 @@ shutdown_task (void *cls) | |||
768 | GST_ats_connect = NULL; | 2253 | GST_ats_connect = NULL; |
769 | GNUNET_ATS_scanner_done (GST_is); | 2254 | GNUNET_ATS_scanner_done (GST_is); |
770 | GST_is = NULL; | 2255 | GST_is = NULL; |
771 | GST_clients_stop (); | 2256 | while (NULL != (cur = a2s_head)) |
772 | GST_blacklist_stop (); | 2257 | { |
2258 | GNUNET_CONTAINER_DLL_remove (a2s_head, | ||
2259 | a2s_tail, | ||
2260 | cur); | ||
2261 | GNUNET_free (cur); | ||
2262 | } | ||
2263 | if (NULL != plugin_nc) | ||
2264 | { | ||
2265 | GNUNET_notification_context_destroy (plugin_nc); | ||
2266 | plugin_nc = NULL; | ||
2267 | } | ||
2268 | GNUNET_CONTAINER_multipeermap_destroy (active_stccs); | ||
2269 | active_stccs = NULL; | ||
2270 | if (NULL != blacklist) | ||
2271 | { | ||
2272 | GNUNET_CONTAINER_multipeermap_iterate (blacklist, | ||
2273 | &free_blacklist_entry, | ||
2274 | NULL); | ||
2275 | GNUNET_CONTAINER_multipeermap_destroy (blacklist); | ||
2276 | blacklist = NULL; | ||
2277 | } | ||
773 | GST_hello_stop (); | 2278 | GST_hello_stop (); |
774 | GST_manipulation_stop (); | 2279 | GST_manipulation_stop (); |
775 | 2280 | ||
@@ -785,10 +2290,452 @@ shutdown_task (void *cls) | |||
785 | } | 2290 | } |
786 | if (NULL != GST_my_private_key) | 2291 | if (NULL != GST_my_private_key) |
787 | { | 2292 | { |
788 | GNUNET_free(GST_my_private_key); | 2293 | GNUNET_free (GST_my_private_key); |
789 | GST_my_private_key = NULL; | 2294 | GST_my_private_key = NULL; |
790 | } | 2295 | } |
791 | GST_server = NULL; | 2296 | } |
2297 | |||
2298 | |||
2299 | /** | ||
2300 | * Perform next action in the blacklist check. | ||
2301 | * | ||
2302 | * @param cls the `struct GST_BlacklistCheck *` | ||
2303 | */ | ||
2304 | static void | ||
2305 | do_blacklist_check (void *cls) | ||
2306 | { | ||
2307 | struct GST_BlacklistCheck *bc = cls; | ||
2308 | struct TransportClient *tc; | ||
2309 | struct GNUNET_MQ_Envelope *env; | ||
2310 | struct BlacklistMessage *bm; | ||
2311 | |||
2312 | bc->task = NULL; | ||
2313 | while (NULL != (tc = bc->bl_pos)) | ||
2314 | { | ||
2315 | if (CT_BLACKLIST == tc->type) | ||
2316 | break; | ||
2317 | bc->bl_pos = tc->next; | ||
2318 | } | ||
2319 | if (NULL == tc) | ||
2320 | { | ||
2321 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2322 | "No other blacklist clients active, will allow neighbour `%s'\n", | ||
2323 | GNUNET_i2s (&bc->peer)); | ||
2324 | |||
2325 | bc->cont (bc->cont_cls, | ||
2326 | &bc->peer, | ||
2327 | bc->address, | ||
2328 | bc->session, | ||
2329 | GNUNET_OK); | ||
2330 | GST_blacklist_test_cancel (bc); | ||
2331 | return; | ||
2332 | } | ||
2333 | if ( (NULL != tc->details.blacklist.bc) || | ||
2334 | (GNUNET_NO != tc->details.blacklist.waiting_for_reply) ) | ||
2335 | return; /* someone else busy with this client */ | ||
2336 | tc->details.blacklist.bc = bc; | ||
2337 | env = GNUNET_MQ_msg (bm, | ||
2338 | GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY); | ||
2339 | bm->is_allowed = htonl (0); | ||
2340 | bm->peer = bc->peer; | ||
2341 | GNUNET_MQ_send (tc->mq, | ||
2342 | env); | ||
2343 | if (GNUNET_YES == tc->details.blacklist.call_receive_done) | ||
2344 | { | ||
2345 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2346 | GNUNET_SERVICE_client_continue (tc->client); | ||
2347 | } | ||
2348 | tc->details.blacklist.waiting_for_reply = GNUNET_YES; | ||
2349 | } | ||
2350 | |||
2351 | |||
2352 | /** | ||
2353 | * A blacklisting client has sent us reply. Process it. | ||
2354 | * | ||
2355 | * @param cls the client | ||
2356 | * @param msg the blacklist-reply message that was sent | ||
2357 | */ | ||
2358 | static void | ||
2359 | handle_client_blacklist_reply (void *cls, | ||
2360 | const struct BlacklistMessage *msg) | ||
2361 | { | ||
2362 | struct TransportClient *tc = cls; | ||
2363 | struct GST_BlacklistCheck *bc; | ||
2364 | |||
2365 | if (CT_BLACKLIST != tc->type) | ||
2366 | { | ||
2367 | GNUNET_break (0); | ||
2368 | GNUNET_SERVICE_client_drop (tc->client); | ||
2369 | return; | ||
2370 | } | ||
2371 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2372 | "Blacklist client %p sent reply for `%s'\n", | ||
2373 | tc, | ||
2374 | GNUNET_i2s (&msg->peer)); | ||
2375 | bc = tc->details.blacklist.bc; | ||
2376 | tc->details.blacklist.bc = NULL; | ||
2377 | tc->details.blacklist.waiting_for_reply = GNUNET_NO; | ||
2378 | tc->details.blacklist.call_receive_done = GNUNET_YES; | ||
2379 | if (NULL != bc) | ||
2380 | { | ||
2381 | /* only run this if the blacklist check has not been | ||
2382 | * cancelled in the meantime... */ | ||
2383 | GNUNET_assert (bc->bl_pos == tc); | ||
2384 | if (ntohl (msg->is_allowed) == GNUNET_SYSERR) | ||
2385 | { | ||
2386 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2387 | "Blacklist check failed, peer not allowed\n"); | ||
2388 | /* For the duration of the continuation, make the ongoing | ||
2389 | check invisible (to avoid double-cancellation); then | ||
2390 | add it back again so we can re-use GST_blacklist_test_cancel() */ | ||
2391 | GNUNET_CONTAINER_DLL_remove (bc_head, | ||
2392 | bc_tail, | ||
2393 | bc); | ||
2394 | bc->cont (bc->cont_cls, | ||
2395 | &bc->peer, | ||
2396 | bc->address, | ||
2397 | bc->session, | ||
2398 | GNUNET_NO); | ||
2399 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
2400 | bc_tail, | ||
2401 | bc); | ||
2402 | GST_blacklist_test_cancel (bc); | ||
2403 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2404 | GNUNET_SERVICE_client_continue (tc->client); | ||
2405 | return; | ||
2406 | } | ||
2407 | else | ||
2408 | { | ||
2409 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2410 | "Blacklist check succeeded, continuing with checks\n"); | ||
2411 | tc->details.blacklist.call_receive_done = GNUNET_NO; | ||
2412 | GNUNET_SERVICE_client_continue (tc->client); | ||
2413 | bc->bl_pos = tc->next; | ||
2414 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
2415 | bc); | ||
2416 | } | ||
2417 | } | ||
2418 | /* check if any other blacklist checks are waiting for this blacklister */ | ||
2419 | for (bc = bc_head; bc != NULL; bc = bc->next) | ||
2420 | if ( (bc->bl_pos == tc) && | ||
2421 | (NULL == bc->task) ) | ||
2422 | { | ||
2423 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
2424 | bc); | ||
2425 | break; | ||
2426 | } | ||
2427 | } | ||
2428 | |||
2429 | |||
2430 | /** | ||
2431 | * Add the given peer to the blacklist (for the given transport). | ||
2432 | * | ||
2433 | * @param peer peer to blacklist | ||
2434 | * @param transport_name transport to blacklist for this peer, NULL for all | ||
2435 | */ | ||
2436 | void | ||
2437 | GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer, | ||
2438 | const char *transport_name) | ||
2439 | { | ||
2440 | char *transport = NULL; | ||
2441 | |||
2442 | if (NULL != transport_name) | ||
2443 | { | ||
2444 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2445 | "Adding peer `%s' with plugin `%s' to blacklist\n", | ||
2446 | GNUNET_i2s (peer), | ||
2447 | transport_name); | ||
2448 | transport = GNUNET_strdup (transport_name); | ||
2449 | } | ||
2450 | else | ||
2451 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2452 | "Adding peer `%s' with all plugins to blacklist\n", | ||
2453 | GNUNET_i2s (peer)); | ||
2454 | if (NULL == blacklist) | ||
2455 | blacklist = | ||
2456 | GNUNET_CONTAINER_multipeermap_create (TRANSPORT_BLACKLIST_HT_SIZE, | ||
2457 | GNUNET_NO); | ||
2458 | |||
2459 | GNUNET_CONTAINER_multipeermap_put (blacklist, | ||
2460 | peer, | ||
2461 | transport, | ||
2462 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
2463 | } | ||
2464 | |||
2465 | |||
2466 | /** | ||
2467 | * Abort blacklist if @a address and @a session match. | ||
2468 | * | ||
2469 | * @param address address used to abort matching checks | ||
2470 | * @param session session used to abort matching checks | ||
2471 | */ | ||
2472 | void | ||
2473 | GST_blacklist_abort_matching (const struct GNUNET_HELLO_Address *address, | ||
2474 | struct GNUNET_ATS_Session *session) | ||
2475 | { | ||
2476 | struct GST_BlacklistCheck *bc; | ||
2477 | struct GST_BlacklistCheck *n; | ||
2478 | |||
2479 | n = bc_head; | ||
2480 | while (NULL != (bc = n)) | ||
2481 | { | ||
2482 | n = bc->next; | ||
2483 | if ( (bc->session == session) && | ||
2484 | (0 == GNUNET_HELLO_address_cmp (bc->address, | ||
2485 | address)) ) | ||
2486 | { | ||
2487 | bc->cont (bc->cont_cls, | ||
2488 | &bc->peer, | ||
2489 | bc->address, | ||
2490 | bc->session, | ||
2491 | GNUNET_SYSERR); | ||
2492 | GST_blacklist_test_cancel (bc); | ||
2493 | } | ||
2494 | } | ||
2495 | } | ||
2496 | |||
2497 | |||
2498 | /** | ||
2499 | * Test if the given blacklist entry matches. If so, | ||
2500 | * abort the iteration. | ||
2501 | * | ||
2502 | * @param cls the transport name to match (const char*) | ||
2503 | * @param key the key (unused) | ||
2504 | * @param value the 'char *' (name of a blacklisted transport) | ||
2505 | * @return #GNUNET_OK if the entry does not match, #GNUNET_NO if it matches | ||
2506 | */ | ||
2507 | static int | ||
2508 | test_blacklisted (void *cls, | ||
2509 | const struct GNUNET_PeerIdentity *key, | ||
2510 | void *value) | ||
2511 | { | ||
2512 | const char *transport_name = cls; | ||
2513 | char *be = value; | ||
2514 | |||
2515 | /* Blacklist entry be: | ||
2516 | * (NULL == be): peer is blacklisted with all plugins | ||
2517 | * (NULL != be): peer is blacklisted for a specific plugin | ||
2518 | * | ||
2519 | * If (NULL != transport_name) we look for a transport specific entry: | ||
2520 | * if (transport_name == be) forbidden | ||
2521 | * | ||
2522 | */ | ||
2523 | |||
2524 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2525 | "Comparing BL request for peer `%4s':`%s' with BL entry: `%s'\n", | ||
2526 | GNUNET_i2s (key), | ||
2527 | (NULL == transport_name) ? "unspecified" : transport_name, | ||
2528 | (NULL == be) ? "all plugins" : be); | ||
2529 | /* all plugins for this peer were blacklisted: disallow */ | ||
2530 | if (NULL == value) | ||
2531 | return GNUNET_NO; | ||
2532 | |||
2533 | /* blacklist check for specific transport */ | ||
2534 | if ( (NULL != transport_name) && | ||
2535 | (NULL != value) ) | ||
2536 | { | ||
2537 | if (0 == strcmp (transport_name, | ||
2538 | be)) | ||
2539 | return GNUNET_NO; /* plugin is blacklisted! */ | ||
2540 | } | ||
2541 | return GNUNET_OK; | ||
2542 | } | ||
2543 | |||
2544 | |||
2545 | /** | ||
2546 | * Test if a peer/transport combination is blacklisted. | ||
2547 | * | ||
2548 | * @param peer the identity of the peer to test | ||
2549 | * @param transport_name name of the transport to test, never NULL | ||
2550 | * @param cont function to call with result | ||
2551 | * @param cont_cls closure for @a cont | ||
2552 | * @param address address to pass back to @a cont, can be NULL | ||
2553 | * @param session session to pass back to @a cont, can be NULL | ||
2554 | * @return handle to the blacklist check, NULL if the decision | ||
2555 | * was made instantly and @a cont was already called | ||
2556 | */ | ||
2557 | struct GST_BlacklistCheck * | ||
2558 | GST_blacklist_test_allowed (const struct GNUNET_PeerIdentity *peer, | ||
2559 | const char *transport_name, | ||
2560 | GST_BlacklistTestContinuation cont, | ||
2561 | void *cont_cls, | ||
2562 | const struct GNUNET_HELLO_Address *address, | ||
2563 | struct GNUNET_ATS_Session *session) | ||
2564 | { | ||
2565 | struct GST_BlacklistCheck *bc; | ||
2566 | struct TransportClient *tc; | ||
2567 | |||
2568 | GNUNET_assert (NULL != peer); | ||
2569 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2570 | "Blacklist check for peer `%s':%s\n", | ||
2571 | GNUNET_i2s (peer), | ||
2572 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
2573 | |||
2574 | /* Check local blacklist by iterating over hashmap | ||
2575 | * If iteration is aborted, we found a matching blacklist entry */ | ||
2576 | if ((NULL != blacklist) && | ||
2577 | (GNUNET_SYSERR == | ||
2578 | GNUNET_CONTAINER_multipeermap_get_multiple (blacklist, peer, | ||
2579 | &test_blacklisted, | ||
2580 | (void *) transport_name))) | ||
2581 | { | ||
2582 | /* Disallowed by config, disapprove instantly */ | ||
2583 | GNUNET_STATISTICS_update (GST_stats, | ||
2584 | gettext_noop ("# disconnects due to blacklist"), | ||
2585 | 1, | ||
2586 | GNUNET_NO); | ||
2587 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2588 | _("Disallowing connection to peer `%s' on transport %s\n"), | ||
2589 | GNUNET_i2s (peer), | ||
2590 | (NULL != transport_name) ? transport_name : "unspecified"); | ||
2591 | if (NULL != cont) | ||
2592 | cont (cont_cls, | ||
2593 | peer, | ||
2594 | address, | ||
2595 | session, | ||
2596 | GNUNET_NO); | ||
2597 | return NULL; | ||
2598 | } | ||
2599 | |||
2600 | for (tc = clients_head; NULL != tc; tc = tc->next) | ||
2601 | if (CT_BLACKLIST == tc->type) | ||
2602 | break; | ||
2603 | if (NULL == tc) | ||
2604 | { | ||
2605 | /* no blacklist clients, approve instantly */ | ||
2606 | if (NULL != cont) | ||
2607 | cont (cont_cls, | ||
2608 | peer, | ||
2609 | address, | ||
2610 | session, | ||
2611 | GNUNET_OK); | ||
2612 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2613 | "Allowing connection to peer `%s' %s\n", | ||
2614 | GNUNET_i2s (peer), | ||
2615 | (NULL != transport_name) ? transport_name : ""); | ||
2616 | return NULL; | ||
2617 | } | ||
2618 | |||
2619 | /* need to query blacklist clients */ | ||
2620 | bc = GNUNET_new (struct GST_BlacklistCheck); | ||
2621 | GNUNET_CONTAINER_DLL_insert (bc_head, | ||
2622 | bc_tail, | ||
2623 | bc); | ||
2624 | bc->peer = *peer; | ||
2625 | bc->address = GNUNET_HELLO_address_copy (address); | ||
2626 | bc->session = session; | ||
2627 | bc->cont = cont; | ||
2628 | bc->cont_cls = cont_cls; | ||
2629 | bc->bl_pos = tc; | ||
2630 | bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, | ||
2631 | bc); | ||
2632 | return bc; | ||
2633 | } | ||
2634 | |||
2635 | |||
2636 | /** | ||
2637 | * Cancel a blacklist check. | ||
2638 | * | ||
2639 | * @param bc check to cancel | ||
2640 | */ | ||
2641 | void | ||
2642 | GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc) | ||
2643 | { | ||
2644 | GNUNET_CONTAINER_DLL_remove (bc_head, | ||
2645 | bc_tail, | ||
2646 | bc); | ||
2647 | if (NULL != bc->bl_pos) | ||
2648 | { | ||
2649 | if ( (CT_BLACKLIST == bc->bl_pos->type) && | ||
2650 | (bc->bl_pos->details.blacklist.bc == bc) ) | ||
2651 | { | ||
2652 | /* we're at the head of the queue, remove us! */ | ||
2653 | bc->bl_pos->details.blacklist.bc = NULL; | ||
2654 | } | ||
2655 | } | ||
2656 | if (NULL != bc->task) | ||
2657 | { | ||
2658 | GNUNET_SCHEDULER_cancel (bc->task); | ||
2659 | bc->task = NULL; | ||
2660 | } | ||
2661 | GNUNET_free_non_null (bc->address); | ||
2662 | GNUNET_free (bc); | ||
2663 | } | ||
2664 | |||
2665 | |||
2666 | /** | ||
2667 | * Function to iterate over options in the blacklisting section for a peer. | ||
2668 | * | ||
2669 | * @param cls closure | ||
2670 | * @param section name of the section | ||
2671 | * @param option name of the option | ||
2672 | * @param value value of the option | ||
2673 | */ | ||
2674 | static void | ||
2675 | blacklist_cfg_iter (void *cls, | ||
2676 | const char *section, | ||
2677 | const char *option, | ||
2678 | const char *value) | ||
2679 | { | ||
2680 | unsigned int *res = cls; | ||
2681 | struct GNUNET_PeerIdentity peer; | ||
2682 | char *plugs; | ||
2683 | char *pos; | ||
2684 | |||
2685 | if (GNUNET_OK != | ||
2686 | GNUNET_CRYPTO_eddsa_public_key_from_string (option, | ||
2687 | strlen (option), | ||
2688 | &peer.public_key)) | ||
2689 | return; | ||
2690 | |||
2691 | if ((NULL == value) || (0 == strcmp(value, ""))) | ||
2692 | { | ||
2693 | /* Blacklist whole peer */ | ||
2694 | GST_blacklist_add_peer (&peer, NULL); | ||
2695 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2696 | _("Adding blacklisting entry for peer `%s'\n"), | ||
2697 | GNUNET_i2s (&peer)); | ||
2698 | } | ||
2699 | else | ||
2700 | { | ||
2701 | plugs = GNUNET_strdup (value); | ||
2702 | for (pos = strtok (plugs, " "); pos != NULL; pos = strtok (NULL, " ")) | ||
2703 | { | ||
2704 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
2705 | _("Adding blacklisting entry for peer `%s':`%s'\n"), | ||
2706 | GNUNET_i2s (&peer), pos); | ||
2707 | GST_blacklist_add_peer (&peer, pos); | ||
2708 | } | ||
2709 | GNUNET_free (plugs); | ||
2710 | } | ||
2711 | (*res)++; | ||
2712 | } | ||
2713 | |||
2714 | |||
2715 | /** | ||
2716 | * Read blacklist configuration | ||
2717 | * | ||
2718 | * @param cfg the configuration handle | ||
2719 | * @param my_id my peer identity | ||
2720 | */ | ||
2721 | static void | ||
2722 | read_blacklist_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2723 | const struct GNUNET_PeerIdentity *my_id) | ||
2724 | { | ||
2725 | char cfg_sect[512]; | ||
2726 | unsigned int res = 0; | ||
2727 | |||
2728 | GNUNET_snprintf (cfg_sect, | ||
2729 | sizeof (cfg_sect), | ||
2730 | "transport-blacklist-%s", | ||
2731 | GNUNET_i2s_full (my_id)); | ||
2732 | GNUNET_CONFIGURATION_iterate_section_values (cfg, | ||
2733 | cfg_sect, | ||
2734 | &blacklist_cfg_iter, | ||
2735 | &res); | ||
2736 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2737 | "Loaded %u blacklisting entries from configuration\n", | ||
2738 | res); | ||
792 | } | 2739 | } |
793 | 2740 | ||
794 | 2741 | ||
@@ -796,13 +2743,13 @@ shutdown_task (void *cls) | |||
796 | * Initiate transport service. | 2743 | * Initiate transport service. |
797 | * | 2744 | * |
798 | * @param cls closure | 2745 | * @param cls closure |
799 | * @param server the initialized server | ||
800 | * @param c configuration to use | 2746 | * @param c configuration to use |
2747 | * @param service the initialized service | ||
801 | */ | 2748 | */ |
802 | static void | 2749 | static void |
803 | run (void *cls, | 2750 | run (void *cls, |
804 | struct GNUNET_SERVER_Handle *server, | 2751 | const struct GNUNET_CONFIGURATION_Handle *c, |
805 | const struct GNUNET_CONFIGURATION_Handle *c) | 2752 | struct GNUNET_SERVICE_Handle *service) |
806 | { | 2753 | { |
807 | char *keyfile; | 2754 | char *keyfile; |
808 | struct GNUNET_CRYPTO_EddsaPrivateKey *pk; | 2755 | struct GNUNET_CRYPTO_EddsaPrivateKey *pk; |
@@ -832,7 +2779,6 @@ run (void *cls, | |||
832 | { | 2779 | { |
833 | hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; | 2780 | hello_expiration = GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION; |
834 | } | 2781 | } |
835 | GST_server = server; | ||
836 | pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); | 2782 | pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); |
837 | GNUNET_free (keyfile); | 2783 | GNUNET_free (keyfile); |
838 | GNUNET_assert (NULL != pk); | 2784 | GNUNET_assert (NULL != pk); |
@@ -842,7 +2788,7 @@ run (void *cls, | |||
842 | GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg); | 2788 | GST_peerinfo = GNUNET_PEERINFO_connect (GST_cfg); |
843 | GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, | 2789 | GNUNET_CRYPTO_eddsa_key_get_public (GST_my_private_key, |
844 | &GST_my_identity.public_key); | 2790 | &GST_my_identity.public_key); |
845 | GNUNET_assert(NULL != GST_my_private_key); | 2791 | GNUNET_assert (NULL != GST_my_private_key); |
846 | 2792 | ||
847 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, | 2793 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, |
848 | "My identity is `%4s'\n", | 2794 | "My identity is `%4s'\n", |
@@ -852,24 +2798,28 @@ run (void *cls, | |||
852 | NULL); | 2798 | NULL); |
853 | if (NULL == GST_peerinfo) | 2799 | if (NULL == GST_peerinfo) |
854 | { | 2800 | { |
855 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 2801 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
856 | _("Could not access PEERINFO service. Exiting.\n")); | 2802 | _("Could not access PEERINFO service. Exiting.\n")); |
857 | GNUNET_SCHEDULER_shutdown (); | 2803 | GNUNET_SCHEDULER_shutdown (); |
858 | return; | 2804 | return; |
859 | } | 2805 | } |
860 | 2806 | ||
861 | max_fd_rlimit = 0; | 2807 | max_fd_rlimit = 0; |
862 | #if HAVE_GETRLIMIT | 2808 | #if HAVE_GETRLIMIT |
863 | struct rlimit r_file; | ||
864 | if (0 == getrlimit (RLIMIT_NOFILE, &r_file)) | ||
865 | { | 2809 | { |
866 | max_fd_rlimit = r_file.rlim_cur; | 2810 | struct rlimit r_file; |
867 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2811 | |
868 | "Maximum number of open files was: %u/%u\n", | 2812 | if (0 == getrlimit (RLIMIT_NOFILE, |
869 | (unsigned int) r_file.rlim_cur, | 2813 | &r_file)) |
870 | (unsigned int) r_file.rlim_max); | 2814 | { |
2815 | max_fd_rlimit = r_file.rlim_cur; | ||
2816 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2817 | "Maximum number of open files was: %u/%u\n", | ||
2818 | (unsigned int) r_file.rlim_cur, | ||
2819 | (unsigned int) r_file.rlim_max); | ||
2820 | } | ||
2821 | max_fd_rlimit = (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */ | ||
871 | } | 2822 | } |
872 | max_fd_rlimit = (9 * max_fd_rlimit) / 10; /* Keep 10% for rest of transport */ | ||
873 | #endif | 2823 | #endif |
874 | if (GNUNET_OK != | 2824 | if (GNUNET_OK != |
875 | GNUNET_CONFIGURATION_get_value_number (GST_cfg, | 2825 | GNUNET_CONFIGURATION_get_value_number (GST_cfg, |
@@ -897,9 +2847,8 @@ run (void *cls, | |||
897 | if (GNUNET_SYSERR == friend_only) | 2847 | if (GNUNET_SYSERR == friend_only) |
898 | friend_only = GNUNET_NO; /* According to topology defaults */ | 2848 | friend_only = GNUNET_NO; /* According to topology defaults */ |
899 | /* start subsystems */ | 2849 | /* start subsystems */ |
900 | GST_blacklist_start (GST_server, | 2850 | read_blacklist_configuration (GST_cfg, |
901 | GST_cfg, | 2851 | &GST_my_identity); |
902 | &GST_my_identity); | ||
903 | GST_is = GNUNET_ATS_scanner_init (); | 2852 | GST_is = GNUNET_ATS_scanner_init (); |
904 | GST_ats_connect = GNUNET_ATS_connectivity_init (GST_cfg); | 2853 | GST_ats_connect = GNUNET_ATS_connectivity_init (GST_cfg); |
905 | GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, | 2854 | GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, |
@@ -915,26 +2864,60 @@ run (void *cls, | |||
915 | &process_hello_update, | 2864 | &process_hello_update, |
916 | NULL); | 2865 | NULL); |
917 | GST_neighbours_start ((max_fd / 3) * 2); | 2866 | GST_neighbours_start ((max_fd / 3) * 2); |
918 | GST_clients_start (GST_server); | 2867 | active_stccs = GNUNET_CONTAINER_multipeermap_create (128, |
2868 | GNUNET_YES); | ||
2869 | plugin_nc = GNUNET_notification_context_create (0); | ||
919 | GST_validation_start ((max_fd / 3)); | 2870 | GST_validation_start ((max_fd / 3)); |
920 | } | 2871 | } |
921 | 2872 | ||
922 | 2873 | ||
923 | /** | 2874 | /** |
924 | * The main function for the transport service. | 2875 | * Define "main" method using service macro. |
925 | * | ||
926 | * @param argc number of arguments from the command line | ||
927 | * @param argv command line arguments | ||
928 | * @return 0 ok, 1 on error | ||
929 | */ | 2876 | */ |
930 | int | 2877 | GNUNET_SERVICE_MAIN |
931 | main (int argc, | 2878 | ("transport", |
932 | char * const *argv) | 2879 | GNUNET_SERVICE_OPTION_NONE, |
933 | { | 2880 | &run, |
934 | return | 2881 | &client_connect_cb, |
935 | (GNUNET_OK | 2882 | &client_disconnect_cb, |
936 | == GNUNET_SERVICE_run (argc, argv, "transport", | 2883 | NULL, |
937 | GNUNET_SERVICE_OPTION_NONE, &run, NULL )) ? 0 : 1; | 2884 | GNUNET_MQ_hd_fixed_size (client_start, |
938 | } | 2885 | GNUNET_MESSAGE_TYPE_TRANSPORT_START, |
2886 | struct StartMessage, | ||
2887 | NULL), | ||
2888 | GNUNET_MQ_hd_var_size (client_hello, | ||
2889 | GNUNET_MESSAGE_TYPE_HELLO, | ||
2890 | struct GNUNET_MessageHeader, | ||
2891 | NULL), | ||
2892 | GNUNET_MQ_hd_var_size (client_send, | ||
2893 | GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, | ||
2894 | struct OutboundMessage, | ||
2895 | NULL), | ||
2896 | GNUNET_MQ_hd_var_size (client_address_to_string, | ||
2897 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, | ||
2898 | struct AddressLookupMessage, | ||
2899 | NULL), | ||
2900 | GNUNET_MQ_hd_fixed_size (client_monitor_peers, | ||
2901 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST, | ||
2902 | struct PeerMonitorMessage, | ||
2903 | NULL), | ||
2904 | GNUNET_MQ_hd_fixed_size (client_blacklist_init, | ||
2905 | GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT, | ||
2906 | struct GNUNET_MessageHeader, | ||
2907 | NULL), | ||
2908 | GNUNET_MQ_hd_fixed_size (client_blacklist_reply, | ||
2909 | GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY, | ||
2910 | struct BlacklistMessage, | ||
2911 | NULL), | ||
2912 | GNUNET_MQ_hd_fixed_size (client_set_metric, | ||
2913 | GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, | ||
2914 | struct TrafficMetricMessage, | ||
2915 | NULL), | ||
2916 | GNUNET_MQ_hd_fixed_size (client_monitor_plugins, | ||
2917 | GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_START, | ||
2918 | struct GNUNET_MessageHeader, | ||
2919 | NULL), | ||
2920 | GNUNET_MQ_handler_end ()); | ||
2921 | |||
939 | 2922 | ||
940 | /* end of file gnunet-service-transport.c */ | 2923 | /* end of file gnunet-service-transport.c */ |