aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_neighbours.c
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2011-10-28 15:43:30 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2011-10-28 15:43:30 +0000
commit363b7a14f9e07ddbdbf7d3b6e6243b276693222e (patch)
treebc779bb85411555059b8217b741f2e6b880fdec1 /src/transport/gnunet-service-transport_neighbours.c
parent3a70e67854d7696dfb0de49c7bbd19ab82b42348 (diff)
downloadgnunet-363b7a14f9e07ddbdbf7d3b6e6243b276693222e.tar.gz
gnunet-363b7a14f9e07ddbdbf7d3b6e6243b276693222e.zip
moving files from dev to final location
Diffstat (limited to 'src/transport/gnunet-service-transport_neighbours.c')
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c1116
1 files changed, 982 insertions, 134 deletions
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index e9662728a..516ef6b70 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -31,6 +31,7 @@
31#include "gnunet-service-transport_clients.h" 31#include "gnunet-service-transport_clients.h"
32#include "gnunet-service-transport.h" 32#include "gnunet-service-transport.h"
33#include "gnunet_peerinfo_service.h" 33#include "gnunet_peerinfo_service.h"
34#include "gnunet-service-transport_blacklist.h"
34#include "gnunet_constants.h" 35#include "gnunet_constants.h"
35#include "transport.h" 36#include "transport.h"
36 37
@@ -55,6 +56,12 @@
55#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90) 56#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90)
56 57
57 58
59#define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
60
61
62#define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
63
64
58/** 65/**
59 * Entry in neighbours. 66 * Entry in neighbours.
60 */ 67 */
@@ -177,6 +184,21 @@ struct MessageQueue
177 184
178}; 185};
179 186
187enum State
188{
189 /* fresh peer or completely disconnected */
190 S_NOT_CONNECTED = 0,
191 /* sent CONNECT message to other peer, waiting for CONNECT_ACK */
192 S_CONNECT_SENT = 1,
193 /* received CONNECT message to other peer, sending CONNECT_ACK */
194 S_CONNECT_RECV = 4,
195 /* sent CONNECT_ACK message to other peer, wait for ACK or payload */
196 S_CONNECT_RECV_ACK_SENT = 8,
197 /* received ACK or payload */
198 S_CONNECTED = 16,
199 /* Disconnect in progress */
200 S_DISCONNECT = 32
201};
180 202
181/** 203/**
182 * Entry in neighbours. 204 * Entry in neighbours.
@@ -254,32 +276,45 @@ struct NeighbourMapEntry
254 struct GNUNET_BANDWIDTH_Tracker in_tracker; 276 struct GNUNET_BANDWIDTH_Tracker in_tracker;
255 277
256 /** 278 /**
279 * Inbound bandwidth from ATS, activated when connection is up
280 */
281 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
282
283 /**
284 * Inbound bandwidth from ATS, activated when connection is up
285 */
286 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
287
288 /**
257 * Timestamp of the 'SESSION_CONNECT' message we got from the other peer 289 * Timestamp of the 'SESSION_CONNECT' message we got from the other peer
258 */ 290 */
259 struct GNUNET_TIME_Absolute connect_ts; 291 struct GNUNET_TIME_Absolute connect_ts;
260 292
261 /** 293 /**
262 * How often has the other peer (recently) violated the inbound 294 * Timeout for ATS
263 * traffic limit? Incremented by 10 per violation, decremented by 1 295 * We asked ATS for a new address for this peer
264 * per non-violation (for each time interval).
265 */ 296 */
266 unsigned int quota_violation_count; 297 GNUNET_SCHEDULER_TaskIdentifier ats_suggest;
267 298
268 /** 299 /**
269 * Number of values in 'ats' array. 300 * Task the resets the peer state after due to an pending
301 * unsuccessful connection setup
270 */ 302 */
271 //unsigned int ats_count; 303 GNUNET_SCHEDULER_TaskIdentifier state_reset;
272 304
273 /** 305 /**
274 * Are we already in the process of disconnecting this neighbour? 306 * How often has the other peer (recently) violated the inbound
307 * traffic limit? Incremented by 10 per violation, decremented by 1
308 * per non-violation (for each time interval).
275 */ 309 */
276 int in_disconnect; 310 unsigned int quota_violation_count;
311
277 312
278 /** 313 /**
279 * Do we currently consider this neighbour connected? (as far as 314 * The current state of the peer
280 * the connect/disconnect callbacks are concerned)? 315 * Element of enum State
281 */ 316 */
282 int is_connected; 317 int state;
283 318
284}; 319};
285 320
@@ -321,6 +356,254 @@ lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
321 return GNUNET_CONTAINER_multihashmap_get (neighbours, &pid->hashPubKey); 356 return GNUNET_CONTAINER_multihashmap_get (neighbours, &pid->hashPubKey);
322} 357}
323 358
359#define change_state(n, state, ...) change (n, state, __LINE__)
360
361static int
362is_connecting (struct NeighbourMapEntry * n)
363{
364 if ((n->state > S_NOT_CONNECTED) && (n->state < S_CONNECTED))
365 return GNUNET_YES;
366 return GNUNET_NO;
367}
368
369static int
370is_connected (struct NeighbourMapEntry * n)
371{
372 if (n->state == S_CONNECTED)
373 return GNUNET_YES;
374 return GNUNET_NO;
375}
376
377static int
378is_disconnecting (struct NeighbourMapEntry * n)
379{
380 if (n->state == S_DISCONNECT)
381 return GNUNET_YES;
382 return GNUNET_NO;
383}
384
385static const char *
386print_state (int state)
387{
388 switch (state) {
389 case S_CONNECTED:
390 return "S_CONNECTED";
391 break;
392 case S_CONNECT_RECV:
393 return "S_CONNECT_RECV";
394 break;
395 case S_CONNECT_RECV_ACK_SENT:
396 return"S_CONNECT_RECV_ACK_SENT";
397 break;
398 case S_CONNECT_SENT:
399 return "S_CONNECT_SENT";
400 break;
401 case S_DISCONNECT:
402 return "S_DISCONNECT";
403 break;
404 case S_NOT_CONNECTED:
405 return "S_NOT_CONNECTED";
406 break;
407 default:
408 GNUNET_break (0);
409 break;
410 }
411 return NULL;
412}
413
414static int
415change (struct NeighbourMapEntry * n, int state, int line);
416
417static void
418ats_suggest_cancel (void *cls,
419 const struct GNUNET_SCHEDULER_TaskContext *tc);
420
421static void
422reset_task (void *cls,
423 const struct GNUNET_SCHEDULER_TaskContext *tc)
424{
425 struct NeighbourMapEntry * n = cls;
426
427 n->state_reset = GNUNET_SCHEDULER_NO_TASK;
428
429#if DEBUG_TRANSPORT
430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
431 "Connection to peer `%s' %s failed in state `%s', resetting connection attempt \n",
432 GNUNET_i2s (&n->id), GST_plugins_a2s(n->plugin_name, n->addr, n->addrlen), print_state(n->state));
433#endif
434 GNUNET_STATISTICS_update (GST_stats,
435 gettext_noop ("# failed connection attempts due to timeout"),
436 1,
437 GNUNET_NO);
438
439 /* resetting state */
440 n->state = S_NOT_CONNECTED;
441
442 /* destroying address */
443 GNUNET_ATS_address_destroyed (GST_ats,
444 &n->id,
445 n->plugin_name,
446 n->addr,
447 n->addrlen,
448 NULL);
449
450 /* request new address */
451 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
452 GNUNET_SCHEDULER_cancel(n->ats_suggest);
453 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
454 GNUNET_ATS_suggest_address(GST_ats, &n->id);
455}
456
457static int
458change (struct NeighbourMapEntry * n, int state, int line)
459{
460 char * old = strdup(print_state(n->state));
461 char * new = strdup(print_state(state));
462
463 /* allowed transitions */
464 int allowed = GNUNET_NO;
465 switch (n->state) {
466 case S_NOT_CONNECTED:
467 if ((state == S_CONNECT_RECV) || (state == S_CONNECT_SENT) ||
468 (state == S_DISCONNECT))
469 {
470 allowed = GNUNET_YES;
471
472 /* Schedule reset task */
473 if ((state == S_CONNECT_RECV) || (state == S_CONNECT_SENT) )
474 {
475 GNUNET_assert (n->state_reset == GNUNET_SCHEDULER_NO_TASK);
476 n->state_reset = GNUNET_SCHEDULER_add_delayed (SETUP_CONNECTION_TIMEOUT, &reset_task, n);
477 }
478
479 break;
480 }
481 break;
482 case S_CONNECT_RECV:
483 if ((state == S_NOT_CONNECTED) || (state == S_DISCONNECT) ||
484 (state == S_CONNECTED) || /* FIXME SENT -> RECV ISSUE!*/ (state == S_CONNECT_SENT))
485 {
486 if ((state == S_CONNECTED) || (state == S_DISCONNECT) || (state == S_NOT_CONNECTED))
487 {
488#if DEBUG_TRANSPORT
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Removed reset task for peer `%s' %s failed in state transition `%s' -> `%s' \n",
491 GNUNET_i2s (&n->id), GST_plugins_a2s(n->plugin_name, n->addr, n->addrlen), print_state(n->state), print_state(state));
492#endif
493 GNUNET_assert (n->state_reset != GNUNET_SCHEDULER_NO_TASK);
494 GNUNET_SCHEDULER_cancel (n->state_reset);
495 n->state_reset = GNUNET_SCHEDULER_NO_TASK;
496 }
497
498 allowed = GNUNET_YES;
499 break;
500 }
501 break;
502 case S_CONNECT_SENT:
503 if ((state == S_NOT_CONNECTED) || (state == S_CONNECTED) ||
504 (state == S_DISCONNECT) || /* FIXME SENT -> RECV ISSUE!*/ (state == S_CONNECT_RECV))
505 {
506 if ((state == S_CONNECTED) || (state == S_DISCONNECT) || (state == S_NOT_CONNECTED))
507 {
508#if DEBUG_TRANSPORT
509 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
510 "Removed reset task for peer `%s' %s failed in state transition `%s' -> `%s' \n",
511 GNUNET_i2s (&n->id), GST_plugins_a2s(n->plugin_name, n->addr, n->addrlen), print_state(n->state), print_state(state));
512#endif
513 GNUNET_assert (n->state_reset != GNUNET_SCHEDULER_NO_TASK);
514 GNUNET_SCHEDULER_cancel (n->state_reset);
515 n->state_reset = GNUNET_SCHEDULER_NO_TASK;
516 }
517
518 allowed = GNUNET_YES;
519 break;
520 }
521 break;
522 case S_CONNECTED:
523 if (state == S_DISCONNECT)
524 {
525 allowed = GNUNET_YES;
526 break;
527 }
528 break;
529 case S_DISCONNECT:
530 /*
531 if (state == S_NOT_CONNECTED)
532 {
533 allowed = GNUNET_YES;
534 break;
535 }*/
536 break;
537 default:
538 GNUNET_break (0);
539 break;
540
541 }
542
543 if (allowed == GNUNET_NO)
544 {
545 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
546 "Illegal state transition from `%s' to `%s' in line %u \n",
547 old, new, line);
548 GNUNET_break (0);
549 GNUNET_free (old);
550 GNUNET_free (new);
551 return GNUNET_SYSERR;
552 }
553
554 n->state = state;
555#if DEBUG_TRANSPORT
556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "State for neighbour `%s' %X changed from `%s' to `%s' in line %u\n",
557 GNUNET_i2s (&n->id), n, old, new, line);
558#endif
559 GNUNET_free (old);
560 GNUNET_free (new);
561 return GNUNET_OK;
562}
563
564static ssize_t
565send_with_plugin ( const struct GNUNET_PeerIdentity * target,
566 const char *msgbuf,
567 size_t msgbuf_size,
568 uint32_t priority,
569 struct GNUNET_TIME_Relative timeout,
570 struct Session * session,
571 const char * plugin_name,
572 const void *addr,
573 size_t addrlen,
574 int force_address,
575 GNUNET_TRANSPORT_TransmitContinuation cont,
576 void *cont_cls)
577
578{
579 struct GNUNET_TRANSPORT_PluginFunctions *papi;
580 size_t ret = GNUNET_SYSERR;
581
582 papi = GST_plugins_find (plugin_name);
583 if (papi == NULL)
584 {
585 if (cont != NULL)
586 cont (cont_cls, target, GNUNET_SYSERR);
587 return GNUNET_SYSERR;
588 }
589
590 ret = papi->send (papi->cls,
591 target,
592 msgbuf, msgbuf_size,
593 0,
594 timeout,
595 session,
596 addr, addrlen,
597 GNUNET_YES,
598 cont, cont_cls);
599
600 if (ret == -1)
601 {
602 if (cont != NULL)
603 cont (cont_cls, target, GNUNET_SYSERR);
604 }
605 return ret;
606}
324 607
325/** 608/**
326 * Task invoked to start a transmission to another peer. 609 * Task invoked to start a transmission to another peer.
@@ -359,6 +642,11 @@ transmit_send_continuation (void *cls,
359 n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n); 642 n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
360 } 643 }
361 } 644 }
645#if DEBUG_TRANSPORT
646 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message of type %u was %s\n",
647 ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
648 (success == GNUNET_OK) ? "successful" : "FAILED");
649#endif
362 if (NULL != mq->cont) 650 if (NULL != mq->cont)
363 mq->cont (mq->cont_cls, success); 651 mq->cont (mq->cont_cls, success);
364 GNUNET_free (mq); 652 GNUNET_free (mq);
@@ -377,12 +665,17 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
377 struct MessageQueue *mq; 665 struct MessageQueue *mq;
378 struct GNUNET_TIME_Relative timeout; 666 struct GNUNET_TIME_Relative timeout;
379 ssize_t ret; 667 ssize_t ret;
380 struct GNUNET_TRANSPORT_PluginFunctions *papi;
381 668
382 if (n->is_active != NULL) 669 if (n->is_active != NULL)
670 {
671 GNUNET_break (0);
383 return; /* transmission already pending */ 672 return; /* transmission already pending */
673 }
384 if (n->transmission_task != GNUNET_SCHEDULER_NO_TASK) 674 if (n->transmission_task != GNUNET_SCHEDULER_NO_TASK)
675 {
676 GNUNET_break (0);
385 return; /* currently waiting for bandwidth */ 677 return; /* currently waiting for bandwidth */
678 }
386 while (NULL != (mq = n->messages_head)) 679 while (NULL != (mq = n->messages_head))
387 { 680 {
388 timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout); 681 timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
@@ -396,8 +689,7 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
396 if (NULL == mq) 689 if (NULL == mq)
397 return; /* no more messages */ 690 return; /* no more messages */
398 691
399 papi = GST_plugins_find (n->plugin_name); 692 if (GST_plugins_find (n->plugin_name) == NULL)
400 if (papi == NULL)
401 { 693 {
402 GNUNET_break (0); 694 GNUNET_break (0);
403 return; 695 return;
@@ -416,17 +708,19 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
416 return; 708 return;
417 } 709 }
418 710
419 ret = 711 ret = send_with_plugin (&n->id,
420 papi->send (papi->cls, &n->id, mq->message_buf, mq->message_buf_size, 712 mq->message_buf, mq->message_buf_size, 0,
421 0 /* priority -- remove from plugin API? */ , 713 timeout,
422 timeout, n->session, n->addr, n->addrlen, GNUNET_YES, 714 n->session, n->plugin_name, n->addr, n->addrlen,
423 &transmit_send_continuation, mq); 715 GNUNET_YES,
716 &transmit_send_continuation, mq);
424 if (ret == -1) 717 if (ret == -1)
425 { 718 {
426 /* failure, but 'send' would not call continuation in this case, 719 /* failure, but 'send' would not call continuation in this case,
427 * so we need to do it here! */ 720 * so we need to do it here! */
428 transmit_send_continuation (mq, &n->id, GNUNET_SYSERR); 721 transmit_send_continuation (mq, &n->id, GNUNET_SYSERR);
429 } 722 }
723
430} 724}
431 725
432 726
@@ -464,6 +758,57 @@ GST_neighbours_start (void *cls, GNUNET_TRANSPORT_NotifyConnect connect_cb,
464} 758}
465 759
466 760
761static void
762send_disconnect_cont (void *cls,
763 const struct GNUNET_PeerIdentity * target,
764 int result)
765{
766#if DEBUG_TRANSPORT
767 struct NeighbourMapEntry *n = cls;
768 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending DISCONNECT message to peer `%4s': %i\n",
769 GNUNET_i2s (&n->id), result);
770#endif
771}
772
773static int
774send_disconnect (struct NeighbourMapEntry *n)
775{
776 size_t ret;
777 struct SessionDisconnectMessage disconnect_msg;
778
779#if DEBUG_TRANSPORT
780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending DISCONNECT message to peer `%4s'\n",
781 GNUNET_i2s (&n->id));
782#endif
783
784 disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage));
785 disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
786 disconnect_msg.reserved = htonl (0);
787 disconnect_msg.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
788 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
789 sizeof (struct GNUNET_TIME_AbsoluteNBO) );
790 disconnect_msg.purpose.purpose = htonl (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT);
791 disconnect_msg.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
792 disconnect_msg.public_key = GST_my_public_key;
793 GNUNET_assert (GNUNET_OK ==
794 GNUNET_CRYPTO_rsa_sign (GST_my_private_key,
795 &disconnect_msg.purpose,
796 &disconnect_msg.signature));
797
798 ret = send_with_plugin(&n->id, (const char *) &disconnect_msg, sizeof (disconnect_msg),
799 UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
800 n->session, n->plugin_name, n->addr, n->addrlen,
801 GNUNET_YES, &send_disconnect_cont, n);
802
803 if (ret == GNUNET_SYSERR)
804 return GNUNET_SYSERR;
805
806 GNUNET_STATISTICS_update (GST_stats,
807 gettext_noop ("# peers disconnected due to external request"), 1,
808 GNUNET_NO);
809 return GNUNET_OK;
810}
811
467/** 812/**
468 * Disconnect from the given neighbour, clean up the record. 813 * Disconnect from the given neighbour, clean up the record.
469 * 814 *
@@ -473,10 +818,24 @@ static void
473disconnect_neighbour (struct NeighbourMapEntry *n) 818disconnect_neighbour (struct NeighbourMapEntry *n)
474{ 819{
475 struct MessageQueue *mq; 820 struct MessageQueue *mq;
821 int was_connected = is_connected(n);
476 822
477 if (GNUNET_YES == n->in_disconnect) 823 /* send DISCONNECT MESSAGE */
824 if (is_connected(n) || is_connecting(n))
825 {
826 if (GNUNET_OK == send_disconnect(n))
827 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent DISCONNECT_MSG to `%s'\n",
828 GNUNET_i2s (&n->id));
829 else
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not send DISCONNECT_MSG to `%s'\n",
831 GNUNET_i2s (&n->id));
832 }
833
834
835 if (is_disconnecting(n))
478 return; 836 return;
479 n->in_disconnect = GNUNET_YES; 837 change_state (n, S_DISCONNECT);
838
480 while (NULL != (mq = n->messages_head)) 839 while (NULL != (mq = n->messages_head))
481 { 840 {
482 GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq); 841 GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
@@ -489,9 +848,8 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
489 n->is_active->n = NULL; 848 n->is_active->n = NULL;
490 n->is_active = NULL; 849 n->is_active = NULL;
491 } 850 }
492 if (GNUNET_YES == n->is_connected) 851 if (was_connected)
493 { 852 {
494 n->is_connected = GNUNET_NO;
495 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->keepalive_task); 853 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->keepalive_task);
496 GNUNET_SCHEDULER_cancel (n->keepalive_task); 854 GNUNET_SCHEDULER_cancel (n->keepalive_task);
497 n->keepalive_task = GNUNET_SCHEDULER_NO_TASK; 855 n->keepalive_task = GNUNET_SCHEDULER_NO_TASK;
@@ -504,6 +862,11 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
504 GNUNET_assert (GNUNET_YES == 862 GNUNET_assert (GNUNET_YES ==
505 GNUNET_CONTAINER_multihashmap_remove (neighbours, 863 GNUNET_CONTAINER_multihashmap_remove (neighbours,
506 &n->id.hashPubKey, n)); 864 &n->id.hashPubKey, n));
865 if (GNUNET_SCHEDULER_NO_TASK != n->ats_suggest)
866 {
867 GNUNET_SCHEDULER_cancel (n->ats_suggest);
868 n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
869 }
507 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task) 870 if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
508 { 871 {
509 GNUNET_SCHEDULER_cancel (n->timeout_task); 872 GNUNET_SCHEDULER_cancel (n->timeout_task);
@@ -526,6 +889,8 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
526 n->addrlen = 0; 889 n->addrlen = 0;
527 } 890 }
528 n->session = NULL; 891 n->session = NULL;
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting peer `%4s', %X\n",
893 GNUNET_i2s (&n->id), n);
529 GNUNET_free (n); 894 GNUNET_free (n);
530} 895}
531 896
@@ -543,8 +908,8 @@ neighbour_timeout_task (void *cls,
543 struct NeighbourMapEntry *n = cls; 908 struct NeighbourMapEntry *n = cls;
544 909
545 n->timeout_task = GNUNET_SCHEDULER_NO_TASK; 910 n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
546 if (GNUNET_YES == n->is_connected) 911
547 GNUNET_STATISTICS_update (GST_stats, 912 GNUNET_STATISTICS_update (GST_stats,
548 gettext_noop ("# peers disconnected due to timeout"), 1, 913 gettext_noop ("# peers disconnected due to timeout"), 1,
549 GNUNET_NO); 914 GNUNET_NO);
550 disconnect_neighbour (n); 915 disconnect_neighbour (n);
@@ -563,25 +928,23 @@ neighbour_keepalive_task (void *cls,
563{ 928{
564 struct NeighbourMapEntry *n = cls; 929 struct NeighbourMapEntry *n = cls;
565 struct GNUNET_MessageHeader m; 930 struct GNUNET_MessageHeader m;
566 struct GNUNET_TRANSPORT_PluginFunctions *papi;
567 931
568 n->keepalive_task = GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY, 932 n->keepalive_task = GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY,
569 &neighbour_keepalive_task, 933 &neighbour_keepalive_task,
570 n); 934 n);
571 GNUNET_assert (GNUNET_YES == n->is_connected); 935 GNUNET_assert (is_connected(n));
572 GNUNET_STATISTICS_update (GST_stats, 936 GNUNET_STATISTICS_update (GST_stats,
573 gettext_noop ("# keepalives sent"), 1, 937 gettext_noop ("# keepalives sent"), 1,
574 GNUNET_NO); 938 GNUNET_NO);
575 m.size = htons (sizeof (struct GNUNET_MessageHeader)); 939 m.size = htons (sizeof (struct GNUNET_MessageHeader));
576 m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE); 940 m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
577 papi = GST_plugins_find (n->plugin_name); 941
578 if (papi != NULL) 942 send_with_plugin(&n->id, (const void *) &m,
579 papi->send (papi->cls, 943 sizeof (m),
580 &n->id, (const void *) &m, 944 UINT32_MAX /* priority */ ,
581 sizeof (m), 945 GNUNET_TIME_UNIT_FOREVER_REL,
582 UINT32_MAX /* priority */ , 946 n->session, n->plugin_name, n->addr, n->addrlen,
583 GNUNET_TIME_UNIT_FOREVER_REL, n->session, n->addr, n->addrlen, 947 GNUNET_YES, NULL, NULL);
584 GNUNET_YES, NULL, NULL);
585} 948}
586 949
587 950
@@ -601,7 +964,7 @@ disconnect_all_neighbours (void *cls, const GNUNET_HashCode * key, void *value)
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n", 964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
602 GNUNET_i2s (&n->id), "SHUTDOWN_TASK"); 965 GNUNET_i2s (&n->id), "SHUTDOWN_TASK");
603#endif 966#endif
604 if (GNUNET_YES == n->is_connected) 967 if (is_connected(n))
605 GNUNET_STATISTICS_update (GST_stats, 968 GNUNET_STATISTICS_update (GST_stats,
606 gettext_noop ("# peers disconnected due to global disconnect"), 1, 969 gettext_noop ("# peers disconnected due to global disconnect"), 1,
607 GNUNET_NO); 970 GNUNET_NO);
@@ -610,6 +973,22 @@ disconnect_all_neighbours (void *cls, const GNUNET_HashCode * key, void *value)
610} 973}
611 974
612 975
976static void
977ats_suggest_cancel (void *cls,
978 const struct GNUNET_SCHEDULER_TaskContext *tc)
979{
980 struct NeighbourMapEntry *n = cls;
981
982 n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
983
984 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
985 " ATS did not suggested address to connect to peer `%s'\n",
986 GNUNET_i2s (&n->id));
987
988 disconnect_neighbour(n);
989}
990
991
613/** 992/**
614 * Cleanup the neighbours subsystem. 993 * Cleanup the neighbours subsystem.
615 */ 994 */
@@ -631,7 +1010,7 @@ GST_neighbours_stop ()
631 1010
632/** 1011/**
633 * We tried to send a SESSION_CONNECT message to another peer. If this 1012 * We tried to send a SESSION_CONNECT message to another peer. If this
634 * succeeded, we should mark the peer up. If it failed, we should tell 1013 * succeeded, we change the state. If it failed, we should tell
635 * ATS to not use this address anymore (until it is re-validated). 1014 * ATS to not use this address anymore (until it is re-validated).
636 * 1015 *
637 * @param cls the 'struct NeighbourMapEntry' 1016 * @param cls the 'struct NeighbourMapEntry'
@@ -639,28 +1018,140 @@ GST_neighbours_stop ()
639 */ 1018 */
640static void 1019static void
641send_connect_continuation (void *cls, 1020send_connect_continuation (void *cls,
642 int success) 1021 const struct GNUNET_PeerIdentity * target,
1022 int success)
1023
643{ 1024{
644 struct NeighbourMapEntry *n = cls; 1025 struct NeighbourMapEntry *n = cls;
645 1026
646 GNUNET_assert (n != NULL); 1027 GNUNET_assert (n != NULL);
647 if (GNUNET_YES == n->in_disconnect) 1028 GNUNET_assert (!is_connected(n));
1029
1030 if (is_disconnecting(n))
648 return; /* neighbour is going away */ 1031 return; /* neighbour is going away */
649 if (GNUNET_YES != success) 1032 if (GNUNET_YES != success)
650 { 1033 {
1034#if DEBUG_TRANSPORT
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1036 "Failed to send CONNECT_MSG to peer `%4s' with plugin `%s' address '%s' session %X, asking ATS for new address \n",
1037 GNUNET_i2s (&n->id), n->plugin_name,
1038 (n->addrlen == 0) ? "<inbound>" : GST_plugins_a2s (n->plugin_name,
1039 n->addr,
1040 n->addrlen),
1041 n->session);
1042#endif
1043
651 GNUNET_ATS_address_destroyed (GST_ats, 1044 GNUNET_ATS_address_destroyed (GST_ats,
652 &n->id, 1045 &n->id,
653 n->plugin_name, 1046 n->plugin_name,
654 n->addr, 1047 n->addr,
655 n->addrlen, 1048 n->addrlen,
656 NULL); 1049 NULL);
657 disconnect_neighbour (n); 1050
1051 if (n->ats_suggest!= GNUNET_SCHEDULER_NO_TASK)
1052 GNUNET_SCHEDULER_cancel(n->ats_suggest);
1053 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
1054 GNUNET_ATS_suggest_address(GST_ats, &n->id);
658 return; 1055 return;
659 } 1056 }
1057 change_state(n, S_CONNECT_SENT);
660} 1058}
661 1059
662 1060
663/** 1061/**
1062 * We tried to switch addresses with an peer already connected. If it failed,
1063 * we should tell ATS to not use this address anymore (until it is re-validated).
1064 *
1065 * @param cls the 'struct NeighbourMapEntry'
1066 * @param success GNUNET_OK on success
1067 */
1068static void
1069send_switch_address_continuation (void *cls,
1070 const struct GNUNET_PeerIdentity * target,
1071 int success)
1072
1073{
1074 struct NeighbourMapEntry *n = cls;
1075
1076 GNUNET_assert (n != NULL);
1077 if (is_disconnecting(n))
1078 return; /* neighbour is going away */
1079
1080 GNUNET_assert (n->state == S_CONNECTED);
1081 if (GNUNET_YES != success)
1082 {
1083#if DEBUG_TRANSPORT
1084 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1085 "Failed to switch connected peer `%s' to plugin `%s' address '%s' session %X, asking ATS for new address \n",
1086 GNUNET_i2s (&n->id), n->plugin_name,
1087 (n->addrlen == 0) ? "<inbound>" : GST_plugins_a2s (n->plugin_name,
1088 n->addr,
1089 n->addrlen),
1090 n->session);
1091#endif
1092
1093 GNUNET_ATS_address_destroyed (GST_ats,
1094 &n->id,
1095 n->plugin_name,
1096 n->addr,
1097 n->addrlen,
1098 NULL);
1099
1100 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
1101 GNUNET_SCHEDULER_cancel(n->ats_suggest);
1102 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
1103 GNUNET_ATS_suggest_address(GST_ats, &n->id);
1104 return;
1105 }
1106}
1107
1108/**
1109 * We tried to send a SESSION_CONNECT message to another peer. If this
1110 * succeeded, we change the state. If it failed, we should tell
1111 * ATS to not use this address anymore (until it is re-validated).
1112 *
1113 * @param cls the 'struct NeighbourMapEntry'
1114 * @param success GNUNET_OK on success
1115 */
1116static void
1117send_connect_ack_continuation (void *cls,
1118 const struct GNUNET_PeerIdentity * target,
1119 int success)
1120
1121{
1122 struct NeighbourMapEntry *n = cls;
1123
1124 GNUNET_assert (n != NULL);
1125
1126 if (GNUNET_YES == success)
1127 return; /* sending successful */
1128
1129 /* sending failed, ask for next address */
1130#if DEBUG_TRANSPORT
1131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132 "Failed to send CONNECT_MSG to peer `%4s' with plugin `%s' address '%s' session %X, asking ATS for new address \n",
1133 GNUNET_i2s (&n->id), n->plugin_name,
1134 (n->addrlen == 0) ? "<inbound>" : GST_plugins_a2s (n->plugin_name,
1135 n->addr,
1136 n->addrlen),
1137 n->session);
1138#endif
1139 change_state(n, S_NOT_CONNECTED);
1140
1141 GNUNET_ATS_address_destroyed (GST_ats,
1142 &n->id,
1143 n->plugin_name,
1144 n->addr,
1145 n->addrlen,
1146 NULL);
1147
1148 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
1149 GNUNET_SCHEDULER_cancel(n->ats_suggest);
1150 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
1151 GNUNET_ATS_suggest_address(GST_ats, &n->id);
1152}
1153
1154/**
664 * For an existing neighbour record, set the active connection to 1155 * For an existing neighbour record, set the active connection to
665 * the given address. 1156 * the given address.
666 * 1157 *
@@ -671,20 +1162,23 @@ send_connect_continuation (void *cls,
671 * @param address_len number of bytes in address 1162 * @param address_len number of bytes in address
672 * @param session session to use (or NULL) 1163 * @param session session to use (or NULL)
673 * @param ats performance data 1164 * @param ats performance data
674 * @param ats_count number of entries in ats (excluding 0-termination) 1165 * @param ats_count number of entries in ats
675 * @return GNUNET_YES if we are currently connected, GNUNET_NO if the 1166 * @return GNUNET_YES if we are currently connected, GNUNET_NO if the
676 * connection is not up (yet) 1167 * connection is not up (yet)
677 */ 1168 */
678int 1169int
679GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer, 1170GST_neighbours_switch_to_address_3way (const struct GNUNET_PeerIdentity *peer,
680 const char *plugin_name, const void *address, 1171 const char *plugin_name, const void *address,
681 size_t address_len, struct Session *session, 1172 size_t address_len, struct Session *session,
682 const struct GNUNET_ATS_Information 1173 const struct GNUNET_ATS_Information
683 *ats, uint32_t ats_count) 1174 *ats, uint32_t ats_count,
1175 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
1176 struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
684{ 1177{
685 struct NeighbourMapEntry *n; 1178 struct NeighbourMapEntry *n;
686 struct SessionConnectMessage connect_msg; 1179 struct SessionConnectMessage connect_msg;
687 int was_connected; 1180 size_t msg_len;
1181 size_t ret;
688 1182
689 GNUNET_assert (neighbours != NULL); 1183 GNUNET_assert (neighbours != NULL);
690 n = lookup_neighbour (peer); 1184 n = lookup_neighbour (peer);
@@ -697,25 +1191,29 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
697 address_len, NULL); 1191 address_len, NULL);
698 return GNUNET_NO; 1192 return GNUNET_NO;
699 } 1193 }
700 was_connected = n->is_connected; 1194
701 n->is_connected = GNUNET_YES; 1195 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
702 if (GNUNET_YES != was_connected) 1196 {
703 n->keepalive_task = GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY, 1197 GNUNET_SCHEDULER_cancel(n->ats_suggest);
704 &neighbour_keepalive_task, 1198 n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
705 n); 1199 }
706 1200
707#if DEBUG_TRANSPORT 1201#if DEBUG_TRANSPORT
708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
709 "SWITCH! Peer `%4s' switches to plugin `%s' address '%s' session %X\n", 1203 "ATS tells us to switch to plugin `%s' address '%s' session %X for %s peer `%s'\n",
710 GNUNET_i2s (peer), plugin_name, 1204 plugin_name,
711 (address_len == 0) ? "<inbound>" : GST_plugins_a2s (plugin_name, 1205 (address_len == 0) ? "<inbound>" : GST_plugins_a2s (plugin_name,
712 address, 1206 address,
713 address_len), 1207 address_len),
714 session); 1208 session, (is_connected(n) ? "CONNECTED" : "NOT CONNECTED"),
1209 GNUNET_i2s (peer));
715#endif 1210#endif
1211
716 GNUNET_free_non_null (n->addr); 1212 GNUNET_free_non_null (n->addr);
717 n->addr = GNUNET_malloc (address_len); 1213 n->addr = GNUNET_malloc (address_len);
718 memcpy (n->addr, address, address_len); 1214 memcpy (n->addr, address, address_len);
1215 n->bandwidth_in = bandwidth_in;
1216 n->bandwidth_out = bandwidth_out;
719 n->addrlen = address_len; 1217 n->addrlen = address_len;
720 n->session = session; 1218 n->session = session;
721 GNUNET_free_non_null (n->plugin_name); 1219 GNUNET_free_non_null (n->plugin_name);
@@ -724,24 +1222,83 @@ GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
724 n->timeout_task = 1222 n->timeout_task =
725 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 1223 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
726 &neighbour_timeout_task, n); 1224 &neighbour_timeout_task, n);
727 connect_msg.header.size = htons (sizeof (struct SessionConnectMessage)); 1225
728 connect_msg.header.type = 1226 if (n->state == S_DISCONNECT)
729 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT); 1227 {
730 connect_msg.reserved = htonl (0); 1228 /* We are disconnecting, nothing to do here */
731 connect_msg.timestamp = 1229 return GNUNET_NO;
732 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 1230 }
733 GST_neighbours_send (peer, &connect_msg, sizeof (connect_msg), 1231 /* We are not connected/connecting and initiate a fresh connect */
734 GNUNET_TIME_UNIT_FOREVER_REL, 1232 if (n->state == S_NOT_CONNECTED)
735 &send_connect_continuation, 1233 {
736 n); 1234 msg_len = sizeof (struct SessionConnectMessage);
737 if (GNUNET_YES == was_connected) 1235 connect_msg.header.size = htons (msg_len);
738 return GNUNET_YES; 1236 connect_msg.header.type =
739 /* First tell clients about connected neighbours...*/ 1237 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
740 neighbours_connected++; 1238 connect_msg.reserved = htonl (0);
741 GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1, 1239 connect_msg.timestamp =
742 GNUNET_NO); 1240 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
743 connect_notify_cb (callback_cls, peer, ats, ats_count); 1241
744 return GNUNET_YES; 1242 ret = send_with_plugin (peer, (const char *) &connect_msg, msg_len, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
1243 session, plugin_name, address, address_len,
1244 GNUNET_YES, &send_connect_continuation, n);
1245
1246 return GNUNET_NO;
1247 }
1248 /* We received a CONNECT message and asked ATS for an address */
1249 else if (n->state == S_CONNECT_RECV)
1250 {
1251 msg_len = sizeof (struct SessionConnectMessage);
1252 connect_msg.header.size = htons (msg_len);
1253 connect_msg.header.type =
1254 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK);
1255 connect_msg.reserved = htonl (0);
1256 connect_msg.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1257
1258 ret = send_with_plugin(&n->id, (const void *) &connect_msg, msg_len, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
1259 session, plugin_name, address, address_len,
1260 GNUNET_YES, &send_connect_ack_continuation, n);
1261 if (ret == GNUNET_SYSERR)
1262 {
1263 change_state (n, S_NOT_CONNECTED);
1264 GNUNET_break (0);
1265 }
1266 return GNUNET_NO;
1267 }
1268 /* connected peer is switching addresses */
1269 else if (n->state == S_CONNECTED)
1270 {
1271 msg_len = sizeof (struct SessionConnectMessage);
1272 connect_msg.header.size = htons (msg_len);
1273 connect_msg.header.type =
1274 htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
1275 connect_msg.reserved = htonl (0);
1276 connect_msg.timestamp =
1277 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1278
1279 ret = send_with_plugin (peer, (const char *) &connect_msg, msg_len, UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
1280 session, plugin_name, address, address_len,
1281 GNUNET_YES, &send_switch_address_continuation, n);
1282 if (ret == GNUNET_SYSERR)
1283 {
1284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285 "Failed to send CONNECT_MESSAGE to `%4s' using plugin `%s' address '%s' session %X\n",
1286 GNUNET_i2s (peer), plugin_name,
1287 (address_len == 0) ? "<inbound>" : GST_plugins_a2s (plugin_name,
1288 address,
1289 address_len),
1290 session);
1291 }
1292 return GNUNET_NO;
1293 }
1294 else if (n->state == S_CONNECT_SENT)
1295 {
1296 //FIXME
1297 return GNUNET_NO;
1298 }
1299 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid connection state to switch addresses %u \n", n->state);
1300 GNUNET_break_op (0);
1301 return GNUNET_NO;
745} 1302}
746 1303
747 1304
@@ -763,6 +1320,7 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer)
763#endif 1320#endif
764 n = GNUNET_malloc (sizeof (struct NeighbourMapEntry)); 1321 n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
765 n->id = *peer; 1322 n->id = *peer;
1323 n->state = S_NOT_CONNECTED;
766 GNUNET_BANDWIDTH_tracker_init (&n->in_tracker, 1324 GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
767 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, 1325 GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
768 MAX_BANDWIDTH_CARRY_S); 1326 MAX_BANDWIDTH_CARRY_S);
@@ -796,8 +1354,16 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
796 memcmp (target, &GST_my_identity, 1354 memcmp (target, &GST_my_identity,
797 sizeof (struct GNUNET_PeerIdentity))); 1355 sizeof (struct GNUNET_PeerIdentity)));
798 n = lookup_neighbour (target); 1356 n = lookup_neighbour (target);
799 if ((NULL != n) && (GNUNET_YES == n->is_connected)) 1357
800 return; /* already connected */ 1358 if (NULL != n)
1359 {
1360 if ((is_connected(n)) || (is_connecting(n)))
1361 return; /* already connecting or connected */
1362 if (is_disconnecting(n))
1363 change_state (n, S_NOT_CONNECTED);
1364 }
1365
1366
801 if (n == NULL) 1367 if (n == NULL)
802 n = setup_neighbour (target); 1368 n = setup_neighbour (target);
803#if DEBUG_TRANSPORT 1369#if DEBUG_TRANSPORT
@@ -805,10 +1371,10 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
805 "Asking ATS for suggested address to connect to peer `%s'\n", 1371 "Asking ATS for suggested address to connect to peer `%s'\n",
806 GNUNET_i2s (&n->id)); 1372 GNUNET_i2s (&n->id));
807#endif 1373#endif
1374
808 GNUNET_ATS_suggest_address (GST_ats, &n->id); 1375 GNUNET_ATS_suggest_address (GST_ats, &n->id);
809} 1376}
810 1377
811
812/** 1378/**
813 * Test if we're connected to the given peer. 1379 * Test if we're connected to the given peer.
814 * 1380 *
@@ -823,7 +1389,8 @@ GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
823 GNUNET_assert (neighbours != NULL); 1389 GNUNET_assert (neighbours != NULL);
824 1390
825 n = lookup_neighbour (target); 1391 n = lookup_neighbour (target);
826 if ((NULL == n) || (n->is_connected != GNUNET_YES)) 1392
1393 if ((NULL == n) || (!is_connected(n)))
827 return GNUNET_NO; /* not connected */ 1394 return GNUNET_NO; /* not connected */
828 return GNUNET_YES; 1395 return GNUNET_YES;
829} 1396}
@@ -848,6 +1415,7 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
848 "Session %X to peer `%s' ended \n", 1415 "Session %X to peer `%s' ended \n",
849 session, GNUNET_i2s (peer)); 1416 session, GNUNET_i2s (peer));
850#endif 1417#endif
1418
851 n = lookup_neighbour (peer); 1419 n = lookup_neighbour (peer);
852 if (NULL == n) 1420 if (NULL == n)
853 return; 1421 return;
@@ -859,15 +1427,19 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
859 n->addr = NULL; 1427 n->addr = NULL;
860 n->addrlen = 0; 1428 n->addrlen = 0;
861 1429
1430 /* not connected anymore anyway, shouldn't matter */
1431 if ((!is_connected(n)) && (!is_connecting(n)))
1432 return;
862 1433
863 if (GNUNET_YES != n->is_connected) 1434 /* We are connected, so ask ATS to switch addresses */
864 return; /* not connected anymore anyway, shouldn't matter */
865 /* fast disconnect unless ATS suggests a new address */
866 GNUNET_SCHEDULER_cancel (n->timeout_task); 1435 GNUNET_SCHEDULER_cancel (n->timeout_task);
867 n->timeout_task = 1436 n->timeout_task =
868 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT, 1437 GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
869 &neighbour_timeout_task, n); 1438 &neighbour_timeout_task, n);
870 /* try QUICKLY to re-establish a connection, reduce timeout! */ 1439 /* try QUICKLY to re-establish a connection, reduce timeout! */
1440 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
1441 GNUNET_SCHEDULER_cancel(n->ats_suggest);
1442 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
871 GNUNET_ATS_suggest_address (GST_ats, peer); 1443 GNUNET_ATS_suggest_address (GST_ats, peer);
872} 1444}
873 1445
@@ -893,7 +1465,7 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
893 GNUNET_assert (neighbours != NULL); 1465 GNUNET_assert (neighbours != NULL);
894 1466
895 n = lookup_neighbour (target); 1467 n = lookup_neighbour (target);
896 if ((n == NULL) || (GNUNET_YES != n->is_connected)) 1468 if ((n == NULL) || (!is_connected(n)))
897 { 1469 {
898 GNUNET_STATISTICS_update (GST_stats, 1470 GNUNET_STATISTICS_update (GST_stats,
899 gettext_noop 1471 gettext_noop
@@ -902,9 +1474,9 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
902#if DEBUG_TRANSPORT 1474#if DEBUG_TRANSPORT
903 if (n == NULL) 1475 if (n == NULL)
904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1476 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905 "Could not send message to peer `%s': unknown neighbor", 1477 "Could not send message to peer `%s': unknown neighbour",
906 GNUNET_i2s (target)); 1478 GNUNET_i2s (target));
907 else if (GNUNET_YES != n->is_connected) 1479 else if (!is_connected(n))
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
909 "Could not send message to peer `%s': not connected\n", 1481 "Could not send message to peer `%s': not connected\n",
910 GNUNET_i2s (target)); 1482 GNUNET_i2s (target));
@@ -930,6 +1502,7 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
930 cont (cont_cls, GNUNET_SYSERR); 1502 cont (cont_cls, GNUNET_SYSERR);
931 return; 1503 return;
932 } 1504 }
1505
933 GNUNET_assert (msg_size >= sizeof (struct GNUNET_MessageHeader)); 1506 GNUNET_assert (msg_size >= sizeof (struct GNUNET_MessageHeader));
934 GNUNET_STATISTICS_update (GST_stats, 1507 GNUNET_STATISTICS_update (GST_stats,
935 gettext_noop 1508 gettext_noop
@@ -944,6 +1517,7 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
944 mq->message_buf_size = msg_size; 1517 mq->message_buf_size = msg_size;
945 mq->timeout = GNUNET_TIME_relative_to_absolute (timeout); 1518 mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
946 GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, mq); 1519 GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, mq);
1520
947 if ((GNUNET_SCHEDULER_NO_TASK == n->transmission_task) && 1521 if ((GNUNET_SCHEDULER_NO_TASK == n->transmission_task) &&
948 (NULL == n->is_active)) 1522 (NULL == n->is_active))
949 n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n); 1523 n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
@@ -986,11 +1560,8 @@ GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity
986 return GNUNET_TIME_UNIT_ZERO; 1560 return GNUNET_TIME_UNIT_ZERO;
987 } 1561 }
988 } 1562 }
989 if (GNUNET_YES != n->is_connected) 1563 if (!is_connected(n))
990 { 1564 {
991 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
992 _("Plugin gave us %d bytes of data but somehow the session is not marked as UP yet!\n"),
993 (int) size);
994 *do_forward = GNUNET_SYSERR; 1565 *do_forward = GNUNET_SYSERR;
995 return GNUNET_TIME_UNIT_ZERO; 1566 return GNUNET_TIME_UNIT_ZERO;
996 } 1567 }
@@ -1103,7 +1674,7 @@ GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
1103 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s' due to `%s'\n", 1674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s' due to `%s'\n",
1104 GNUNET_i2s (&n->id), "SET_QUOTA"); 1675 GNUNET_i2s (&n->id), "SET_QUOTA");
1105#endif 1676#endif
1106 if (GNUNET_YES == n->is_connected) 1677 if (is_connected(n))
1107 GNUNET_STATISTICS_update (GST_stats, 1678 GNUNET_STATISTICS_update (GST_stats,
1108 gettext_noop ("# disconnects due to quota of 0"), 1, 1679 gettext_noop ("# disconnects due to quota of 0"), 1,
1109 GNUNET_NO); 1680 GNUNET_NO);
@@ -1142,7 +1713,7 @@ neighbours_iterate (void *cls, const GNUNET_HashCode * key, void *value)
1142 struct IteratorContext *ic = cls; 1713 struct IteratorContext *ic = cls;
1143 struct NeighbourMapEntry *n = value; 1714 struct NeighbourMapEntry *n = value;
1144 1715
1145 if (GNUNET_YES != n->is_connected) 1716 if (is_connected(n))
1146 return GNUNET_OK; 1717 return GNUNET_OK;
1147 1718
1148 ic->cb (ic->cb_cls, &n->id, NULL, 0, n->plugin_name, n->addr, n->addrlen); 1719 ic->cb (ic->cb_cls, &n->id, NULL, 0, n->plugin_name, n->addr, n->addrlen);
@@ -1168,7 +1739,6 @@ GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls)
1168 GNUNET_CONTAINER_multihashmap_iterate (neighbours, &neighbours_iterate, &ic); 1739 GNUNET_CONTAINER_multihashmap_iterate (neighbours, &neighbours_iterate, &ic);
1169} 1740}
1170 1741
1171
1172/** 1742/**
1173 * If we have an active connection to the given target, it must be shutdown. 1743 * If we have an active connection to the given target, it must be shutdown.
1174 * 1744 *
@@ -1178,40 +1748,16 @@ void
1178GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target) 1748GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
1179{ 1749{
1180 struct NeighbourMapEntry *n; 1750 struct NeighbourMapEntry *n;
1181 struct GNUNET_TRANSPORT_PluginFunctions *papi;
1182 struct SessionDisconnectMessage disconnect_msg;
1183 1751
1184 GNUNET_assert (neighbours != NULL); 1752 GNUNET_assert (neighbours != NULL);
1185 1753
1186 n = lookup_neighbour (target); 1754 n = lookup_neighbour (target);
1187 if (NULL == n) 1755 if (NULL == n)
1188 return; /* not active */ 1756 return; /* not active */
1189 if (GNUNET_YES == n->is_connected) 1757 if (is_connected(n))
1190 { 1758 {
1191 /* we're actually connected, send DISCONNECT message */ 1759 send_disconnect(n);
1192 disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage)); 1760
1193 disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
1194 disconnect_msg.reserved = htonl (0);
1195 disconnect_msg.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
1196 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) +
1197 sizeof (struct GNUNET_TIME_AbsoluteNBO) );
1198 disconnect_msg.purpose.purpose = htonl (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT);
1199 disconnect_msg.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1200 disconnect_msg.public_key = GST_my_public_key;
1201 GNUNET_assert (GNUNET_OK ==
1202 GNUNET_CRYPTO_rsa_sign (GST_my_private_key,
1203 &disconnect_msg.purpose,
1204 &disconnect_msg.signature));
1205 papi = GST_plugins_find (n->plugin_name);
1206 if (papi != NULL)
1207 papi->send (papi->cls, target, (const void *) &disconnect_msg,
1208 sizeof (disconnect_msg),
1209 UINT32_MAX /* priority */ ,
1210 GNUNET_TIME_UNIT_FOREVER_REL, n->session, n->addr, n->addrlen,
1211 GNUNET_YES, NULL, NULL);
1212 GNUNET_STATISTICS_update (GST_stats,
1213 gettext_noop ("# peers disconnected due to external request"), 1,
1214 GNUNET_NO);
1215 n = lookup_neighbour (target); 1761 n = lookup_neighbour (target);
1216 if (NULL == n) 1762 if (NULL == n)
1217 return; /* gone already */ 1763 return; /* gone already */
@@ -1235,6 +1781,11 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer
1235 const struct SessionDisconnectMessage *sdm; 1781 const struct SessionDisconnectMessage *sdm;
1236 GNUNET_HashCode hc; 1782 GNUNET_HashCode hc;
1237 1783
1784#if DEBUG_TRANSPORT
1785 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1786 "Received DISCONNECT message from peer `%s'\n", GNUNET_i2s (peer));
1787#endif
1788
1238 if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage)) 1789 if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage))
1239 { 1790 {
1240 // GNUNET_break_op (0); 1791 // GNUNET_break_op (0);
@@ -1285,6 +1836,281 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer
1285 GST_neighbours_force_disconnect (peer); 1836 GST_neighbours_force_disconnect (peer);
1286} 1837}
1287 1838
1839/**
1840 * We received a 'SESSION_CONNECT_ACK' message from the other peer.
1841 * Consider switching to it.
1842 *
1843 * @param message possibly a 'struct SessionConnectMessage' (check format)
1844 * @param peer identity of the peer to switch the address for
1845 * @param plugin_name name of transport that delivered the PONG
1846 * @param address address of the other peer, NULL if other peer
1847 * connected to us
1848 * @param address_len number of bytes in address
1849 * @param session session to use (or NULL)
1850 * @param ats performance data
1851 * @param ats_count number of entries in ats
1852 */
1853void
1854GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message,
1855 const struct GNUNET_PeerIdentity *peer,
1856 const char *plugin_name,
1857 const char *sender_address, uint16_t sender_address_len,
1858 struct Session *session,
1859 const struct GNUNET_ATS_Information *ats,
1860 uint32_t ats_count)
1861{
1862 const struct SessionConnectMessage *scm;
1863 struct QuotaSetMessage q_msg;
1864 struct GNUNET_MessageHeader msg;
1865 struct NeighbourMapEntry *n;
1866 size_t msg_len;
1867 size_t ret;
1868 int was_connected;
1869
1870#if DEBUG_TRANSPORT
1871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1872 "Received CONNECT_ACK message from peer `%s'\n", GNUNET_i2s (peer));
1873#endif
1874
1875 if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
1876 {
1877 GNUNET_break_op (0);
1878 return;
1879 }
1880
1881 scm = (const struct SessionConnectMessage *) message;
1882 GNUNET_break_op (ntohl (scm->reserved) == 0);
1883 n = lookup_neighbour (peer);
1884 if (NULL == n)
1885 n = setup_neighbour (peer);
1886/*
1887 if (n->state != S_CONNECT_SENT)
1888 {
1889 GNUNET_break (0);
1890 send_disconnect(n);
1891 return;
1892 }
1893*/
1894 if (NULL != session)
1895 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1896 "transport-ats",
1897 "Giving ATS session %p of plugin %s for peer %s\n",
1898 session,
1899 plugin_name,
1900 GNUNET_i2s (peer));
1901 GNUNET_ATS_address_update (GST_ats,
1902 peer,
1903 plugin_name, sender_address, sender_address_len,
1904 session, ats, ats_count);
1905
1906 was_connected = is_connected(n);
1907 if (!is_connected(n))
1908 change_state (n, S_CONNECTED);
1909
1910#if DEBUG_TRANSPORT
1911 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1912 "Setting inbound quota of %u for peer `%s' to \n",
1913 ntohl (n->bandwidth_in.value__), GNUNET_i2s (&n->id));
1914#endif
1915 GST_neighbours_set_incoming_quota(&n->id, n->bandwidth_in);
1916
1917 /* send ACK (ACK)*/
1918 msg_len = sizeof (msg);
1919 msg.size = htons (msg_len);
1920 msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
1921
1922 ret = send_with_plugin (&n->id, (const char *) &msg, msg_len, UINT32_MAX,
1923 GNUNET_TIME_UNIT_FOREVER_REL,
1924 n->session, n->plugin_name, n->addr, n->addrlen,
1925 GNUNET_YES, NULL, NULL);
1926
1927 if (ret == GNUNET_SYSERR)
1928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1929 "Failed to send SESSION_ACK to `%4s' using plugin `%s' address '%s' session %X\n",
1930 GNUNET_i2s (&n->id), n->plugin_name,
1931 (n->addrlen == 0) ? "<inbound>" : GST_plugins_a2s (n->plugin_name,
1932 n->addr,
1933 n->addrlen),
1934 n->session);
1935
1936
1937 if (!was_connected)
1938 {
1939 if (n->keepalive_task == GNUNET_SCHEDULER_NO_TASK)
1940 n->keepalive_task = GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY,
1941 &neighbour_keepalive_task,
1942 n);
1943
1944 neighbours_connected++;
1945 GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
1946 GNUNET_NO);
1947 connect_notify_cb (callback_cls, &n->id, ats, ats_count);
1948
1949#if DEBUG_TRANSPORT
1950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1951 "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
1952 ntohl (n->bandwidth_out.value__), GNUNET_i2s (peer));
1953#endif
1954 q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
1955 q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
1956 q_msg.quota = n->bandwidth_out;
1957 q_msg.peer = (*peer);
1958 GST_clients_broadcast (&q_msg.header, GNUNET_NO);
1959 }
1960}
1961
1962void
1963GST_neighbours_handle_ack (const struct GNUNET_MessageHeader *message,
1964 const struct GNUNET_PeerIdentity *peer,
1965 const char *plugin_name,
1966 const char *sender_address, uint16_t sender_address_len,
1967 struct Session *session,
1968 const struct GNUNET_ATS_Information *ats,
1969 uint32_t ats_count)
1970{
1971 struct NeighbourMapEntry *n;
1972 struct QuotaSetMessage q_msg;
1973
1974#if DEBUG_TRANSPORT
1975 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1976 "Received ACK message from peer `%s'\n", GNUNET_i2s (peer));
1977#endif
1978
1979 if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
1980 {
1981 GNUNET_break_op (0);
1982 return;
1983 }
1984
1985 n = lookup_neighbour (peer);
1986 if (NULL == n)
1987 {
1988 send_disconnect(n);
1989 GNUNET_break (0);
1990 }
1991// FIXME check this
1992// if (n->state != S_CONNECT_RECV)
1993/* if (is_connecting(n))
1994 {
1995 send_disconnect (n);
1996 change_state (n, S_DISCONNECT);
1997 GNUNET_break (0);
1998 return;
1999 }
2000*/
2001 if (is_connected(n))
2002 return;
2003
2004 if (NULL != session)
2005 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2006 "transport-ats",
2007 "Giving ATS session %p of plugin %s for peer %s\n",
2008 session,
2009 plugin_name,
2010 GNUNET_i2s (peer));
2011 GNUNET_ATS_address_update (GST_ats,
2012 peer,
2013 plugin_name, sender_address, sender_address_len,
2014 session, ats, ats_count);
2015
2016 change_state (n, S_CONNECTED);
2017
2018 GST_neighbours_set_incoming_quota(&n->id, n->bandwidth_in);
2019
2020 if (n->keepalive_task == GNUNET_SCHEDULER_NO_TASK)
2021 n->keepalive_task = GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY,
2022 &neighbour_keepalive_task,
2023 n);
2024
2025 neighbours_connected++;
2026 GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
2027 GNUNET_NO);
2028 connect_notify_cb (callback_cls, &n->id, ats, ats_count);
2029
2030#if DEBUG_TRANSPORT
2031 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2032 "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
2033 ntohl (n->bandwidth_out.value__), GNUNET_i2s (peer));
2034#endif
2035
2036 q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
2037 q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
2038 q_msg.quota = n->bandwidth_out;
2039 q_msg.peer = (*peer);
2040 GST_clients_broadcast (&q_msg.header, GNUNET_NO);
2041}
2042
2043struct BlackListCheckContext
2044{
2045 struct GNUNET_ATS_Information *ats;
2046
2047 uint32_t ats_count;
2048
2049 struct Session *session;
2050
2051 char *sender_address;
2052
2053 uint16_t sender_address_len;
2054
2055 char *plugin_name;
2056
2057 struct GNUNET_TIME_Absolute ts;
2058};
2059
2060
2061static void
2062handle_connect_blacklist_cont (void *cls,
2063 const struct GNUNET_PeerIdentity
2064 * peer, int result)
2065{
2066 struct NeighbourMapEntry *n;
2067 struct BlackListCheckContext * bcc = cls;
2068
2069#if DEBUG_TRANSPORT
2070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2071 "Blacklist check due to CONNECT message: `%s'\n", GNUNET_i2s (peer), (result == GNUNET_OK) ? "ALLOWED" : "FORBIDDEN");
2072#endif
2073
2074 /* not allowed */
2075 if (GNUNET_OK != result)
2076 {
2077 GNUNET_free (bcc);
2078 return;
2079 }
2080
2081 n = lookup_neighbour (peer);
2082 if (NULL == n)
2083 n = setup_neighbour (peer);
2084
2085 if (bcc->ts.abs_value > n->connect_ts.abs_value)
2086 {
2087 if (NULL != bcc->session)
2088 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2089 "transport-ats",
2090 "Giving ATS session %p of plugin %s address `%s' for peer %s\n",
2091 bcc->session,
2092 bcc->plugin_name,
2093 GST_plugins_a2s (bcc->plugin_name, bcc->sender_address, bcc->sender_address_len),
2094 GNUNET_i2s (peer));
2095 GNUNET_ATS_address_update (GST_ats,
2096 peer,
2097 bcc->plugin_name, bcc->sender_address, bcc->sender_address_len,
2098 bcc->session, bcc->ats, bcc->ats_count);
2099 n->connect_ts = bcc->ts;
2100 }
2101
2102 GNUNET_free (bcc);
2103/*
2104 if (n->state != S_NOT_CONNECTED)
2105 return;*/
2106 change_state (n, S_CONNECT_RECV);
2107
2108 /* Ask ATS for an address to connect via that address */
2109 if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
2110 GNUNET_SCHEDULER_cancel(n->ats_suggest);
2111 n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel, n);
2112 GNUNET_ATS_suggest_address(GST_ats, peer);
2113}
1288 2114
1289/** 2115/**
1290 * We received a 'SESSION_CONNECT' message from the other peer. 2116 * We received a 'SESSION_CONNECT' message from the other peer.
@@ -1310,35 +2136,57 @@ GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
1310 uint32_t ats_count) 2136 uint32_t ats_count)
1311{ 2137{
1312 const struct SessionConnectMessage *scm; 2138 const struct SessionConnectMessage *scm;
1313 struct GNUNET_TIME_Absolute ts; 2139 struct NeighbourMapEntry * n;
1314 struct NeighbourMapEntry *n; 2140 struct BlackListCheckContext * bcc = NULL;
2141
2142#if DEBUG_TRANSPORT
2143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2144 "Received CONNECT message from peer `%s'\n", GNUNET_i2s (peer));
2145#endif
1315 2146
1316 if (ntohs (message->size) != sizeof (struct SessionConnectMessage)) 2147 if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
1317 { 2148 {
1318 GNUNET_break_op (0); 2149 GNUNET_break_op (0);
1319 return; 2150 return;
1320 } 2151 }
2152
1321 scm = (const struct SessionConnectMessage *) message; 2153 scm = (const struct SessionConnectMessage *) message;
1322 GNUNET_break_op (ntohl (scm->reserved) == 0); 2154 GNUNET_break_op (ntohl (scm->reserved) == 0);
1323 ts = GNUNET_TIME_absolute_ntoh (scm->timestamp); 2155
1324 n = lookup_neighbour (peer); 2156 n = lookup_neighbour(peer);
1325 if (NULL == n) 2157 if (n != NULL)
1326 n = setup_neighbour (peer);
1327 if (ts.abs_value > n->connect_ts.abs_value)
1328 { 2158 {
1329 if (NULL != session) 2159 /* connected peer switches addresses */
1330 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, 2160 if (is_connected(n))
1331 "transport-ats", 2161 {
1332 "Giving ATS session %p of plugin %s for peer %s\n", 2162 GNUNET_ATS_address_update(GST_ats, peer, plugin_name, sender_address, sender_address_len, session, ats, ats_count);
1333 session, 2163 return;
1334 plugin_name, 2164 }
1335 GNUNET_i2s (peer));
1336 GNUNET_ATS_address_update (GST_ats,
1337 peer,
1338 plugin_name, sender_address, sender_address_len,
1339 session, ats, ats_count);
1340 n->connect_ts = ts;
1341 } 2165 }
2166
2167 /* we are not connected to this peer */
2168 /* do blacklist check*/
2169 bcc = GNUNET_malloc (sizeof (struct BlackListCheckContext) +
2170 sizeof (struct GNUNET_ATS_Information) * ats_count +
2171 sender_address_len +
2172 strlen (plugin_name)+1);
2173
2174 bcc->ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
2175
2176 bcc->ats_count = ats_count;
2177 bcc->sender_address_len = sender_address_len;
2178 bcc->session = session;
2179
2180 bcc->ats = (struct GNUNET_ATS_Information *) &bcc[1];
2181 memcpy (bcc->ats, ats,sizeof (struct GNUNET_ATS_Information) * ats_count );
2182
2183 bcc->sender_address = (char *) &bcc->ats[ats_count];
2184 memcpy (bcc->sender_address, sender_address , sender_address_len);
2185
2186 bcc->plugin_name = &bcc->sender_address[sender_address_len];
2187 strcpy (bcc->plugin_name, plugin_name);
2188
2189 GST_blacklist_test_allowed (peer, plugin_name, handle_connect_blacklist_cont, bcc);
1342} 2190}
1343 2191
1344 2192