towards neighbour management
[oweals/gnunet.git] / src / transport / gnunet-service-transport_neighbours.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010,2011 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_neighbours.c
23  * @brief neighbour management
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet-service-transport_neighbours.h"
28 #include "gnunet-service-transport.h"
29 #include "gnunet_constants.h"
30
31
32 /**
33  * Size of the neighbour hash map.
34  */
35 #define NEIGHBOUR_TABLE_SIZE 256
36
37
38 // TODO:
39 // - have a way to access the currently 'connected' session
40 //   (for sending and to notice disconnect of it!)
41 // - have a way to access/update bandwidth/quota information per peer
42 //   (for CostReport/TrafficReport callbacks)
43
44
45 struct NeighbourMapEntry;
46
47 /**
48  * For each neighbour we keep a list of messages
49  * that we still want to transmit to the neighbour.
50  */
51 struct MessageQueue
52 {
53
54   /**
55    * This is a doubly linked list.
56    */
57   struct MessageQueue *next;
58
59   /**
60    * This is a doubly linked list.
61    */
62   struct MessageQueue *prev;
63
64   /**
65    * The message(s) we want to transmit, GNUNET_MessageHeader(s)
66    * stuck together in memory.  Allocated at the end of this struct.
67    */
68   const char *message_buf;
69
70   /**
71    * Size of the message buf
72    */
73   size_t message_buf_size;
74
75   /**
76    * Client responsible for queueing the message; used to check that a
77    * client has no two messages pending for the same target and to
78    * notify the client of a successful transmission; NULL if this is
79    * an internal message.
80    */
81   struct TransportClient *client;
82
83   /**
84    * At what time should we fail?
85    */
86   struct GNUNET_TIME_Absolute timeout;
87
88   /**
89    * Internal message of the transport system that should not be
90    * included in the usual SEND-SEND_OK transmission confirmation
91    * traffic management scheme.  Typically, "internal_msg" will
92    * be set whenever "client" is NULL (but it is not strictly
93    * required).
94    */
95   int internal_msg;
96
97   /**
98    * How important is the message?
99    */
100   unsigned int priority;
101
102 };
103
104
105
106 /**
107  * Entry in neighbours. 
108  */
109 struct NeighbourMapEntry
110 {
111
112   /**
113    * Head of list of messages we would like to send to this peer;
114    * must contain at most one message per client.
115    */
116   struct MessageQueue *messages_head;
117
118   /**
119    * Tail of list of messages we would like to send to this peer; must
120    * contain at most one message per client.
121    */
122   struct MessageQueue *messages_tail;
123
124   /**
125    * Context for peerinfo iteration.
126    * NULL after we are done processing peerinfo's information.
127    */
128   struct GNUNET_PEERINFO_IteratorContext *piter;
129
130   /**
131    * Performance data for the peer.
132    */
133   struct GNUNET_TRANSPORT_ATS_Information *ats;
134
135   /**
136    * Public key for this peer.  Valid only if the respective flag is set below.
137    */
138   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
139
140   /**
141    * Identity of this neighbour.
142    */
143   struct GNUNET_PeerIdentity id;
144
145   /**
146    * ID of task scheduled to run when this peer is about to
147    * time out (will free resources associated with the peer).
148    */
149   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
150
151   /**
152    * ID of task scheduled to run when we should retry transmitting
153    * the head of the message queue.  Actually triggered when the
154    * transmission is timing out (we trigger instantly when we have
155    * a chance of success).
156    */
157   GNUNET_SCHEDULER_TaskIdentifier retry_task;
158
159   /**
160    * How long until we should consider this peer dead (if we don't
161    * receive another message in the meantime)?
162    */
163   struct GNUNET_TIME_Absolute peer_timeout;
164
165   /**
166    * Tracker for inbound bandwidth.
167    */
168   struct GNUNET_BANDWIDTH_Tracker in_tracker;
169
170   /**
171    * The latency we have seen for this particular address for
172    * this particular peer.  This latency may have been calculated
173    * over multiple transports.  This value reflects how long it took
174    * us to receive a response when SENDING via this particular
175    * transport/neighbour/address combination!
176    *
177    * FIXME: we need to periodically send PINGs to update this
178    * latency (at least more often than the current "huge" (11h?)
179    * update interval).
180    */
181   struct GNUNET_TIME_Relative latency;
182
183   /**
184    * How often has the other peer (recently) violated the inbound
185    * traffic limit?  Incremented by 10 per violation, decremented by 1
186    * per non-violation (for each time interval).
187    */
188   unsigned int quota_violation_count;
189
190   /**
191    * DV distance to this peer (1 if no DV is used).
192    */
193   uint32_t distance;
194
195   /**
196    * Have we seen an PONG from this neighbour in the past (and
197    * not had a disconnect since)?
198    */
199   int received_pong;
200
201   /**
202    * Do we have a valid public key for this neighbour?
203    */
204   int public_key_valid;
205
206   /**
207    * Are we already in the process of disconnecting this neighbour?
208    */
209   int in_disconnect;
210
211 };
212
213
214 /**
215  * All known neighbours and their HELLOs.
216  */
217 static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
218
219 /**
220  * Closure for connect_notify_cb and disconnect_notify_cb
221  */
222 static void *callback_cls;
223
224 /**
225  * Function to call when we connected to a neighbour.
226  */
227 static GNUNET_TRANSPORT_NotifyConnect connect_notify_cb;
228
229 /**
230  * Function to call when we disconnected from a neighbour.
231  */
232 static GNUNET_TRANSPORT_NotifyDisconnect disconnect_notify_cb;
233
234
235 #if 0
236 /**
237  * Check the ready list for the given neighbour and if a plugin is
238  * ready for transmission (and if we have a message), do so!
239  *
240  * @param neighbour target peer for which to transmit
241  */
242 static void
243 try_transmission_to_peer (struct NeighbourMapEntry *n)
244 {
245   struct ReadyList *rl;
246   struct MessageQueue *mq;
247   struct GNUNET_TIME_Relative timeout;
248   ssize_t ret;
249   int force_address;
250
251   if (n->messages_head == NULL)
252     {
253 #if DEBUG_TRANSPORT
254       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255                   "Transmission queue for `%4s' is empty\n",
256                   GNUNET_i2s (&n->id));
257 #endif
258       return;                     /* nothing to do */
259     }
260   rl = NULL;
261   mq = n->messages_head;
262   force_address = GNUNET_YES;
263   if (mq->specific_address == NULL)
264     {
265       /* TODO: ADD ATS */
266       mq->specific_address = get_preferred_ats_address(n);
267       GNUNET_STATISTICS_update (stats,
268                                 gettext_noop ("# transport selected peer address freely"),
269                                 1,
270                                 GNUNET_NO);
271       force_address = GNUNET_NO;
272     }
273   if (mq->specific_address == NULL)
274     {
275       GNUNET_STATISTICS_update (stats,
276                                 gettext_noop ("# transport failed to selected peer address"),
277                                 1,
278                                 GNUNET_NO);
279       timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
280       if (timeout.rel_value == 0)
281         {
282 #if DEBUG_TRANSPORT
283           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284                       "No destination address available to transmit message of size %u to peer `%4s'\n",
285                       mq->message_buf_size,
286                       GNUNET_i2s (&mq->neighbour_id));
287 #endif
288           GNUNET_STATISTICS_update (stats,
289                                     gettext_noop ("# bytes in message queue for other peers"),
290                                     - (int64_t) mq->message_buf_size,
291                                     GNUNET_NO);
292           GNUNET_STATISTICS_update (stats,
293                                     gettext_noop ("# bytes discarded (no destination address available)"),
294                                     mq->message_buf_size,
295                                     GNUNET_NO);
296           if (mq->client != NULL)
297             transmit_send_ok (mq->client, n, &n->id, GNUNET_NO);
298           GNUNET_CONTAINER_DLL_remove (n->messages_head,
299                                        n->messages_tail,
300                                        mq);
301           GNUNET_free (mq);
302           return;               /* nobody ready */
303         }
304       GNUNET_STATISTICS_update (stats,
305                                 gettext_noop ("# message delivery deferred (no address)"),
306                                 1,
307                                 GNUNET_NO);
308       if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
309         GNUNET_SCHEDULER_cancel (n->retry_task);
310       n->retry_task = GNUNET_SCHEDULER_add_delayed (timeout,
311                                                     &retry_transmission_task,
312                                                     n);
313 #if DEBUG_TRANSPORT
314       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315                   "No validated destination address available to transmit message of size %u to peer `%4s', will wait %llums to find an address.\n",
316                   mq->message_buf_size,
317                   GNUNET_i2s (&mq->neighbour_id),
318                   timeout.rel_value);
319 #endif
320       /* FIXME: might want to trigger peerinfo lookup here
321          (unless that's already pending...) */
322       return;
323     }
324   GNUNET_CONTAINER_DLL_remove (n->messages_head,
325                                n->messages_tail,
326                                mq);
327   if (mq->specific_address->connected == GNUNET_NO)
328     mq->specific_address->connect_attempts++;
329   rl = mq->specific_address->ready_list;
330   mq->plugin = rl->plugin;
331   if (!mq->internal_msg)
332     mq->specific_address->in_transmit = GNUNET_YES;
333 #if DEBUG_TRANSPORT
334   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
335               "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
336               mq->message_buf_size,
337               GNUNET_i2s (&n->id),
338               (mq->specific_address->addr != NULL)
339               ? a2s (mq->plugin->short_name,
340                      mq->specific_address->addr,
341                      mq->specific_address->addrlen)
342               : "<inbound>",
343               rl->plugin->short_name);
344 #endif
345   GNUNET_STATISTICS_update (stats,
346                             gettext_noop ("# bytes in message queue for other peers"),
347                             - (int64_t) mq->message_buf_size,
348                             GNUNET_NO);
349   GNUNET_STATISTICS_update (stats,
350                             gettext_noop ("# bytes pending with plugins"),
351                             mq->message_buf_size,
352                             GNUNET_NO);
353
354   GNUNET_CONTAINER_DLL_insert (n->cont_head,
355                                n->cont_tail,
356                                mq);
357
358   ret = rl->plugin->api->send (rl->plugin->api->cls,
359                                &mq->neighbour_id,
360                                mq->message_buf,
361                                mq->message_buf_size,
362                                mq->priority,
363                                GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
364                                mq->specific_address->session,
365                                mq->specific_address->addr,
366                                mq->specific_address->addrlen,
367                                force_address,
368                                &transmit_send_continuation, mq);
369   if (ret == -1)
370     {
371       /* failure, but 'send' would not call continuation in this case,
372          so we need to do it here! */
373       transmit_send_continuation (mq,
374                                   &mq->neighbour_id,
375                                   GNUNET_SYSERR);
376     }
377 }
378
379
380 /**
381  * Send the specified message to the specified peer.
382  *
383  * @param client source of the transmission request (can be NULL)
384  * @param peer_address ForeignAddressList where we should send this message
385  * @param priority how important is the message
386  * @param timeout how long do we have to transmit?
387  * @param message_buf message(s) to send GNUNET_MessageHeader(s)
388  * @param message_buf_size total size of all messages in message_buf
389  * @param is_internal is this an internal message; these are pre-pended and
390  *                    also do not count for plugins being "ready" to transmit
391  * @param neighbour handle to the neighbour for transmission
392  */
393 static void
394 transmit_to_peer (struct TransportClient *client,
395                   struct ForeignAddressList *peer_address,
396                   unsigned int priority,
397                   struct GNUNET_TIME_Relative timeout,
398                   const char *message_buf,
399                   size_t message_buf_size,
400                   int is_internal, struct NeighbourMapEntry *neighbour)
401 {
402   struct MessageQueue *mq;
403
404 #if EXTRA_CHECKS
405   if (client != NULL)
406     {
407       /* check for duplicate submission */
408       mq = neighbour->messages_head;
409       while (NULL != mq)
410         {
411           if (mq->client == client)
412             {
413               /* client transmitted to same peer twice
414                  before getting SEND_OK! */
415               GNUNET_break (0);
416               return;
417             }
418           mq = mq->next;
419         }
420     }
421 #endif
422   GNUNET_STATISTICS_update (stats,
423                             gettext_noop ("# bytes in message queue for other peers"),
424                             message_buf_size,
425                             GNUNET_NO);
426   mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
427   mq->specific_address = peer_address;
428   mq->client = client;
429   /* FIXME: this memcpy can be up to 7% of our total runtime! */
430   memcpy (&mq[1], message_buf, message_buf_size);
431   mq->message_buf = (const char*) &mq[1];
432   mq->message_buf_size = message_buf_size;
433   memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
434   mq->internal_msg = is_internal;
435   mq->priority = priority;
436   mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
437   if (is_internal)
438     GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
439                                  neighbour->messages_tail,
440                                  mq);
441   else
442     GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
443                                        neighbour->messages_tail,
444                                        neighbour->messages_tail,
445                                        mq);
446   try_transmission_to_peer (neighbour);
447 }
448
449
450 /**
451  * Create a fresh entry in our neighbour list for the given peer.
452  * Will try to transmit our current HELLO to the new neighbour.
453  * Do not call this function directly, use 'setup_peer_check_blacklist.
454  *
455  * @param peer the peer for which we create the entry
456  * @param do_hello should we schedule transmitting a HELLO
457  * @return the new neighbour list entry
458  */
459 static struct NeighbourMapEntry *
460 setup_new_neighbour (const struct GNUNET_PeerIdentity *peer,
461                      int do_hello)
462 {
463   struct NeighbourMapEntry *n;
464   struct TransportPlugin *tp;
465   struct ReadyList *rl;
466
467   GNUNET_assert (0 != memcmp (peer,
468                               &my_identity,
469                               sizeof (struct GNUNET_PeerIdentity)));
470 #if DEBUG_TRANSPORT
471   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
472               "Setting up state for neighbour `%4s'\n",
473               GNUNET_i2s (peer));
474 #endif
475   GNUNET_STATISTICS_update (stats,
476                             gettext_noop ("# active neighbours"),
477                             1,
478                             GNUNET_NO);
479   n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
480   n->id = *peer;
481   n->peer_timeout =
482     GNUNET_TIME_relative_to_absolute
483     (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
484   GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
485                                  GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
486                                  MAX_BANDWIDTH_CARRY_S);
487   tp = plugins;
488   while (tp != NULL)
489     {
490       if ((tp->api->send != NULL) && (!is_blacklisted(peer, tp)))
491         {
492           rl = GNUNET_malloc (sizeof (struct ReadyList));
493           rl->neighbour = n;
494           rl->next = n->plugins;
495           n->plugins = rl;
496           rl->plugin = tp;
497           rl->addresses = NULL;
498         }
499       tp = tp->next;
500     }
501   n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
502   n->distance = -1;
503   n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
504                                                   &neighbour_timeout_task, n);
505   GNUNET_CONTAINER_multihashmap_put (neighbours,
506                                      &n->id.hashPubKey,
507                                      n,
508                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
509   if (do_hello)
510     {
511       GNUNET_STATISTICS_update (stats,
512                                 gettext_noop ("# peerinfo new neighbor iterate requests"),
513                                 1,
514                                 GNUNET_NO);
515       GNUNET_STATISTICS_update (stats,
516                                 gettext_noop ("# outstanding peerinfo iterate requests"),
517                                 1,
518                                 GNUNET_NO);
519       n->piter = GNUNET_PEERINFO_iterate (peerinfo, peer,
520                                           GNUNET_TIME_UNIT_FOREVER_REL,
521                                           &add_hello_for_peer, n);
522
523       GNUNET_STATISTICS_update (stats,
524                                 gettext_noop ("# HELLO's sent to new neighbors"),
525                                 1,
526                                 GNUNET_NO);
527       if (NULL != our_hello)
528         transmit_to_peer (NULL, NULL, 0,
529                           HELLO_ADDRESS_EXPIRATION,
530                           (const char *) our_hello, GNUNET_HELLO_size(our_hello),
531                           GNUNET_NO, n);
532     }
533   return n;
534 }
535 #endif
536
537
538 /**
539  * Initialize the neighbours subsystem.
540  *
541  * @param cls closure for callbacks
542  * @param connect_cb function to call if we connect to a peer
543  * @param disconnect_cb function to call if we disconnect from a peer
544  */
545 void 
546 GST_neighbours_start (void *cls,
547                       GNUNET_TRANSPORT_NotifyConnect connect_cb,
548                       GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb)
549 {
550   callback_cls = cls;
551   connect_notify_cb = connect_cb;
552   disconnect_notify_cb = disconnect_cb;
553   neighbours = GNUNET_CONTAINER_multihashmap_create (NEIGHBOUR_TABLE_SIZE);
554 }
555
556
557 /**
558  * Disconnect from the given neighbour.
559  *
560  * @param cls unused
561  * @param key hash of neighbour's public key (not used)
562  * @param value the 'struct NeighbourMapEntry' of the neighbour
563  */
564 static int
565 disconnect_all_neighbours (void *cls,
566                            const GNUNET_HashCode *key,
567                            void *value)
568 {
569   struct NeighbourMapEntry *n = value;
570
571 #if DEBUG_TRANSPORT
572   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
573               "Disconnecting peer `%4s', %s\n",
574               GNUNET_i2s(&n->id),
575               "SHUTDOWN_TASK");
576 #endif
577   // FIXME:
578   // disconnect_neighbour (n);
579   n++; 
580   return GNUNET_OK;
581 }
582
583
584 /**
585  * Cleanup the neighbours subsystem.
586  */
587 void
588 GST_neighbours_stop ()
589 {
590   GNUNET_CONTAINER_multihashmap_iterate (neighbours,
591                                          &disconnect_all_neighbours,
592                                          NULL);
593   GNUNET_CONTAINER_multihashmap_destroy (neighbours);
594   neighbours = NULL;
595   callback_cls = NULL;
596   connect_notify_cb = NULL;
597   disconnect_notify_cb = NULL;
598 }
599
600
601 /**
602  * Try to create a connection to the given target (eventually).
603  *
604  * @param target peer to try to connect to
605  */
606 void
607 GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
608 {
609 }
610
611
612 /**
613  * Test if we're connected to the given peer.
614  * 
615  * @param target peer to test
616  * @return GNUNET_YES if we are connected, GNUNET_NO if not
617  */
618 int
619 GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
620 {
621   return GNUNET_NO;
622 }
623
624
625 /**
626  * Transmit a message to the given target using the active connection.
627  *
628  * @param target destination
629  * @param msg message to send
630  * @param cont function to call when done
631  * @param cont_cls closure for 'cont'
632  */
633 void
634 GST_neighbours_send (const struct GNUNET_PeerIdentity *target,
635                      const struct GNUNET_MessageHeader *msg,
636                      GST_NeighbourSendContinuation cont,
637                      void *cont_cls)
638 {
639 }
640
641
642 /**
643  * Change the incoming quota for the given peer.
644  *
645  * @param neighbour identity of peer to change qutoa for
646  * @param quota new quota 
647  */
648 void
649 GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
650                                    struct GNUNET_BANDWIDTH_Value32NBO quota)
651 {
652 #if 0
653
654   n = find_neighbour (neighbour);
655   if (n == NULL)
656     {
657       GNUNET_STATISTICS_update (stats,
658                                 gettext_noop ("# SET QUOTA messages ignored (no such peer)"),
659                                 1,
660                                 GNUNET_NO);
661       return;
662     }
663   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker,
664                                          quota);
665   if (0 != ntohl (qsm->quota.value__))
666     return;
667 #if DEBUG_TRANSPORT
668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
669               "Disconnecting peer `%4s' due to `%s'\n",
670               GNUNET_i2s(&n->id),
671               "SET_QUOTA");
672 #endif
673   GNUNET_STATISTICS_update (stats,
674                             gettext_noop ("# disconnects due to quota of 0"),
675                             1,
676                             GNUNET_NO);
677   GST_neighbours_force_disconnect (neighbour);
678
679 #endif
680 }
681
682
683 /**
684  * If we have an active connection to the given target, it must be shutdown.
685  *
686  * @param target peer to disconnect from
687  */
688 void
689 GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
690 {
691 }
692
693
694 /**
695  * Iterate over all connected neighbours.
696  *
697  * @param cb function to call 
698  * @param cb_cls closure for cb
699  */
700 void
701 GST_neighbours_iterate (GST_NeighbourIterator cb,
702                         void *cb_cls)
703 {
704 }
705
706
707 /**
708  * We have received a PONG.  Update lifeness of the neighbour.
709  *
710  * @param sender peer sending the PONG
711  * @param hdr the PONG message (presumably)
712  * @param plugin_name name of transport that delivered the PONG
713  * @param sender_address address of the other peer, NULL if other peer
714  *                       connected to us
715  * @param sender_address_len number of bytes in sender_address
716  * @param ats performance data
717  * @param ats_count number of entries in ats (excluding 0-termination)
718  * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
719  */
720 int
721 GST_neighbours_handle_pong (const struct GNUNET_PeerIdentity *sender,
722                             const struct GNUNET_MessageHeader *hdr,
723                             const char *plugin_name,
724                             const void *sender_address,
725                             size_t sender_address_len,
726                             const struct GNUNET_TRANSPORT_ATS_Information *ats,
727                             uint32_t ats_count)
728 {
729   return GNUNET_SYSERR;
730 }
731
732
733 /**
734  * We have received a CONNECT.  Set the peer to connected.
735  *
736  * @param sender peer sending the PONG
737  * @param hdr the PONG message (presumably)
738  * @param plugin_name name of transport that delivered the PONG
739  * @param sender_address address of the other peer, NULL if other peer
740  *                       connected to us
741  * @param sender_address_len number of bytes in sender_address
742  * @param ats performance data
743  * @param ats_count number of entries in ats (excluding 0-termination)
744  * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
745  */
746 int
747 GST_neighbours_handle_connect (const struct GNUNET_PeerIdentity *sender,
748                                const struct GNUNET_MessageHeader *hdr,
749                                const char *plugin_name,
750                                const void *sender_address,
751                                size_t sender_address_len,
752                                const struct GNUNET_TRANSPORT_ATS_Information *ats,
753                                uint32_t ats_count)
754 {
755   return GNUNET_SYSERR;
756 }
757
758
759 /**
760  * We have received a DISCONNECT.  Set the peer to disconnected.
761  *
762  * @param sender peer sending the PONG
763  * @param hdr the PONG message (presumably)
764  * @param plugin_name name of transport that delivered the PONG
765  * @param sender_address address of the other peer, NULL if other peer
766  *                       connected to us
767  * @param sender_address_len number of bytes in sender_address
768  * @return GNUNET_OK if the message was well-formed, GNUNET_SYSERR if not
769  */
770 int
771 GST_neighbours_handle_disconnect (const struct GNUNET_PeerIdentity *sender,
772                                   const struct GNUNET_MessageHeader *hdr,
773                                   const char *plugin_name,
774                                   const void *sender_address,
775                                   size_t sender_address_len)
776 {
777   return GNUNET_SYSERR;
778 }
779
780
781 /* end of file gnunet-service-transport_neighbours.c */