aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_tcp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-03-19 13:42:36 +0000
committerChristian Grothoff <christian@grothoff.org>2010-03-19 13:42:36 +0000
commit4b86063584ff95cc79b0af4f712dd5166962c1e9 (patch)
tree3b0ef9b772696fdb703e09a9a946dbdb9f2cedab /src/transport/plugin_transport_tcp.c
parentc0bb6897499d729673abd2f7d3ff1027c95b93fc (diff)
downloadgnunet-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.c71
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 */
597static struct Session *
598select_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",