diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-03-19 13:42:36 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-03-19 13:42:36 +0000 |
commit | 4b86063584ff95cc79b0af4f712dd5166962c1e9 (patch) | |
tree | 3b0ef9b772696fdb703e09a9a946dbdb9f2cedab /src/transport/plugin_transport_tcp.c | |
parent | c0bb6897499d729673abd2f7d3ff1027c95b93fc (diff) | |
download | gnunet-4b86063584ff95cc79b0af4f712dd5166962c1e9.tar.gz gnunet-4b86063584ff95cc79b0af4f712dd5166962c1e9.zip |
better session selection
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 71 |
1 files changed, 59 insertions, 12 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index afba750f2..72c99b3ea 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -174,6 +174,12 @@ struct Session | |||
174 | void *connect_addr; | 174 | void *connect_addr; |
175 | 175 | ||
176 | /** | 176 | /** |
177 | * Last activity on this connection. Used to select preferred | ||
178 | * connection. | ||
179 | */ | ||
180 | struct GNUNET_TIME_Absolute last_activity; | ||
181 | |||
182 | /** | ||
177 | * Length of connect_addr. | 183 | * Length of connect_addr. |
178 | */ | 184 | */ |
179 | size_t connect_alen; | 185 | size_t connect_alen; |
@@ -297,6 +303,7 @@ create_session (struct Plugin *plugin, | |||
297 | "Creating new session for peer `%4s'\n", | 303 | "Creating new session for peer `%4s'\n", |
298 | GNUNET_i2s (target)); | 304 | GNUNET_i2s (target)); |
299 | ret = GNUNET_malloc (sizeof (struct Session)); | 305 | ret = GNUNET_malloc (sizeof (struct Session)); |
306 | ret->last_activity = GNUNET_TIME_absolute_get (); | ||
300 | ret->plugin = plugin; | 307 | ret->plugin = plugin; |
301 | ret->next = plugin->sessions; | 308 | ret->next = plugin->sessions; |
302 | plugin->sessions = ret; | 309 | plugin->sessions = ret; |
@@ -438,6 +445,7 @@ do_transmit (void *cls, size_t size, void *buf) | |||
438 | cancel everything don't cause us to use a session that no longer | 445 | cancel everything don't cause us to use a session that no longer |
439 | exists... */ | 446 | exists... */ |
440 | process_pending_messages (session); | 447 | process_pending_messages (session); |
448 | session->last_activity = GNUNET_TIME_absolute_get (); | ||
441 | pid = session->target; | 449 | pid = session->target; |
442 | /* we'll now call callbacks that may cancel the session; hence | 450 | /* we'll now call callbacks that may cancel the session; hence |
443 | we should not use 'session' after this point */ | 451 | we should not use 'session' after this point */ |
@@ -580,6 +588,41 @@ disconnect_session (struct Session *session) | |||
580 | 588 | ||
581 | 589 | ||
582 | /** | 590 | /** |
591 | * Given two otherwise equivalent sessions, pick the better one. | ||
592 | * | ||
593 | * @param s1 one session (also default) | ||
594 | * @param s2 other session | ||
595 | * @return "better" session (more active) | ||
596 | */ | ||
597 | static struct Session * | ||
598 | select_better_session (struct Session *s1, | ||
599 | struct Session *s2) | ||
600 | { | ||
601 | if (s1 == NULL) | ||
602 | return s2; | ||
603 | if (s2 == NULL) | ||
604 | return s1; | ||
605 | if ( (s1->expecting_welcome == GNUNET_NO) && | ||
606 | (s2->expecting_welcome == GNUNET_YES) ) | ||
607 | return s1; | ||
608 | if ( (s1->expecting_welcome == GNUNET_YES) && | ||
609 | (s2->expecting_welcome == GNUNET_NO) ) | ||
610 | return s2; | ||
611 | if (s1->last_activity.value < s2->last_activity.value) | ||
612 | return s2; | ||
613 | if (s1->last_activity.value > s2->last_activity.value) | ||
614 | return s1; | ||
615 | if ( (GNUNET_YES == s1->inbound) && | ||
616 | (GNUNET_NO == s2->inbound) ) | ||
617 | return s1; | ||
618 | if ( (GNUNET_NO == s1->inbound) && | ||
619 | (GNUNET_YES == s2->inbound) ) | ||
620 | return s2; | ||
621 | return s1; | ||
622 | } | ||
623 | |||
624 | |||
625 | /** | ||
583 | * Function that can be used by the transport service to transmit | 626 | * Function that can be used by the transport service to transmit |
584 | * a message using the plugin. Note that in the case of a | 627 | * a message using the plugin. Note that in the case of a |
585 | * peer disconnecting, the continuation MUST be called | 628 | * peer disconnecting, the continuation MUST be called |
@@ -628,6 +671,7 @@ tcp_plugin_send (void *cls, | |||
628 | { | 671 | { |
629 | struct Plugin *plugin = cls; | 672 | struct Plugin *plugin = cls; |
630 | struct Session *session; | 673 | struct Session *session; |
674 | struct Session *cand_session; | ||
631 | struct Session *next; | 675 | struct Session *next; |
632 | struct PendingMessage *pm; | 676 | struct PendingMessage *pm; |
633 | struct GNUNET_CONNECTION_Handle *sa; | 677 | struct GNUNET_CONNECTION_Handle *sa; |
@@ -640,25 +684,24 @@ tcp_plugin_send (void *cls, | |||
640 | /* FIXME: we could do this a cheaper with a hash table | 684 | /* FIXME: we could do this a cheaper with a hash table |
641 | where we could restrict the iteration to entries that match | 685 | where we could restrict the iteration to entries that match |
642 | the target peer... */ | 686 | the target peer... */ |
687 | cand_session = NULL; | ||
643 | next = plugin->sessions; | 688 | next = plugin->sessions; |
644 | while (NULL != (session = next)) | 689 | while (NULL != (session = next)) |
645 | { | 690 | { |
646 | next = session->next; | 691 | next = session->next; |
647 | if (session->client == NULL) | 692 | GNUNET_assert (session->client != NULL); |
648 | continue; | ||
649 | if (0 != memcmp (target, | 693 | if (0 != memcmp (target, |
650 | &session->target, | 694 | &session->target, |
651 | sizeof (struct GNUNET_PeerIdentity))) | 695 | sizeof (struct GNUNET_PeerIdentity))) |
652 | continue; | 696 | continue; |
653 | if (GNUNET_SYSERR == force_address) | 697 | if ( ( (GNUNET_SYSERR == force_address) && |
698 | (session->expecting_welcome == GNUNET_NO) ) || | ||
699 | (GNUNET_NO == force_address) ) | ||
654 | { | 700 | { |
655 | if (session->expecting_welcome == GNUNET_NO) | 701 | cand_session = select_better_session (cand_session, |
656 | break; /* established and reliable (TCP!) */ | 702 | session); |
657 | else | 703 | continue; |
658 | continue; /* not established */ | ||
659 | } | 704 | } |
660 | if (GNUNET_NO == force_address) | ||
661 | break; | ||
662 | GNUNET_break (GNUNET_YES == force_address); | 705 | GNUNET_break (GNUNET_YES == force_address); |
663 | if (addr == NULL) | 706 | if (addr == NULL) |
664 | { | 707 | { |
@@ -669,11 +712,14 @@ tcp_plugin_send (void *cls, | |||
669 | continue; | 712 | continue; |
670 | if (addrlen != session->connect_alen) | 713 | if (addrlen != session->connect_alen) |
671 | continue; | 714 | continue; |
672 | if (0 == memcmp (session->connect_addr, | 715 | if (0 != memcmp (session->connect_addr, |
673 | addr, | 716 | addr, |
674 | addrlen)) | 717 | addrlen)) |
675 | break; | 718 | continue; |
719 | cand_session = select_better_session (cand_session, | ||
720 | session); | ||
676 | } | 721 | } |
722 | session = cand_session; | ||
677 | if ( (session == NULL) && | 723 | if ( (session == NULL) && |
678 | (addr == NULL) ) | 724 | (addr == NULL) ) |
679 | { | 725 | { |
@@ -1112,18 +1158,19 @@ handle_tcp_data (void *cls, | |||
1112 | struct Session *session; | 1158 | struct Session *session; |
1113 | struct GNUNET_TIME_Relative delay; | 1159 | struct GNUNET_TIME_Relative delay; |
1114 | 1160 | ||
1115 | session = find_session_by_client (plugin, client); | ||
1116 | if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) | 1161 | if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) |
1117 | { | 1162 | { |
1118 | /* We don't want to propagate WELCOME messages up! */ | 1163 | /* We don't want to propagate WELCOME messages up! */ |
1119 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1164 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1120 | return; | 1165 | return; |
1121 | } | 1166 | } |
1167 | session = find_session_by_client (plugin, client); | ||
1122 | if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome)) | 1168 | if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome)) |
1123 | { | 1169 | { |
1124 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1170 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1125 | return; | 1171 | return; |
1126 | } | 1172 | } |
1173 | session->last_activity = GNUNET_TIME_absolute_get (); | ||
1127 | #if DEBUG_TCP | 1174 | #if DEBUG_TCP |
1128 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 1175 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
1129 | "tcp", | 1176 | "tcp", |