2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/gnunet-service-transport_clients.c
23 * @brief plugin management API
24 * @author Christian Grothoff
27 #include "gnunet-service-transport_blacklist.h"
28 #include "gnunet-service-transport_clients.h"
29 #include "gnunet-service-transport_hello.h"
30 #include "gnunet-service-transport_neighbours.h"
31 #include "gnunet-service-transport_plugins.h"
32 #include "gnunet-service-transport_validation.h"
33 #include "gnunet-service-transport.h"
34 #include "transport.h"
38 * How many messages can we have pending for a given client process
39 * before we start to drop incoming messages? We typically should
40 * have only one client and so this would be the primary buffer for
41 * messages, so the number should be chosen rather generously.
43 * The expectation here is that most of the time the queue is large
44 * enough so that a drop is virtually never required. Note that
45 * this value must be about as large as 'TOTAL_MSGS' in the
46 * 'test_transport_api_reliability.c', otherwise that testcase may
49 #define MAX_PENDING (128 * 1024)
53 * Linked list of messages to be transmitted to the client. Each
54 * entry is followed by the actual message.
56 struct ClientMessageQueueEntry
59 * This is a doubly-linked list.
61 struct ClientMessageQueueEntry *next;
64 * This is a doubly-linked list.
66 struct ClientMessageQueueEntry *prev;
71 * Client connected to the transport service.
73 struct TransportClient
77 * This is a doubly-linked list.
79 struct TransportClient *next;
82 * This is a doubly-linked list.
84 struct TransportClient *prev;
87 * Handle to the client.
89 struct GNUNET_SERVER_Client *client;
92 * Linked list of messages yet to be transmitted to
95 struct ClientMessageQueueEntry *message_queue_head;
98 * Tail of linked list of messages yet to be transmitted to the
101 struct ClientMessageQueueEntry *message_queue_tail;
104 * Current transmit request handle.
106 struct GNUNET_SERVER_TransmitHandle *th;
109 * Length of the list of messages pending for this client.
111 unsigned int message_count;
114 * Is this client interested in payload messages?
120 * Context for address to string operations
122 struct AddressToStringContext
125 * This is a doubly-linked list.
127 struct AddressToStringContext *next;
130 * This is a doubly-linked list.
132 struct AddressToStringContext *prev;
135 * Transmission context
137 struct GNUNET_SERVER_TransmitContext* tc;
141 * Client monitoring changes of active addresses of our neighbours.
143 struct MonitoringClient
146 * This is a doubly-linked list.
148 struct MonitoringClient *next;
151 * This is a doubly-linked list.
153 struct MonitoringClient *prev;
156 * Handle to the client.
158 struct GNUNET_SERVER_Client *client;
161 * Peer identity to monitor the addresses of.
162 * Zero to monitor all neighrours.
164 struct GNUNET_PeerIdentity peer;
170 * Head of linked list of all clients to this service.
172 static struct TransportClient *clients_head;
175 * Tail of linked list of all clients to this service.
177 static struct TransportClient *clients_tail;
180 * Head of linked list of all pending address iterations
182 struct AddressToStringContext *a2s_head;
185 * Tail of linked list of all pending address iterations
187 struct AddressToStringContext *a2s_tail;
190 * Head of linked list of monitoring clients.
192 static struct MonitoringClient *monitoring_clients_head;
195 * Tail of linked list of monitoring clients.
197 static struct MonitoringClient *monitoring_clients_tail;
200 * Notification context, to send updates on changes to active addresses
203 struct GNUNET_SERVER_NotificationContext *nc = NULL;
207 * Find the internal handle associated with the given client handle
209 * @param client server's client handle to look up
210 * @return internal client handle
212 static struct TransportClient *
213 lookup_client (struct GNUNET_SERVER_Client *client)
215 struct TransportClient *tc;
220 if (tc->client == client)
229 * Create the internal handle for the given server client handle
231 * @param client server's client handle to create our internal handle for
232 * @return fresh internal client handle
234 static struct TransportClient *
235 setup_client (struct GNUNET_SERVER_Client *client)
237 struct TransportClient *tc;
239 GNUNET_assert (lookup_client (client) == NULL);
240 tc = GNUNET_malloc (sizeof (struct TransportClient));
242 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
248 * Find the handle to the monitoring client associated with the given
251 * @param client server's client handle to look up
252 * @return handle to the monitoring client
254 static struct MonitoringClient *
255 lookup_monitoring_client (struct GNUNET_SERVER_Client *client)
257 struct MonitoringClient *mc;
259 mc = monitoring_clients_head;
262 if (mc->client == client)
271 * Setup a new monitoring client using the given server client handle and
274 * @param client server's client handle to create our internal handle for
275 * @param peer identity of the peer to monitor the addresses of,
276 * zero to monitor all neighrours.
277 * @return handle to the new monitoring client
279 static struct MonitoringClient *
280 setup_monitoring_client (struct GNUNET_SERVER_Client *client,
281 struct GNUNET_PeerIdentity *peer)
283 struct MonitoringClient *mc;
285 GNUNET_assert (lookup_monitoring_client (client) == NULL);
286 mc = GNUNET_malloc (sizeof (struct MonitoringClient));
289 GNUNET_CONTAINER_DLL_insert (monitoring_clients_head,
290 monitoring_clients_tail,
292 GNUNET_SERVER_notification_context_add (nc, client);
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
295 "Client %p started monitoring of the peer `%s'\n",
296 mc, GNUNET_i2s (peer));
302 * Function called to notify a client about the socket being ready to
303 * queue more data. "buf" will be NULL and "size" zero if the socket
304 * was closed for writing in the meantime.
307 * @param size number of bytes available in buf
308 * @param buf where the callee should write the message
309 * @return number of bytes written to buf
312 transmit_to_client_callback (void *cls, size_t size, void *buf)
314 struct TransportClient *tc = cls;
315 struct ClientMessageQueueEntry *q;
316 const struct GNUNET_MessageHeader *msg;
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
325 "Transmission to client failed, closing connection.\n");
330 while (NULL != (q = tc->message_queue_head))
332 msg = (const struct GNUNET_MessageHeader *) &q[1];
333 msize = ntohs (msg->size);
334 if (msize + tsize > size)
336 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
337 "Transmitting message of type %u to client %p.\n",
338 ntohs (msg->type), tc);
339 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
342 memcpy (&cbuf[tsize], msg, msize);
348 GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
350 GNUNET_SERVER_notify_transmit_ready (tc->client, msize,
351 GNUNET_TIME_UNIT_FOREVER_REL,
352 &transmit_to_client_callback, tc);
353 GNUNET_assert (tc->th != NULL);
360 * Queue the given message for transmission to the given client
362 * @param tc target of the message
363 * @param msg message to transmit
364 * @param may_drop GNUNET_YES if the message can be dropped
367 unicast (struct TransportClient *tc, const struct GNUNET_MessageHeader *msg,
370 struct ClientMessageQueueEntry *q;
379 if ((tc->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
381 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
383 ("Dropping message of type %u and size %u, have %u/%u messages pending\n"),
384 ntohs (msg->type), ntohs (msg->size), tc->message_count,
386 GNUNET_STATISTICS_update (GST_stats,
388 ("# messages dropped due to slow client"), 1,
392 msize = ntohs (msg->size);
393 GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
394 q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
395 memcpy (&q[1], msg, msize);
396 GNUNET_CONTAINER_DLL_insert_tail (tc->message_queue_head,
397 tc->message_queue_tail, q);
402 GNUNET_SERVER_notify_transmit_ready (tc->client, msize,
403 GNUNET_TIME_UNIT_FOREVER_REL,
404 &transmit_to_client_callback, tc);
405 GNUNET_assert (tc->th != NULL);
410 * Called whenever a client is disconnected. Frees our
411 * resources associated with that client.
414 * @param client identification of the client
417 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
419 struct TransportClient *tc;
420 struct MonitoringClient *mc;
421 struct ClientMessageQueueEntry *mqe;
425 mc = lookup_monitoring_client (client);
428 GNUNET_CONTAINER_DLL_remove (monitoring_clients_head,
429 monitoring_clients_tail,
433 tc = lookup_client (client);
436 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
437 "Client %p disconnected, cleaning up.\n", tc);
438 while (NULL != (mqe = tc->message_queue_head))
440 GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
445 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
448 GNUNET_SERVER_notify_transmit_ready_cancel (tc->th);
451 GNUNET_break (0 == tc->message_count);
457 * Function called for each of our connected neighbours. Notify the
458 * client about the existing neighbour.
460 * @param cls the 'struct TransportClient' to notify
461 * @param peer identity of the neighbour
462 * @param ats performance data
463 * @param ats_count number of entries in ats (excluding 0-termination)
464 * @param address the address
465 * @param bandwidth_in inbound bandwidth in NBO
466 * @param bandwidth_out outbound bandwidth in NBO
469 notify_client_about_neighbour (void *cls,
470 const struct GNUNET_PeerIdentity *peer,
471 const struct GNUNET_ATS_Information *ats,
473 const struct GNUNET_HELLO_Address *address,
474 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
475 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
477 struct TransportClient *tc = cls;
478 struct ConnectInfoMessage *cim;
479 struct GNUNET_ATS_Information *ap;
481 sizeof (struct ConnectInfoMessage) +
482 ats_count * sizeof (struct GNUNET_ATS_Information);
483 char buf[size] GNUNET_ALIGN;
485 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
486 cim = (struct ConnectInfoMessage *) buf;
487 cim->header.size = htons (size);
488 cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
489 cim->ats_count = htonl (ats_count);
491 cim->quota_in = bandwidth_in;
492 cim->quota_out = bandwidth_out;
493 ap = (struct GNUNET_ATS_Information *) &cim[1];
494 memcpy (ap, ats, ats_count * sizeof (struct GNUNET_ATS_Information));
495 unicast (tc, &cim->header, GNUNET_NO);
500 * Initialize a normal client. We got a start message from this
501 * client, add him to the list of clients for broadcasting of inbound
505 * @param client the client
506 * @param message the start message that was sent
509 clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
510 const struct GNUNET_MessageHeader *message)
512 const struct StartMessage *start;
513 struct TransportClient *tc;
516 tc = lookup_client (client);
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
519 "Client %p sent START\n", tc);
522 /* got 'start' twice from the same client, not allowed */
523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
524 "TransportClient %p ServerClient %p sent multiple START messages\n",
527 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
530 start = (const struct StartMessage *) message;
531 options = ntohl (start->options);
532 if ((0 != (1 & options)) &&
534 memcmp (&start->self, &GST_my_identity,
535 sizeof (struct GNUNET_PeerIdentity))))
537 /* client thinks this is a different peer, reject */
538 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
540 ("Rejecting control connection from peer `%s', which is not me!\n"),
541 GNUNET_i2s (&start->self));
542 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
545 tc = setup_client (client);
546 tc->send_payload = (0 != (2 & options));
547 unicast (tc, GST_hello_get (), GNUNET_NO);
548 GST_neighbours_iterate (¬ify_client_about_neighbour, tc);
549 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
550 GNUNET_SERVER_receive_done (client, GNUNET_OK);
555 * Client sent us a HELLO. Process the request.
558 * @param client the client
559 * @param message the HELLO message
562 clients_handle_hello (void *cls, struct GNUNET_SERVER_Client *client,
563 const struct GNUNET_MessageHeader *message)
565 GST_validation_handle_hello (message);
566 GNUNET_SERVER_receive_done (client, GNUNET_OK);
571 * Closure for 'handle_send_transmit_continuation'
573 struct SendTransmitContinuationContext
576 * Client that made the request.
578 struct GNUNET_SERVER_Client *client;
581 * Peer that was the target.
583 struct GNUNET_PeerIdentity target;
588 * Function called after the transmission is done. Notify the client that it is
589 * OK to send the next message.
592 * @param success GNUNET_OK on success, GNUNET_NO on failure, GNUNET_SYSERR if we're not connected
593 * @param bytes_payload bytes payload sent
594 * @param bytes_on_wire bytes sent on wire
597 handle_send_transmit_continuation (void *cls, int success,
598 size_t bytes_payload, size_t bytes_on_wire)
600 struct SendTransmitContinuationContext *stcc = cls;
601 struct SendOkMessage send_ok_msg;
603 //GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Payload: %u, On wire %u result: %i\n", bytes_payload, bytes_on_wire, success);
605 if (GNUNET_OK == success)
606 GNUNET_assert (bytes_on_wire >= bytes_payload);
609 GNUNET_assert (bytes_on_wire <= bytes_payload);
611 send_ok_msg.header.size = htons (sizeof (send_ok_msg));
612 send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
613 send_ok_msg.bytes_msg = htonl (bytes_payload);
614 send_ok_msg.bytes_physical = htonl (bytes_on_wire);
615 send_ok_msg.success = htonl (success);
616 send_ok_msg.latency =
617 GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL);
618 send_ok_msg.peer = stcc->target;
619 GST_clients_unicast (stcc->client, &send_ok_msg.header, GNUNET_NO);
620 GNUNET_SERVER_client_drop (stcc->client);
626 * Client asked for transmission to a peer. Process the request.
629 * @param client the client
630 * @param message the send message that was sent
633 clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client,
634 const struct GNUNET_MessageHeader *message)
636 const struct OutboundMessage *obm;
637 const struct GNUNET_MessageHeader *obmm;
638 struct SendTransmitContinuationContext *stcc;
641 struct TransportClient *tc;
643 tc = lookup_client (client);
646 /* client asked for transmission before 'START' */
648 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
652 size = ntohs (message->size);
654 sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
657 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
660 obm = (const struct OutboundMessage *) message;
661 obmm = (const struct GNUNET_MessageHeader *) &obm[1];
662 msize = size - sizeof (struct OutboundMessage);
663 if (msize < sizeof (struct GNUNET_MessageHeader))
666 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
672 "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize);
673 if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer))
675 /* not connected, not allowed to send; can happen due to asynchronous operations */
676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
677 "Could not send message to peer `%s': not connected\n",
678 GNUNET_i2s (&obm->peer));
679 GNUNET_STATISTICS_update (GST_stats,
681 ("# bytes payload dropped (other peer was not connected)"),
683 GNUNET_SERVER_receive_done (client, GNUNET_OK);
686 GNUNET_SERVER_receive_done (client, GNUNET_OK);
687 stcc = GNUNET_malloc (sizeof (struct SendTransmitContinuationContext));
688 stcc->target = obm->peer;
689 stcc->client = client;
690 GNUNET_SERVER_client_keep (client);
691 GST_neighbours_send (&obm->peer, obmm, msize,
692 GNUNET_TIME_relative_ntoh (obm->timeout),
693 &handle_send_transmit_continuation, stcc);
698 * Try to initiate a connection to the given peer if the blacklist
701 * @param cls closure (unused, NULL)
702 * @param peer identity of peer that was tested
703 * @param result GNUNET_OK if the connection is allowed,
707 try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer,
710 if (GNUNET_OK != result)
711 return; /* not allowed */
712 GST_neighbours_try_connect (peer);
717 * Handle request connect message
719 * @param cls closure (always NULL)
720 * @param client identification of the client
721 * @param message the actual message
724 clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
725 const struct GNUNET_MessageHeader *message)
727 const struct TransportRequestConnectMessage *trcm =
728 (const struct TransportRequestConnectMessage *) message;
730 GNUNET_STATISTICS_update (GST_stats,
732 ("# REQUEST CONNECT messages received"), 1,
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 "Received a request connect message for peer `%s'\n",
736 GNUNET_i2s (&trcm->peer));
737 (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed,
739 GNUNET_SERVER_receive_done (client, GNUNET_OK);
744 * Take the given address and append it to the set of results sent back to
747 * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
748 * @param buf text to transmit
751 transmit_address_to_client (void *cls, const char *buf)
753 struct AddressToStringContext *actx = cls;
757 GNUNET_SERVER_transmit_context_append_data (actx->tc, NULL, 0,
758 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
759 GNUNET_SERVER_transmit_context_run (actx->tc, GNUNET_TIME_UNIT_FOREVER_REL);
760 GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx);
764 GNUNET_SERVER_transmit_context_append_data (actx->tc, buf, strlen (buf) + 1,
765 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
770 * Client asked to resolve an address. Process the request.
773 * @param client the client
774 * @param message the resolution request
777 clients_handle_address_to_string (void *cls,
778 struct GNUNET_SERVER_Client *client,
779 const struct GNUNET_MessageHeader *message)
781 const struct AddressLookupMessage *alum;
782 struct GNUNET_TRANSPORT_PluginFunctions *papi;
783 const char *plugin_name;
785 uint32_t address_len;
787 struct GNUNET_SERVER_TransmitContext *tc;
788 struct AddressToStringContext *actx;
789 struct GNUNET_TIME_Relative rtimeout;
792 size = ntohs (message->size);
793 if (size < sizeof (struct AddressLookupMessage))
796 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
799 alum = (const struct AddressLookupMessage *) message;
800 address_len = ntohs (alum->addrlen);
801 if (size <= sizeof (struct AddressLookupMessage) + address_len)
804 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
807 address = (const char *) &alum[1];
808 plugin_name = (const char *) &address[address_len];
809 if (plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1]
813 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
816 rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
817 numeric = ntohs (alum->numeric_only);
818 tc = GNUNET_SERVER_transmit_context_create (client);
819 papi = GST_plugins_printer_find (plugin_name);
822 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
823 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
824 GNUNET_SERVER_transmit_context_run (tc, rtimeout);
827 actx = GNUNET_malloc (sizeof (struct AddressToStringContext));
829 GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx);
830 GNUNET_SERVER_disable_receive_done_warning (client);
831 papi->address_pretty_printer (papi->cls, plugin_name, address, address_len,
832 numeric, rtimeout, &transmit_address_to_client,
838 * Compose AddressIterateResponseMessage using the given peer and address.
840 * @param peer identity of the peer
841 * @param address the address, NULL on disconnect
842 * @return composed message
844 static struct AddressIterateResponseMessage *
845 compose_address_iterate_response_message (const struct GNUNET_PeerIdentity
847 const struct GNUNET_HELLO_Address
850 struct AddressIterateResponseMessage *msg;
856 GNUNET_assert (NULL != peer);
859 tlen = strlen (address->transport_name) + 1;
860 alen = address->address_length;
864 size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen);
865 msg = GNUNET_malloc (size);
866 msg->header.size = htons (size);
868 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE);
869 msg->reserved = htonl (0);
871 msg->addrlen = htonl (alen);
872 msg->pluginlen = htonl (tlen);
875 addr = (char *) &msg[1];
876 memcpy (addr, address->address, alen);
877 memcpy (&addr[alen], address->transport_name, tlen);
884 * Output the active address of connected neighbours to the given client.
886 * @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission to the client
887 * @param peer identity of the neighbour
888 * @param ats performance data
889 * @param ats_count number of entries in ats (excluding 0-termination)
890 * @param address the address
891 * @param bandwidth_in inbound quota in NBO
892 * @param bandwidth_out outbound quota in NBO
895 output_address (void *cls, const struct GNUNET_PeerIdentity *peer,
896 const struct GNUNET_ATS_Information *ats, uint32_t ats_count,
897 const struct GNUNET_HELLO_Address *address,
898 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
899 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
901 struct GNUNET_SERVER_TransmitContext *tc = cls;
902 struct AddressIterateResponseMessage *msg;
904 msg = compose_address_iterate_response_message (peer, address);
905 GNUNET_SERVER_transmit_context_append_message (tc, &msg->header);
911 * Client asked to obtain information about all actively used addresses
913 * Process the request.
916 * @param client the client
917 * @param message the peer address information request
920 clients_handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client,
921 const struct GNUNET_MessageHeader *message)
923 static struct GNUNET_PeerIdentity all_zeros;
924 struct GNUNET_SERVER_TransmitContext *tc;
925 struct AddressIterateMessage *msg;
926 struct GNUNET_HELLO_Address *address;
928 if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE)
931 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
934 if (ntohs (message->size) != sizeof (struct AddressIterateMessage))
937 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
940 msg = (struct AddressIterateMessage *) message;
941 if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
942 (NULL != lookup_monitoring_client (client)) )
944 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
945 "ServerClient %p tried to start monitoring twice\n",
948 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
951 GNUNET_SERVER_disable_receive_done_warning (client);
952 tc = GNUNET_SERVER_transmit_context_create (client);
953 if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
955 /* iterate over all neighbours */
956 GST_neighbours_iterate (&output_address, tc);
960 /* just return one neighbour */
961 address = GST_neighbour_get_current_address (&msg->peer);
963 output_address (tc, &msg->peer, NULL, 0, address,
964 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
965 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT);
967 if (GNUNET_YES != ntohl (msg->one_shot))
968 setup_monitoring_client (client, &msg->peer);
970 GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
971 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE);
972 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
977 * Start handling requests from clients.
979 * @param server server used to accept clients from.
982 GST_clients_start (struct GNUNET_SERVER_Handle *server)
984 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
985 {&clients_handle_start, NULL,
986 GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)},
987 {&clients_handle_hello, NULL,
988 GNUNET_MESSAGE_TYPE_HELLO, 0},
989 {&clients_handle_send, NULL,
990 GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
991 {&clients_handle_request_connect, NULL,
992 GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT,
993 sizeof (struct TransportRequestConnectMessage)},
994 {&clients_handle_address_to_string, NULL,
995 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, 0},
996 {&clients_handle_address_iterate, NULL,
997 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE,
998 sizeof (struct AddressIterateMessage)},
999 {&GST_blacklist_handle_init, NULL,
1000 GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
1001 sizeof (struct GNUNET_MessageHeader)},
1002 {&GST_blacklist_handle_reply, NULL,
1003 GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY,
1004 sizeof (struct BlacklistMessage)},
1007 nc = GNUNET_SERVER_notification_context_create (server, 0);
1008 GNUNET_SERVER_add_handlers (server, handlers);
1009 GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
1015 * Stop processing clients.
1020 struct AddressToStringContext *cur;
1022 while (NULL != (cur = a2s_head))
1024 GNUNET_SERVER_transmit_context_destroy (cur->tc, GNUNET_NO);
1025 GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur);
1031 GNUNET_SERVER_notification_context_destroy (nc);
1037 * Broadcast the given message to all of our clients.
1039 * @param msg message to broadcast
1040 * @param may_drop GNUNET_YES if the message can be dropped / is payload
1043 GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop)
1045 struct TransportClient *tc;
1047 for (tc = clients_head; tc != NULL; tc = tc->next)
1049 if ((GNUNET_YES == may_drop) && (GNUNET_YES != tc->send_payload))
1050 continue; /* skip, this client does not care about payload */
1051 unicast (tc, msg, may_drop);
1057 * Send the given message to a particular client
1059 * @param client target of the message
1060 * @param msg message to transmit
1061 * @param may_drop GNUNET_YES if the message can be dropped
1064 GST_clients_unicast (struct GNUNET_SERVER_Client *client,
1065 const struct GNUNET_MessageHeader *msg, int may_drop)
1067 struct TransportClient *tc;
1069 tc = lookup_client (client);
1071 return; /* client got disconnected in the meantime, drop message */
1072 unicast (tc, msg, may_drop);
1077 * Broadcast the new active address to all clients monitoring the peer.
1079 * @param peer peer this update is about (never NULL)
1080 * @param address address, NULL on disconnect
1083 GST_clients_broadcast_address_notification (const struct GNUNET_PeerIdentity
1085 const struct GNUNET_HELLO_Address
1088 struct AddressIterateResponseMessage *msg;
1089 struct MonitoringClient *mc;
1090 static struct GNUNET_PeerIdentity all_zeros;
1092 msg = compose_address_iterate_response_message (peer, address);
1093 mc = monitoring_clients_head;
1096 if ((0 == memcmp (&mc->peer, &all_zeros,
1097 sizeof (struct GNUNET_PeerIdentity))) ||
1098 (0 == memcmp (&mc->peer, peer,
1099 sizeof (struct GNUNET_PeerIdentity))))
1101 GNUNET_SERVER_notification_context_unicast (nc, mc->client,
1102 &msg->header, GNUNET_NO);
1111 /* end of file gnunet-service-transport_clients.c */