aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-20 19:53:24 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-20 19:53:24 +0000
commit03f0ae4bb10cf55bb9bab601d45fd96c2eb13603 (patch)
tree9089fc11319e7de97c43d2e0bf8e6d9b67836b92 /src/transport/gnunet-service-transport.c
parent450982bb56fde81bd512cb21360b809482caf19b (diff)
downloadgnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.tar.gz
gnunet-03f0ae4bb10cf55bb9bab601d45fd96c2eb13603.zip
migrating transport service to new MQ API
Diffstat (limited to 'src/transport/gnunet-service-transport.c')
-rw-r--r--src/transport/gnunet-service-transport.c2103
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 */
96enum 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 */
123struct GST_BlacklistCheck;
124
125/**
126 * Client connected to the transport service.
127 */
128struct 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 */
197struct 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 */
251struct 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 */
273struct 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 */
308static struct TransportClient *clients_head;
309
310/**
311 * Tail of linked list of all clients to this service.
312 */
313static 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 */
321static struct GNUNET_CONTAINER_MultiPeerMap *active_stccs;
322
323/**
324 * Head of linked list of all pending address iterations
325 */
326static struct AddressToStringContext *a2s_head;
327
328/**
329 * Tail of linked list of all pending address iterations
330 */
331static struct AddressToStringContext *a2s_tail;
332
333/**
334 * Head of DLL of active blacklisting queries.
335 */
336static struct GST_BlacklistCheck *bc_head;
337
338/**
339 * Tail of DLL of active blacklisting queries.
340 */
341static 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 */
347static struct GNUNET_CONTAINER_MultiPeerMap *blacklist;
348
349/**
350 * Notification context, to send updates on changes to active plugin
351 * connections.
352 */
353static 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 */
359static 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 */
365static 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;
96struct GNUNET_PEERINFO_Handle *GST_peerinfo; 385struct GNUNET_PEERINFO_Handle *GST_peerinfo;
97 386
98/** 387/**
99 * Handle to our service's server.
100 */
101static struct GNUNET_SERVER_Handle *GST_server;
102
103/**
104 * Our private key. 388 * Our private key.
105 */ 389 */
106struct GNUNET_CRYPTO_EddsaPrivateKey *GST_my_private_key; 390struct 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 */
430static void
431unicast (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 */
467static void *
468client_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 */
492static void
493do_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 */
505static int
506mark_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 */
530static void
531client_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 */
583static void
584notify_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 */
616static void
617handle_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 (&notify_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 */
664static int
665check_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 */
678static void
679handle_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 */
698static void
699handle_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 */
762static int
763check_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 */
791static void
792handle_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 */
855static void
856transmit_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 */
916static int
917check_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 */
949static void
950handle_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 */
1017static struct PeerIterateResponseMessage *
1018compose_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 */
1067struct 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 */
1097static void
1098send_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 */
1138static void
1139handle_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 */
1214static void
1215plugin_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 */
1306static void
1307handle_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 */
1329void
1330GST_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 */
1366void
1367GST_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 */
1409static int
1410mark_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 */
1427void
1428GST_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 */
2077struct 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 */
2102static void
2103confirm_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 */
2131static void
2132test_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 */
2171static void
2172handle_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 */
2206static int
2207free_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 */
2224static void
2225handle_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,
758static void 2241static void
759shutdown_task (void *cls) 2242shutdown_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 */
2304static void
2305do_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 */
2358static void
2359handle_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 */
2436void
2437GST_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 */
2472void
2473GST_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 */
2507static int
2508test_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 */
2557struct GST_BlacklistCheck *
2558GST_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 */
2641void
2642GST_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 */
2674static void
2675blacklist_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 */
2721static void
2722read_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 */
802static void 2749static void
803run (void *cls, 2750run (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 */
930int 2877GNUNET_SERVICE_MAIN
931main (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 */