fixes for reconnecting and message handling
[oweals/gnunet.git] / src / transport / gnunet-service-transport_clients.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010-2013 Christian Grothoff (and other contributing authors)
4
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.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
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.
19 */
20
21 /**
22  * @file transport/gnunet-service-transport_clients.c
23  * @brief plugin management API
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
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_manipulation.h"
34 #include "gnunet-service-transport.h"
35 #include "transport.h"
36
37
38 /**
39  * How many messages can we have pending for a given client process
40  * before we start to drop incoming messages?  We typically should
41  * have only one client and so this would be the primary buffer for
42   * messages, so the number should be chosen rather generously.
43  *
44  * The expectation here is that most of the time the queue is large
45  * enough so that a drop is virtually never required.  Note that
46  * this value must be about as large as 'TOTAL_MSGS' in the
47  * 'test_transport_api_reliability.c', otherwise that testcase may
48  * fail.
49  */
50 #define MAX_PENDING (128 * 1024)
51
52
53 /**
54  * Linked list of messages to be transmitted to the client.  Each
55  * entry is followed by the actual message.
56  */
57 struct ClientMessageQueueEntry
58 {
59   /**
60    * This is a doubly-linked list.
61    */
62   struct ClientMessageQueueEntry *next;
63
64   /**
65    * This is a doubly-linked list.
66    */
67   struct ClientMessageQueueEntry *prev;
68 };
69
70
71 /**
72  * Client connected to the transport service.
73  */
74 struct TransportClient
75 {
76
77   /**
78    * This is a doubly-linked list.
79    */
80   struct TransportClient *next;
81
82   /**
83    * This is a doubly-linked list.
84    */
85   struct TransportClient *prev;
86
87   /**
88    * Handle to the client.
89    */
90   struct GNUNET_SERVER_Client *client;
91
92   /**
93    * Linked list of messages yet to be transmitted to
94    * the client.
95    */
96   struct ClientMessageQueueEntry *message_queue_head;
97
98   /**
99    * Tail of linked list of messages yet to be transmitted to the
100    * client.
101    */
102   struct ClientMessageQueueEntry *message_queue_tail;
103
104   /**
105    * Current transmit request handle.
106    */
107   struct GNUNET_SERVER_TransmitHandle *th;
108
109   /**
110    * Length of the list of messages pending for this client.
111    */
112   unsigned int message_count;
113
114   /**
115    * Is this client interested in payload messages?
116    */
117   int send_payload;
118 };
119
120 /**
121  * Context for address to string operations
122  */
123 struct AddressToStringContext
124 {
125   /**
126    * This is a doubly-linked list.
127    */
128   struct AddressToStringContext *next;
129
130   /**
131    * This is a doubly-linked list.
132    */
133   struct AddressToStringContext *prev;
134
135   /**
136    * Transmission context
137    */
138   struct GNUNET_SERVER_TransmitContext* tc;
139 };
140
141 /**
142  * Client monitoring changes of active addresses of our neighbours.
143  */
144 struct MonitoringClient
145 {
146   /**
147    * This is a doubly-linked list.
148    */
149   struct MonitoringClient *next;
150
151   /**
152    * This is a doubly-linked list.
153    */
154   struct MonitoringClient *prev;
155
156   /**
157    * Handle to the client.
158    */
159   struct GNUNET_SERVER_Client *client;
160
161   /**
162    * Peer identity to monitor the addresses of.
163    * Zero to monitor all neighrours.
164    */
165   struct GNUNET_PeerIdentity peer;
166
167 };
168
169
170 /**
171  * Head of linked list of all clients to this service.
172  */
173 static struct TransportClient *clients_head;
174
175 /**
176  * Tail of linked list of all clients to this service.
177  */
178 static struct TransportClient *clients_tail;
179
180 /**
181  * Head of linked list of all pending address iterations
182  */
183 struct AddressToStringContext *a2s_head;
184
185 /**
186  * Tail of linked list of all pending address iterations
187  */
188 struct AddressToStringContext *a2s_tail;
189
190 /**
191  * Head of linked list of monitoring clients.
192  */
193 static struct MonitoringClient *peer_monitoring_clients_head;
194
195 /**
196  * Tail of linked list of monitoring clients.
197  */
198 static struct MonitoringClient *peer_monitoring_clients_tail;
199
200 /**
201  * Head of linked list of validation monitoring clients.
202  */
203 static struct MonitoringClient *val_monitoring_clients_head;
204
205 /**
206  * Tail of linked list of validation monitoring clients.
207  */
208 static struct MonitoringClient *val_monitoring_clients_tail;
209
210 /**
211  * Notification context, to send updates on changes to active addresses
212  * of our neighbours.
213  */
214 static struct GNUNET_SERVER_NotificationContext *peer_nc;
215
216 /**
217  * Notification context, to send updates on changes to active addresses
218  * of our neighbours.
219  */
220 static struct GNUNET_SERVER_NotificationContext *val_nc;
221
222 /**
223  * Find the internal handle associated with the given client handle
224  *
225  * @param client server's client handle to look up
226  * @return internal client handle
227  */
228 static struct TransportClient *
229 lookup_client (struct GNUNET_SERVER_Client *client)
230 {
231   struct TransportClient *tc;
232
233   for (tc = clients_head; NULL != tc; tc = tc->next)
234     if (tc->client == client)
235       return tc;
236   return NULL;
237 }
238
239
240 /**
241  * Create the internal handle for the given server client handle
242  *
243  * @param client server's client handle to create our internal handle for
244  * @return fresh internal client handle
245  */
246 static struct TransportClient *
247 setup_client (struct GNUNET_SERVER_Client *client)
248 {
249   struct TransportClient *tc;
250
251   GNUNET_assert (NULL == lookup_client (client));
252   tc = GNUNET_new (struct TransportClient);
253   tc->client = client;
254   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255               "Client %p connected\n",
256               tc);
257   return tc;
258 }
259
260
261 /**
262  * Find the handle to the monitoring client associated with the given
263  * client handle
264  *
265  * @param client server's client handle to look up
266  * @return handle to the monitoring client
267  */
268 static struct MonitoringClient *
269 lookup_monitoring_client (struct MonitoringClient *head,
270     struct GNUNET_SERVER_Client *client)
271 {
272   struct MonitoringClient *mc;
273
274   for (mc = head; NULL != mc; mc = mc->next)
275     if (mc->client == client)
276       return mc;
277   return NULL;
278 }
279
280
281 /**
282  * Setup a new monitoring client using the given server client handle and
283  * the peer identity.
284  *
285  * @param client server's client handle to create our internal handle for
286  * @param peer identity of the peer to monitor the addresses of,
287  *             zero to monitor all neighrours.
288  * @return handle to the new monitoring client
289  */
290 static struct MonitoringClient *
291 setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
292                          struct GNUNET_PeerIdentity *peer)
293 {
294   struct MonitoringClient *mc;
295   static struct GNUNET_PeerIdentity all_zeros;
296
297   GNUNET_assert (lookup_monitoring_client (peer_monitoring_clients_head, client) == NULL);
298   mc = GNUNET_new (struct MonitoringClient);
299   mc->client = client;
300   mc->peer = *peer;
301   GNUNET_CONTAINER_DLL_insert (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc);
302   GNUNET_SERVER_notification_context_add (peer_nc, client);
303
304   if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
305     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
306                 "Client %p started monitoring of the peer `%s'\n",
307                 mc, GNUNET_i2s (peer));
308   else
309     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
310               "Client %p started monitoring all peers\n", mc);
311   return mc;
312 }
313
314 /**
315  * Setup a new monitoring client using the given server client handle and
316  * the peer identity.
317  *
318  * @param client server's client handle to create our internal handle for
319  * @param peer identity of the peer to monitor the addresses of,
320  *             zero to monitor all neighrours.
321  * @return handle to the new monitoring client
322  */
323 static struct MonitoringClient *
324 setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
325                          struct GNUNET_PeerIdentity *peer)
326 {
327   struct MonitoringClient *mc;
328   static struct GNUNET_PeerIdentity all_zeros;
329
330   GNUNET_assert (lookup_monitoring_client (val_monitoring_clients_head, client) == NULL);
331   mc = GNUNET_new (struct MonitoringClient);
332   mc->client = client;
333   mc->peer = *peer;
334   GNUNET_CONTAINER_DLL_insert (val_monitoring_clients_head, val_monitoring_clients_tail, mc);
335   GNUNET_SERVER_notification_context_add (val_nc, client);
336
337   if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
338     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
339                 "Client %p started monitoring of the peer `%s'\n",
340                 mc, GNUNET_i2s (peer));
341   else
342     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
343               "Client %p started monitoring all peers\n", mc);
344   return mc;
345 }
346
347
348 /**
349  * Function called to notify a client about the socket being ready to
350  * queue more data.  "buf" will be NULL and "size" zero if the socket
351  * was closed for writing in the meantime.
352  *
353  * @param cls closure
354  * @param size number of bytes available in @a buf
355  * @param buf where the callee should write the message
356  * @return number of bytes written to @a buf
357  */
358 static size_t
359 transmit_to_client_callback (void *cls, size_t size, void *buf)
360 {
361   struct TransportClient *tc = cls;
362   struct ClientMessageQueueEntry *q;
363   const struct GNUNET_MessageHeader *msg;
364   char *cbuf;
365   uint16_t msize;
366   size_t tsize;
367
368   tc->th = NULL;
369   if (NULL == buf)
370   {
371     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
372                 "Transmission to client failed, closing connection.\n");
373     return 0;
374   }
375   cbuf = buf;
376   tsize = 0;
377   while (NULL != (q = tc->message_queue_head))
378   {
379     msg = (const struct GNUNET_MessageHeader *) &q[1];
380     msize = ntohs (msg->size);
381     if (msize + tsize > size)
382       break;
383     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
384                 "Transmitting message of type %u to client %p.\n",
385                 ntohs (msg->type), tc);
386     GNUNET_CONTAINER_DLL_remove (tc->message_queue_head,
387                                  tc->message_queue_tail,
388                                  q);
389     tc->message_count--;
390     memcpy (&cbuf[tsize], msg, msize);
391     GNUNET_free (q);
392     tsize += msize;
393   }
394   if (NULL != q)
395   {
396     GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
397     tc->th =
398         GNUNET_SERVER_notify_transmit_ready (tc->client, msize,
399                                              GNUNET_TIME_UNIT_FOREVER_REL,
400                                              &transmit_to_client_callback, tc);
401     GNUNET_assert (NULL != tc->th);
402   }
403   return tsize;
404 }
405
406
407 /**
408  * Queue the given message for transmission to the given client
409  *
410  * @param tc target of the message
411  * @param msg message to transmit
412  * @param may_drop #GNUNET_YES if the message can be dropped
413  */
414 static void
415 unicast (struct TransportClient *tc,
416          const struct GNUNET_MessageHeader *msg,
417          int may_drop)
418 {
419   struct ClientMessageQueueEntry *q;
420   uint16_t msize;
421
422   if (NULL == msg)
423   {
424     GNUNET_break (0);
425     return;
426   }
427
428   if ((tc->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
429   {
430     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
431                 _("Dropping message of type %u and size %u, have %u/%u messages pending\n"),
432                 ntohs (msg->type),
433                 ntohs (msg->size),
434                 tc->message_count,
435                 MAX_PENDING);
436     GNUNET_STATISTICS_update (GST_stats,
437                               gettext_noop
438                               ("# messages dropped due to slow client"), 1,
439                               GNUNET_NO);
440     return;
441   }
442   msize = ntohs (msg->size);
443   GNUNET_assert (msize >= sizeof (struct GNUNET_MessageHeader));
444   q = GNUNET_malloc (sizeof (struct ClientMessageQueueEntry) + msize);
445   memcpy (&q[1], msg, msize);
446   GNUNET_CONTAINER_DLL_insert_tail (tc->message_queue_head,
447                                     tc->message_queue_tail, q);
448   tc->message_count++;
449   if (NULL != tc->th)
450     return;
451   tc->th =
452       GNUNET_SERVER_notify_transmit_ready (tc->client, msize,
453                                            GNUNET_TIME_UNIT_FOREVER_REL,
454                                            &transmit_to_client_callback, tc);
455   GNUNET_assert (NULL != tc->th);
456 }
457
458
459 /**
460  * Called whenever a client is disconnected.  Frees our
461  * resources associated with that client.
462  *
463  * @param cls closure
464  * @param client identification of the client
465  */
466 static void
467 client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
468 {
469   struct TransportClient *tc;
470   struct MonitoringClient *mc;
471   struct ClientMessageQueueEntry *mqe;
472
473   if (client == NULL)
474     return;
475   mc = lookup_monitoring_client (peer_monitoring_clients_head, client);
476   if (mc != NULL)
477   {
478     GNUNET_CONTAINER_DLL_remove (peer_monitoring_clients_head,
479                                  peer_monitoring_clients_tail,
480                                  mc);
481     GNUNET_free (mc);
482   }
483   mc = lookup_monitoring_client (val_monitoring_clients_head, client);
484   if (mc != NULL)
485   {
486     GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head,
487                                  val_monitoring_clients_tail,
488                                  mc);
489     GNUNET_free (mc);
490   }
491   tc = lookup_client (client);
492   if (tc == NULL)
493     return;
494   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
495               "Client %p disconnected, cleaning up.\n", tc);
496   while (NULL != (mqe = tc->message_queue_head))
497   {
498     GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
499                                  mqe);
500     tc->message_count--;
501     GNUNET_free (mqe);
502   }
503   GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
504   if (tc->th != NULL)
505   {
506     GNUNET_SERVER_notify_transmit_ready_cancel (tc->th);
507     tc->th = NULL;
508   }
509   GNUNET_break (0 == tc->message_count);
510   GNUNET_free (tc);
511 }
512
513
514 /**
515  * Function called for each of our connected neighbours.  Notify the
516  * client about the existing neighbour.
517  *
518  * @param cls the `struct TransportClient *` to notify
519  * @param peer identity of the neighbour
520  * @param address the address
521  * @param state the current state of the peer
522  * @param state_timeout the time out for the state
523  * @param bandwidth_in inbound bandwidth in NBO
524  * @param bandwidth_out outbound bandwidth in NBO
525  */
526 static void
527 notify_client_about_neighbour (void *cls,
528     const struct GNUNET_PeerIdentity *peer,
529     const struct GNUNET_HELLO_Address *address,
530     enum GNUNET_TRANSPORT_PeerState state,
531     struct GNUNET_TIME_Absolute state_timeout,
532     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
533     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
534 {
535   struct TransportClient *tc = cls;
536   struct ConnectInfoMessage *cim;
537   size_t size = sizeof (struct ConnectInfoMessage);
538   char buf[size] GNUNET_ALIGN;
539
540   if (GNUNET_NO == GST_neighbours_test_connected (peer))
541     return;
542
543   GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
544   cim = (struct ConnectInfoMessage *) buf;
545   cim->header.size = htons (size);
546   cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
547   cim->id = *peer;
548   cim->quota_in = bandwidth_in;
549   cim->quota_out = bandwidth_out;
550   unicast (tc, &cim->header, GNUNET_NO);
551 }
552
553
554 /**
555  * Initialize a normal client.  We got a start message from this
556  * client, add him to the list of clients for broadcasting of inbound
557  * messages.
558  *
559  * @param cls unused
560  * @param client the client
561  * @param message the start message that was sent
562  */
563 static void
564 clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
565                       const struct GNUNET_MessageHeader *message)
566 {
567   const struct StartMessage *start;
568   struct TransportClient *tc;
569   uint32_t options;
570
571   tc = lookup_client (client);
572
573   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
574               "Client %p sent START\n", tc);
575   if (tc != NULL)
576   {
577     /* got 'start' twice from the same client, not allowed */
578     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
579                 "TransportClient %p ServerClient %p sent multiple START messages\n",
580                 tc, tc->client);
581     GNUNET_break (0);
582     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
583     return;
584   }
585   start = (const struct StartMessage *) message;
586   options = ntohl (start->options);
587   if ((0 != (1 & options)) &&
588       (0 !=
589        memcmp (&start->self, &GST_my_identity,
590                sizeof (struct GNUNET_PeerIdentity))))
591   {
592     /* client thinks this is a different peer, reject */
593     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
594                 _
595                 ("Rejecting control connection from peer `%s', which is not me!\n"),
596                 GNUNET_i2s (&start->self));
597     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
598     return;
599   }
600   tc = setup_client (client);
601   tc->send_payload = (0 != (2 & options));
602   unicast (tc, GST_hello_get (), GNUNET_NO);
603   GST_neighbours_iterate (&notify_client_about_neighbour, tc);
604   GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc);
605   GNUNET_SERVER_receive_done (client, GNUNET_OK);
606 }
607
608
609 /**
610  * Client sent us a HELLO.  Process the request.
611  *
612  * @param cls unused
613  * @param client the client
614  * @param message the HELLO message
615  */
616 static void
617 clients_handle_hello (void *cls, struct GNUNET_SERVER_Client *client,
618                       const struct GNUNET_MessageHeader *message)
619 {
620   GST_validation_handle_hello (message);
621   GNUNET_SERVER_receive_done (client, GNUNET_OK);
622 }
623
624
625 /**
626  * Closure for 'handle_send_transmit_continuation'
627  */
628 struct SendTransmitContinuationContext
629 {
630   /**
631    * Client that made the request.
632    */
633   struct GNUNET_SERVER_Client *client;
634
635   /**
636    * Peer that was the target.
637    */
638   struct GNUNET_PeerIdentity target;
639 };
640
641
642 /**
643  * Function called after the transmission is done.  Notify the client that it is
644  * OK to send the next message.
645  *
646  * @param cls closure
647  * @param success #GNUNET_OK on success, #GNUNET_NO on failure, #GNUNET_SYSERR if we're not connected
648  * @param bytes_payload bytes payload sent
649  * @param bytes_on_wire bytes sent on wire
650  */
651 static void
652 handle_send_transmit_continuation (void *cls, int success,
653                                    size_t bytes_payload,
654                                    size_t bytes_on_wire)
655 {
656   struct SendTransmitContinuationContext *stcc = cls;
657   struct SendOkMessage send_ok_msg;
658
659   if (GNUNET_OK == success)
660     GST_neighbours_notify_payload_sent (&stcc->target, bytes_payload);
661
662   send_ok_msg.header.size = htons (sizeof (send_ok_msg));
663   send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
664   send_ok_msg.bytes_msg = htonl (bytes_payload);
665   send_ok_msg.bytes_physical = htonl (bytes_on_wire);
666   send_ok_msg.success = htonl (success);
667   send_ok_msg.latency =
668       GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL);
669   send_ok_msg.peer = stcc->target;
670   GST_clients_unicast (stcc->client, &send_ok_msg.header, GNUNET_NO);
671   GNUNET_SERVER_client_drop (stcc->client);
672   GNUNET_free (stcc);
673 }
674
675
676 /**
677  * Client asked for transmission to a peer.  Process the request.
678  *
679  * @param cls unused
680  * @param client the client
681  * @param message the send message that was sent
682  */
683 static void
684 clients_handle_send (void *cls,
685                      struct GNUNET_SERVER_Client *client,
686                      const struct GNUNET_MessageHeader *message)
687 {
688   const struct OutboundMessage *obm;
689   const struct GNUNET_MessageHeader *obmm;
690   struct SendTransmitContinuationContext *stcc;
691   uint16_t size;
692   uint16_t msize;
693   struct TransportClient *tc;
694
695   tc = lookup_client (client);
696   if (NULL == tc)
697   {
698     /* client asked for transmission before 'START' */
699     GNUNET_break (0);
700     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
701     return;
702   }
703
704   size = ntohs (message->size);
705   if (size <
706       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
707   {
708     GNUNET_break (0);
709     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
710     return;
711   }
712   obm = (const struct OutboundMessage *) message;
713   obmm = (const struct GNUNET_MessageHeader *) &obm[1];
714   msize = size - sizeof (struct OutboundMessage);
715   if (msize < sizeof (struct GNUNET_MessageHeader))
716   {
717     GNUNET_break (0);
718     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
719     return;
720   }
721
722   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723               "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
724               "SEND",
725               GNUNET_i2s (&obm->peer),
726               ntohs (obmm->type),
727               msize);
728   if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer))
729   {
730     /* not connected, not allowed to send; can happen due to asynchronous operations */
731     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
732                 "Could not send message to peer `%s': not connected\n",
733                 GNUNET_i2s (&obm->peer));
734     GNUNET_STATISTICS_update (GST_stats,
735                               gettext_noop
736                               ("# bytes payload dropped (other peer was not connected)"),
737                               msize, GNUNET_NO);
738     GNUNET_SERVER_receive_done (client, GNUNET_OK);
739     return;
740   }
741   GNUNET_SERVER_receive_done (client, GNUNET_OK);
742   stcc = GNUNET_new (struct SendTransmitContinuationContext);
743   stcc->target = obm->peer;
744   stcc->client = client;
745   GNUNET_SERVER_client_keep (client);
746   GST_manipulation_send (&obm->peer, obmm, msize,
747                        GNUNET_TIME_relative_ntoh (obm->timeout),
748                        &handle_send_transmit_continuation, stcc);
749 }
750
751
752 /**
753  * Try to initiate a connection to the given peer if the blacklist
754  * allowed it.
755  *
756  * @param cls closure (unused, NULL)
757  * @param peer identity of peer that was tested
758  * @param result #GNUNET_OK if the connection is allowed,
759  *               #GNUNET_NO if not
760  */
761 static void
762 try_connect_if_allowed (void *cls,
763                         const struct GNUNET_PeerIdentity *peer,
764                         int result)
765 {
766   if (GNUNET_OK != result)
767   {
768     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
769                 "Blacklist refuses connection attempt to peer `%s'\n",
770                 GNUNET_i2s (peer));
771     return;                     /* not allowed */
772   }
773   GST_neighbours_try_connect (peer);
774 }
775
776
777 /**
778  * Handle request connect message
779  *
780  * @param cls closure (always NULL)
781  * @param client identification of the client
782  * @param message the actual message
783  */
784 static void
785 clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
786                                 const struct GNUNET_MessageHeader *message)
787 {
788   const struct TransportRequestConnectMessage *trcm =
789       (const struct TransportRequestConnectMessage *) message;
790
791   GNUNET_STATISTICS_update (GST_stats,
792                             gettext_noop
793                             ("# REQUEST CONNECT messages received"), 1,
794                             GNUNET_NO);
795
796   if (0 == memcmp (&trcm->peer, &GST_my_identity,
797                 sizeof (struct GNUNET_PeerIdentity)))
798   {
799     GNUNET_break_op (0);
800     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
801                 "Received a request connect message myself `%s'\n",
802                 GNUNET_i2s (&trcm->peer));
803   }
804   else
805   {
806     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
807                 "Received a request connect message for peer `%s'\n",
808                 GNUNET_i2s (&trcm->peer));
809
810     (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed,
811                                      NULL);
812   }
813   GNUNET_SERVER_receive_done (client, GNUNET_OK);
814 }
815
816
817 /**
818  * Take the given address and append it to the set of results sent back to
819  * the client.
820  *
821  * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
822  * @param buf text to transmit
823  */
824 static void
825 transmit_address_to_client (void *cls, const char *buf)
826 {
827   struct AddressToStringContext *actx = cls;
828   if (NULL == buf)
829   {
830     GNUNET_SERVER_transmit_context_append_data (actx->tc, NULL, 0,
831                                                 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
832     GNUNET_SERVER_transmit_context_run (actx->tc, GNUNET_TIME_UNIT_FOREVER_REL);
833     GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx);
834     GNUNET_free (actx);
835     return;
836   }
837   GNUNET_SERVER_transmit_context_append_data (actx->tc, buf, strlen (buf) + 1,
838                                               GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
839 }
840
841
842 /**
843  * Client asked to resolve an address.  Process the request.
844  *
845  * @param cls unused
846  * @param client the client
847  * @param message the resolution request
848  */
849 static void
850 clients_handle_address_to_string (void *cls,
851                                   struct GNUNET_SERVER_Client *client,
852                                   const struct GNUNET_MessageHeader *message)
853 {
854   const struct AddressLookupMessage *alum;
855   struct GNUNET_TRANSPORT_PluginFunctions *papi;
856   const char *plugin_name;
857   const char *address;
858   uint32_t address_len;
859   uint16_t size;
860   struct GNUNET_SERVER_TransmitContext *tc;
861   struct AddressToStringContext *actx;
862   struct GNUNET_TIME_Relative rtimeout;
863   int32_t numeric;
864
865   size = ntohs (message->size);
866   if (size < sizeof (struct AddressLookupMessage))
867   {
868     GNUNET_break (0);
869     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
870     return;
871   }
872   alum = (const struct AddressLookupMessage *) message;
873   address_len = ntohs (alum->addrlen);
874   if (size <= sizeof (struct AddressLookupMessage) + address_len)
875   {
876     GNUNET_break (0);
877     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
878     return;
879   }
880   address = (const char *) &alum[1];
881   plugin_name = (const char *) &address[address_len];
882   if ('\0' != plugin_name[size - sizeof (struct AddressLookupMessage) - address_len - 1])
883   {
884     GNUNET_break (0);
885     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
886     return;
887   }
888   rtimeout = GNUNET_TIME_relative_ntoh (alum->timeout);
889   numeric = ntohs (alum->numeric_only);
890   tc = GNUNET_SERVER_transmit_context_create (client);
891   papi = GST_plugins_printer_find (plugin_name);
892   if (NULL == papi)
893   {
894     GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
895                                                 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
896     GNUNET_SERVER_transmit_context_run (tc, rtimeout);
897     return;
898   }
899   actx = GNUNET_new (struct AddressToStringContext);
900   actx->tc = tc;
901   GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx);
902   GNUNET_SERVER_disable_receive_done_warning (client);
903   papi->address_pretty_printer (papi->cls, plugin_name, address, address_len,
904                                 numeric, rtimeout, &transmit_address_to_client,
905                                 actx);
906 }
907
908
909 /**
910  * Compose #PeerIterateResponseMessage using the given peer and address.
911  *
912  * @param peer identity of the peer
913  * @param address the address, NULL on disconnect
914  * @return composed message
915  */
916 static struct PeerIterateResponseMessage *
917 compose_address_iterate_response_message (const struct GNUNET_PeerIdentity *peer,
918                                           const struct GNUNET_HELLO_Address *address)
919 {
920   struct PeerIterateResponseMessage *msg;
921   size_t size;
922   size_t tlen;
923   size_t alen;
924   char *addr;
925
926   GNUNET_assert (NULL != peer);
927   if (NULL != address)
928   {
929     tlen = strlen (address->transport_name) + 1;
930     alen = address->address_length;
931   }
932   else
933     tlen = alen = 0;
934   size = (sizeof (struct PeerIterateResponseMessage) + alen + tlen);
935   msg = GNUNET_malloc (size);
936   msg->header.size = htons (size);
937   msg->header.type =
938       htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
939   msg->reserved = htonl (0);
940   msg->peer = *peer;
941   msg->addrlen = htonl (alen);
942   msg->pluginlen = htonl (tlen);
943
944   if (NULL != address)
945   {
946     msg->local_address_info = htonl((uint32_t) address->local_info);
947     addr = (char *) &msg[1];
948     memcpy (addr, address->address, alen);
949     memcpy (&addr[alen], address->transport_name, tlen);
950   }
951   return msg;
952 }
953
954 /**
955  * Compose #PeerIterateResponseMessage using the given peer and address.
956  *
957  * @param peer identity of the peer
958  * @param address the address, NULL on disconnect
959  * @return composed message
960  */
961 static struct ValidationIterateResponseMessage *
962 compose_validation_iterate_response_message (const struct GNUNET_PeerIdentity *peer,
963                                           const struct GNUNET_HELLO_Address *address)
964 {
965   struct ValidationIterateResponseMessage *msg;
966   size_t size;
967   size_t tlen;
968   size_t alen;
969   char *addr;
970
971   GNUNET_assert (NULL != peer);
972   if (NULL != address)
973   {
974     tlen = strlen (address->transport_name) + 1;
975     alen = address->address_length;
976   }
977   else
978     tlen = alen = 0;
979   size = (sizeof (struct ValidationIterateResponseMessage) + alen + tlen);
980   msg = GNUNET_malloc (size);
981   msg->header.size = htons (size);
982   msg->header.type =
983       htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
984   msg->reserved = htonl (0);
985   msg->peer = *peer;
986   msg->addrlen = htonl (alen);
987   msg->pluginlen = htonl (tlen);
988
989   if (NULL != address)
990   {
991     msg->local_address_info = htonl((uint32_t) address->local_info);
992     addr = (char *) &msg[1];
993     memcpy (addr, address->address, alen);
994     memcpy (&addr[alen], address->transport_name, tlen);
995   }
996   return msg;
997 }
998
999 struct IterationContext
1000 {
1001   struct GNUNET_SERVER_TransmitContext *tc;
1002
1003   struct GNUNET_PeerIdentity id;
1004
1005   int all;
1006 };
1007
1008 /**
1009  * Output information of neighbours to the given client.
1010  *
1011  * @param cls the 'struct PeerIterationContext'
1012  * @param peer identity of the neighbour
1013  * @param address the address
1014  * @param state current state this peer is in
1015  * @param state_timeout timeout for the current state of the peer
1016  * @param bandwidth_in inbound quota in NBO
1017  * @param bandwidth_out outbound quota in NBO
1018  */
1019 static void
1020 send_validation_information (void *cls,
1021     const struct GNUNET_PeerIdentity *peer,
1022     const struct GNUNET_HELLO_Address *address,
1023     struct GNUNET_TIME_Absolute last_validation,
1024     struct GNUNET_TIME_Absolute valid_until,
1025     struct GNUNET_TIME_Absolute next_validation,
1026     enum GNUNET_TRANSPORT_ValidationState state)
1027 {
1028   struct IterationContext *pc = cls;
1029   struct ValidationIterateResponseMessage *msg;
1030
1031   if ( (GNUNET_YES == pc->all) ||
1032        (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
1033   {
1034     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1035         "Sending information about for validation entry for peer `%s' using address `%s'\n",
1036         GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
1037     msg = compose_validation_iterate_response_message (peer, address);
1038     msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
1039     msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
1040     msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
1041     msg->state = htonl ((uint32_t) state);
1042     GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
1043     GNUNET_free (msg);
1044   }
1045 }
1046
1047
1048 /**
1049  * Output information of neighbours to the given client.
1050  *
1051  * @param cls the 'struct PeerIterationContext'
1052  * @param peer identity of the neighbour
1053  * @param address the address
1054  * @param state current state this peer is in
1055  * @param state_timeout timeout for the current state of the peer
1056  * @param bandwidth_in inbound quota in NBO
1057  * @param bandwidth_out outbound quota in NBO
1058  */
1059 static void
1060 send_peer_information (void *cls,
1061     const struct GNUNET_PeerIdentity *peer,
1062     const struct GNUNET_HELLO_Address *address,
1063     enum GNUNET_TRANSPORT_PeerState state,
1064     struct GNUNET_TIME_Absolute state_timeout,
1065     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
1066     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
1067 {
1068   struct IterationContext *pc = cls;
1069   struct PeerIterateResponseMessage *msg;
1070
1071   if ( (GNUNET_YES == pc->all) ||
1072        (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
1073   {
1074     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1075         "Sending information about `%s' using address `%s' in state `%s'\n",
1076         GNUNET_i2s(peer),
1077         (address != NULL) ? GST_plugins_a2s (address) : "<none>",
1078         GNUNET_TRANSPORT_ps2s (state));
1079     msg = compose_address_iterate_response_message (peer, address);
1080     msg->state = htonl (state);
1081     msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout);
1082     GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
1083     GNUNET_free (msg);
1084   }
1085 }
1086
1087
1088
1089 /**
1090  * Client asked to obtain information about a specific or all peers
1091  * Process the request.
1092  *
1093  * @param cls unused
1094  * @param client the client
1095  * @param message the peer address information request
1096  */
1097 static void
1098 clients_handle_monitor_peers (void *cls, struct GNUNET_SERVER_Client *client,
1099                                 const struct GNUNET_MessageHeader *message)
1100 {
1101   static struct GNUNET_PeerIdentity all_zeros;
1102   struct GNUNET_SERVER_TransmitContext *tc;
1103   struct PeerMonitorMessage *msg;
1104   struct IterationContext pc;
1105
1106   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST)
1107   {
1108     GNUNET_break (0);
1109     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1110     return;
1111   }
1112   if (ntohs (message->size) != sizeof (struct PeerMonitorMessage))
1113   {
1114     GNUNET_break (0);
1115     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1116     return;
1117   }
1118   msg = (struct PeerMonitorMessage *) message;
1119   if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
1120        (NULL != lookup_monitoring_client (peer_monitoring_clients_head, client)) )
1121   {
1122     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1123                 "ServerClient %p tried to start monitoring twice\n",
1124                 client);
1125     GNUNET_break (0);
1126     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1127     return;
1128   }
1129   GNUNET_SERVER_disable_receive_done_warning (client);
1130   pc.tc = tc = GNUNET_SERVER_transmit_context_create (client);
1131
1132   /* Send initial list */
1133   if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
1134   {
1135     /* iterate over all neighbours */
1136     pc.all = GNUNET_YES;
1137     pc.id = msg->peer;
1138   }
1139   else
1140   {
1141     /* just return one neighbour */
1142     pc.all = GNUNET_NO;
1143     pc.id = msg->peer;
1144   }
1145   GST_neighbours_iterate (&send_peer_information, &pc);
1146
1147   if (GNUNET_YES != ntohl (msg->one_shot))
1148   {
1149     setup_peer_monitoring_client (client, &msg->peer);
1150   }
1151   else
1152   {
1153     GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
1154         GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
1155   }
1156
1157   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
1158 }
1159
1160
1161 /**
1162  * Client asked to obtain information about a specific or all validation
1163  * processes
1164  *
1165  * @param cls unused
1166  * @param client the client
1167  * @param message the peer address information request
1168  */
1169 static void
1170 clients_handle_monitor_validation (void *cls, struct GNUNET_SERVER_Client *client,
1171                                 const struct GNUNET_MessageHeader *message)
1172 {
1173   static struct GNUNET_PeerIdentity all_zeros;
1174   struct GNUNET_SERVER_TransmitContext *tc;
1175   struct PeerMonitorMessage *msg;
1176   struct IterationContext pc;
1177
1178   if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST)
1179   {
1180     GNUNET_break (0);
1181     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1182     return;
1183   }
1184   if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage))
1185   {
1186     GNUNET_break (0);
1187     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1188     return;
1189   }
1190   msg = (struct PeerMonitorMessage *) message;
1191   if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
1192        (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) )
1193   {
1194     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1195                 "ServerClient %p tried to start monitoring twice\n",
1196                 client);
1197     GNUNET_break (0);
1198     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1199     return;
1200   }
1201   GNUNET_SERVER_disable_receive_done_warning (client);
1202   pc.tc = tc = GNUNET_SERVER_transmit_context_create (client);
1203
1204   /* Send initial list */
1205   if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
1206   {
1207     /* iterate over all neighbours */
1208     pc.all = GNUNET_YES;
1209     pc.id = msg->peer;
1210   }
1211   else
1212   {
1213     /* just return one neighbour */
1214     pc.all = GNUNET_NO;
1215     pc.id = msg->peer;
1216   }
1217
1218   GST_validation_iterate (&send_validation_information, &pc);
1219
1220   if (GNUNET_YES != ntohl (msg->one_shot))
1221   {
1222     setup_val_monitoring_client (client, &msg->peer);
1223   }
1224   else
1225   {
1226     GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
1227         GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
1228   }
1229   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
1230 }
1231
1232 /**
1233  * Start handling requests from clients.
1234  *
1235  * @param server server used to accept clients from.
1236  */
1237 void
1238 GST_clients_start (struct GNUNET_SERVER_Handle *server)
1239 {
1240   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
1241     {&clients_handle_start, NULL,
1242      GNUNET_MESSAGE_TYPE_TRANSPORT_START, sizeof (struct StartMessage)},
1243     {&clients_handle_hello, NULL,
1244      GNUNET_MESSAGE_TYPE_HELLO, 0},
1245     {&clients_handle_send, NULL,
1246      GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
1247     {&clients_handle_request_connect, NULL,
1248      GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT,
1249      sizeof (struct TransportRequestConnectMessage)},
1250     {&clients_handle_address_to_string, NULL,
1251      GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, 0},
1252     {&clients_handle_monitor_peers, NULL,
1253      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST,
1254      sizeof (struct PeerMonitorMessage)},
1255     {&clients_handle_monitor_validation, NULL,
1256      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST,
1257      sizeof (struct ValidationMonitorMessage)},
1258     {&GST_blacklist_handle_init, NULL,
1259      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
1260      sizeof (struct GNUNET_MessageHeader)},
1261     {&GST_blacklist_handle_reply, NULL,
1262      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY,
1263      sizeof (struct BlacklistMessage)},
1264     {&GST_manipulation_set_metric, NULL,
1265      GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, 0},
1266     {NULL, NULL, 0, 0}
1267   };
1268   peer_nc = GNUNET_SERVER_notification_context_create (server, 0);
1269   val_nc = GNUNET_SERVER_notification_context_create (server, 0);
1270   GNUNET_SERVER_add_handlers (server, handlers);
1271   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
1272                                    NULL);
1273 }
1274
1275
1276 /**
1277  * Stop processing clients.
1278  */
1279 void
1280 GST_clients_stop ()
1281 {
1282   struct AddressToStringContext *cur;
1283
1284   while (NULL != (cur = a2s_head))
1285   {
1286     GNUNET_SERVER_transmit_context_destroy (cur->tc, GNUNET_NO);
1287     GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur);
1288     GNUNET_free (cur);
1289   }
1290   if (NULL != peer_nc)
1291   {
1292     GNUNET_SERVER_notification_context_destroy (peer_nc);
1293     peer_nc = NULL;
1294   }
1295   if (NULL != val_nc)
1296   {
1297     GNUNET_SERVER_notification_context_destroy (val_nc);
1298     val_nc = NULL;
1299   }
1300 }
1301
1302
1303 /**
1304  * Broadcast the given message to all of our clients.
1305  *
1306  * @param msg message to broadcast
1307  * @param may_drop #GNUNET_YES if the message can be dropped / is payload
1308  */
1309 void
1310 GST_clients_broadcast (const struct GNUNET_MessageHeader *msg, int may_drop)
1311 {
1312   struct TransportClient *tc;
1313
1314   for (tc = clients_head; NULL != tc; tc = tc->next)
1315   {
1316     if ((GNUNET_YES == may_drop) && (GNUNET_YES != tc->send_payload))
1317       continue;                 /* skip, this client does not care about payload */
1318     unicast (tc, msg, may_drop);
1319   }
1320 }
1321
1322
1323 /**
1324  * Send the given message to a particular client
1325  *
1326  * @param client target of the message
1327  * @param msg message to transmit
1328  * @param may_drop #GNUNET_YES if the message can be dropped
1329  */
1330 void
1331 GST_clients_unicast (struct GNUNET_SERVER_Client *client,
1332                      const struct GNUNET_MessageHeader *msg, int may_drop)
1333 {
1334   struct TransportClient *tc;
1335
1336   tc = lookup_client (client);
1337   if (NULL == tc)
1338     return;                     /* client got disconnected in the meantime, drop message */
1339   unicast (tc, msg, may_drop);
1340 }
1341
1342
1343 /**
1344  * Broadcast the new active address to all clients monitoring the peer.
1345  *
1346  * @param peer peer this update is about (never NULL)
1347  * @param address address, NULL on disconnect
1348  * @param state the current state of the peer
1349  * @param state_timeout the time out for the state
1350  */
1351 void
1352 GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
1353     const struct GNUNET_HELLO_Address *address,
1354     enum GNUNET_TRANSPORT_PeerState state,
1355     struct GNUNET_TIME_Absolute state_timeout)
1356 {
1357   struct PeerIterateResponseMessage *msg;
1358   struct MonitoringClient *mc;
1359   static struct GNUNET_PeerIdentity all_zeros;
1360   msg = compose_address_iterate_response_message (peer, address);
1361   msg->state = htonl (state);
1362   msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout);
1363   mc = peer_monitoring_clients_head;
1364   while (mc != NULL)
1365   {
1366     if ((0 == memcmp (&mc->peer, &all_zeros,
1367                       sizeof (struct GNUNET_PeerIdentity))) ||
1368         (0 == memcmp (&mc->peer, peer,
1369                       sizeof (struct GNUNET_PeerIdentity))))
1370     {
1371       GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client,
1372                                                   &msg->header, GNUNET_NO);
1373     }
1374
1375     mc = mc->next;
1376   }
1377   GNUNET_free (msg);
1378 }
1379
1380 /**
1381  * Broadcast the new active address to all clients monitoring the peer.
1382  *
1383  * @param peer peer this update is about (never NULL)
1384  * @param address address, NULL on disconnect
1385  * @param state the current state of the peer
1386  * @param state_timeout the time out for the state
1387  */
1388 void
1389 GST_clients_broadcast_validation_notification (
1390     const struct GNUNET_PeerIdentity *peer,
1391     const struct GNUNET_HELLO_Address *address,
1392     struct GNUNET_TIME_Absolute last_validation,
1393     struct GNUNET_TIME_Absolute valid_until,
1394     struct GNUNET_TIME_Absolute next_validation,
1395     enum GNUNET_TRANSPORT_ValidationState state)
1396 {
1397   struct ValidationIterateResponseMessage *msg;
1398   struct MonitoringClient *mc;
1399   static struct GNUNET_PeerIdentity all_zeros;
1400
1401   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1402       "Sending information about for validation entry for peer `%s' using address `%s'\n",
1403       GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
1404
1405   msg = compose_validation_iterate_response_message (peer, address);
1406   msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
1407   msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
1408   msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
1409   msg->state = htonl ((uint32_t) state);
1410   mc = val_monitoring_clients_head;
1411   while (mc != NULL)
1412   {
1413     if ((0 == memcmp (&mc->peer, &all_zeros,
1414                       sizeof (struct GNUNET_PeerIdentity))) ||
1415         (0 == memcmp (&mc->peer, peer,
1416                       sizeof (struct GNUNET_PeerIdentity))))
1417     {
1418       GNUNET_SERVER_notification_context_unicast (val_nc, mc->client,
1419                                                   &msg->header, GNUNET_NO);
1420
1421     }
1422     mc = mc->next;
1423   }
1424   GNUNET_free (msg);
1425 }
1426
1427
1428 /* end of file gnunet-service-transport_clients.c */