aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-02-14 23:59:47 +0000
committerChristian Grothoff <christian@grothoff.org>2010-02-14 23:59:47 +0000
commita8a8461c3e3f9f60a99cb7f1f15abb3fb3ebfdf2 (patch)
tree20908bb965384d6ff60ceb1fce3d104f010dff2d
parentaf63d98838d8b6e03ee304bcf1ae736b0e81b7aa (diff)
downloadgnunet-a8a8461c3e3f9f60a99cb7f1f15abb3fb3ebfdf2.tar.gz
gnunet-a8a8461c3e3f9f60a99cb7f1f15abb3fb3ebfdf2.zip
towards better working transport code
-rw-r--r--src/transport/gnunet-service-transport.c1556
-rw-r--r--src/transport/plugin_transport.h2
-rw-r--r--src/transport/plugin_transport_tcp.c19
-rw-r--r--src/transport/plugin_transport_template.c2
-rw-r--r--src/transport/plugin_transport_udp.c2
-rw-r--r--src/transport/test_transport_api.c1
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf7
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf6
8 files changed, 816 insertions, 779 deletions
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index 937d55448..70144e8c1 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -23,11 +23,15 @@
23 * @brief low-level P2P messaging 23 * @brief low-level P2P messaging
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * 25 *
26 * TODO: 26 * NOTE:
27 * - remove AddressValidations, incorporate them into the PeerAddressLists 27 * - This code uses 'GNUNET_a2s' for debug printing in many places,
28 * which is technically wrong since it assumes we have IP+Port
29 * (v4/v6) addresses. Once we add transports like http or smtp
30 * this will have to be changed!
28 */ 31 */
29#include "platform.h" 32#include "platform.h"
30#include "gnunet_client_lib.h" 33#include "gnunet_client_lib.h"
34#include "gnunet_container_lib.h"
31#include "gnunet_constants.h" 35#include "gnunet_constants.h"
32#include "gnunet_getopt_lib.h" 36#include "gnunet_getopt_lib.h"
33#include "gnunet_hello_lib.h" 37#include "gnunet_hello_lib.h"
@@ -59,6 +63,13 @@
59#define MAX_CONNECT_RETRY 3 63#define MAX_CONNECT_RETRY 3
60 64
61/** 65/**
66 * Limit on the number of ready-to-run tasks when validating
67 * HELLOs. If more tasks are ready to run, we will drop
68 * HELLOs instead of validating them.
69 */
70#define MAX_HELLO_LOAD 4
71
72/**
62 * How often must a peer violate bandwidth quotas before we start 73 * How often must a peer violate bandwidth quotas before we start
63 * to simply drop its messages? 74 * to simply drop its messages?
64 */ 75 */
@@ -91,9 +102,9 @@
91#define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15) 102#define PLUGIN_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
92 103
93/** 104/**
94 * After how long do we expire an address in a HELLO 105 * After how long do we expire an address in a HELLO that we just
95 * that we just validated? This value is also used 106 * validated? This value is also used for our own addresses when we
96 * for our own addresses when we create a HELLO. 107 * create a HELLO.
97 */ 108 */
98#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) 109#define HELLO_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
99 110
@@ -101,34 +112,18 @@
101/** 112/**
102 * List of addresses of other peers 113 * List of addresses of other peers
103 */ 114 */
104struct PeerAddressList 115struct ForeignAddressList
105{ 116{
106 /** 117 /**
107 * This is a linked list. 118 * This is a linked list.
108 */ 119 */
109 struct PeerAddressList *next; 120 struct ForeignAddressList *next;
110
111 /*
112 * Pointer to the validation associated with this
113 * address. May be NULL if already validated!
114 */
115 struct ValidationAddress *validation;
116 121
117 /** 122 /**
118 * Which of our transport plugins does this entry 123 * Which ready list does this entry belong to.
119 * belong to?
120 */
121 struct TransportPlugin *plugin;
122
123 /**
124 * Neighbor this entry belongs to.
125 */
126 struct NeighborList *neighbor;
127
128 /*
129 * Ready list (transport) that this peer belongs to
130 */ 124 */
131 struct ReadyList *ready_list; 125 struct ReadyList *ready_list;
126
132 /** 127 /**
133 * How long until we auto-expire this address (unless it is 128 * How long until we auto-expire this address (unless it is
134 * re-confirmed by the transport)? 129 * re-confirmed by the transport)?
@@ -141,9 +136,9 @@ struct PeerAddressList
141 size_t addrlen; 136 size_t addrlen;
142 137
143 /** 138 /**
144 * The address 139 * The address.
145 */ 140 */
146 char *addr; 141 const void *addr;
147 142
148 /** 143 /**
149 * What was the last latency observed for this plugin 144 * What was the last latency observed for this plugin
@@ -158,19 +153,18 @@ struct PeerAddressList
158 * transport simply stalls writing to the stream but does not 153 * transport simply stalls writing to the stream but does not
159 * formerly get a signal that the other peer died. 154 * formerly get a signal that the other peer died.
160 */ 155 */
156 /* FIXME: Do we need this? */
161 struct GNUNET_TIME_Absolute timeout; 157 struct GNUNET_TIME_Absolute timeout;
162 158
163 /** 159 /**
164 * Is this plugin currently connected? The first time 160 * Is this plugin currently connected? The first time we transmit
165 * we transmit or send data to a peer via a particular 161 * or send data to a peer via a particular plugin, we set this to
166 * plugin, we set this to GNUNET_YES. If we later get 162 * GNUNET_YES. If we later get an error (disconnect notification or
167 * an error (disconnect notification or transmission 163 * transmission failure), we set it back to GNUNET_NO. Each time
168 * failure), we set it back to GNUNET_NO. Each time the 164 * the value is set to GNUNET_YES, we increment the
169 * value is set to GNUNET_YES, we increment the 165 * "connect_attempts" counter. If that one reaches a particular
170 * "connect_attempts" counter. If that one reaches a 166 * threshold, we consider the address to not be working properly at
171 * particular threshold, we consider the plugin to not 167 * this time and remove it from the eligible list.
172 * be working properly at this time for the given peer
173 * and remove it from the eligible list.
174 */ 168 */
175 int connected; 169 int connected;
176 170
@@ -183,6 +177,11 @@ struct PeerAddressList
183 int transmit_ready; 177 int transmit_ready;
184 178
185 /** 179 /**
180 * Has this address been validated yet?
181 */
182 int validated;
183
184 /**
186 * How often have we tried to connect using this plugin? 185 * How often have we tried to connect using this plugin?
187 */ 186 */
188 unsigned int connect_attempts; 187 unsigned int connect_attempts;
@@ -191,21 +190,21 @@ struct PeerAddressList
191 190
192 191
193/** 192/**
194 * Entry in linked list of network addresses. 193 * Entry in linked list of network addresses for ourselves.
195 */ 194 */
196struct AddressList 195struct OwnAddressList
197{ 196{
198 /** 197 /**
199 * This is a linked list. 198 * This is a linked list.
200 */ 199 */
201 struct AddressList *next; 200 struct OwnAddressList *next;
202 201
203 /** 202 /**
204 * The address, actually a pointer to the end 203 * The address, actually a pointer to the end
205 * of this struct. Do not free! 204 * of this struct. Do not free!
206 */ 205 */
207 void *addr; 206 const void *addr;
208 207
209 /** 208 /**
210 * How long until we auto-expire this address (unless it is 209 * How long until we auto-expire this address (unless it is
211 * re-confirmed by the transport)? 210 * re-confirmed by the transport)?
@@ -250,7 +249,7 @@ struct TransportPlugin
250 /** 249 /**
251 * List of our known addresses for this transport. 250 * List of our known addresses for this transport.
252 */ 251 */
253 struct AddressList *addresses; 252 struct OwnAddressList *addresses;
254 253
255 /** 254 /**
256 * Environment this transport service is using 255 * Environment this transport service is using
@@ -263,7 +262,6 @@ struct TransportPlugin
263 */ 262 */
264 GNUNET_SCHEDULER_TaskIdentifier address_update_task; 263 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
265 264
266
267 /** 265 /**
268 * Set to GNUNET_YES if we need to scrap the existing 266 * Set to GNUNET_YES if we need to scrap the existing
269 * list of "addresses" and start fresh when we receive 267 * list of "addresses" and start fresh when we receive
@@ -291,9 +289,9 @@ struct MessageQueue
291 289
292 /** 290 /**
293 * The message(s) we want to transmit, GNUNET_MessageHeader(s) 291 * The message(s) we want to transmit, GNUNET_MessageHeader(s)
294 * stuck together in memory. 292 * stuck together in memory. Allocated at the end of this struct.
295 */ 293 */
296 char *message_buf; 294 const char *message_buf;
297 295
298 /** 296 /**
299 * Size of the message buf 297 * Size of the message buf
@@ -310,17 +308,12 @@ struct MessageQueue
310 /** 308 /**
311 * Using which specific address should we send this message? 309 * Using which specific address should we send this message?
312 */ 310 */
313 struct PeerAddressList *specific_peer; 311 struct ForeignAddressList *specific_address;
314
315 /**
316 * Neighbor this entry belongs to.
317 */
318 /*struct NeighborList *neighbor;*/
319 312
320 /** 313 /**
321 * Peer ID of the Neighbor this entry belongs to. 314 * Peer ID of the Neighbor this entry belongs to.
322 */ 315 */
323 struct GNUNET_PeerIdentity *neighbor_id; 316 struct GNUNET_PeerIdentity neighbor_id;
324 317
325 /** 318 /**
326 * Plugin that we used for the transmission. 319 * Plugin that we used for the transmission.
@@ -363,15 +356,10 @@ struct ReadyList
363 struct TransportPlugin *plugin; 356 struct TransportPlugin *plugin;
364 357
365 /** 358 /**
366 * Neighbor this entry belongs to.
367 */
368 struct NeighborList *neighbor;
369
370 /**
371 * Transport addresses, latency, and readiness for 359 * Transport addresses, latency, and readiness for
372 * this particular plugin. 360 * this particular plugin.
373 */ 361 */
374 struct PeerAddressList *addresses; 362 struct ForeignAddressList *addresses;
375 363
376 /** 364 /**
377 * Is this plugin ready to transmit to the specific target? 365 * Is this plugin ready to transmit to the specific target?
@@ -379,12 +367,15 @@ struct ReadyList
379 * transmission is in progress, "transmit_ready" is set to 367 * transmission is in progress, "transmit_ready" is set to
380 * GNUNET_NO. 368 * GNUNET_NO.
381 */ 369 */
370 // FIXME: is this dead?
382 int plugin_transmit_ready; 371 int plugin_transmit_ready;
383 372
384 /** 373 /**
385 * Are any of our PeerAddressList addresses still connected? 374 * Is the plugin represented by this entry currently connected to
375 * the respective peer?
386 */ 376 */
387 int connected; /* FIXME: dynamically check PeerAddressList addresses when asked to! */ 377 int connected;
378
388}; 379};
389 380
390 381
@@ -435,12 +426,6 @@ struct NeighborList
435 struct GNUNET_TIME_Absolute last_quota_update; 426 struct GNUNET_TIME_Absolute last_quota_update;
436 427
437 /** 428 /**
438 * At what time should we try to again add plugins to
439 * our ready list?
440 */
441 struct GNUNET_TIME_Absolute retry_plugins_time;
442
443 /**
444 * The latency we have seen for this particular address for 429 * The latency we have seen for this particular address for
445 * this particular peer. This latency may have been calculated 430 * this particular peer. This latency may have been calculated
446 * over multiple transports. This value reflects how long it took 431 * over multiple transports. This value reflects how long it took
@@ -616,20 +601,16 @@ struct TransportClient
616 601
617 602
618/** 603/**
619 * For each HELLO, we may have to validate multiple addresses; 604 * Entry in map of all HELLOs awaiting validation.
620 * each address gets its own request entry.
621 */ 605 */
622struct ValidationAddress 606struct ValidationEntry
623{ 607{
624 /**
625 * This is a linked list.
626 */
627 struct ValidationAddress *next;
628 608
629 /** 609 /**
630 * What peer_address does this validation belong to? 610 * The address, actually a pointer to the end
611 * of this struct. Do not free!
631 */ 612 */
632 struct PeerAddressList *peer_address; 613 const void *addr;
633 614
634 /** 615 /**
635 * Name of the transport. 616 * Name of the transport.
@@ -637,9 +618,15 @@ struct ValidationAddress
637 char *transport_name; 618 char *transport_name;
638 619
639 /** 620 /**
640 * When should this validated address expire? 621 * The public key of the peer.
641 */ 622 */
642 struct GNUNET_TIME_Absolute expiration; 623 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
624
625 /**
626 * ID of task that will clean up this entry if we don't succeed
627 * with the validation first.
628 */
629 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
643 630
644 /** 631 /**
645 * At what time did we send this validation? 632 * At what time did we send this validation?
@@ -647,91 +634,62 @@ struct ValidationAddress
647 struct GNUNET_TIME_Absolute send_time; 634 struct GNUNET_TIME_Absolute send_time;
648 635
649 /** 636 /**
650 * Challenge number we used. 637 * Length of addr.
651 */ 638 */
652 uint32_t challenge; 639 size_t addrlen;
653 640
654 /** 641 /**
655 * Set to GNUNET_YES if the challenge was met, 642 * Challenge number we used.
656 * GNUNET_SYSERR if we know it failed, GNUNET_NO
657 * if we are waiting on a response.
658 */ 643 */
659 int ok; 644 uint32_t challenge;
645
660}; 646};
661 647
662 648
663/** 649/**
664 * Entry in linked list of all HELLOs awaiting validation. 650 * Context of currently active requests to peerinfo
651 * for validation of HELLOs.
665 */ 652 */
666struct ValidationList 653struct CheckHelloValidatedContext
667{ 654{
668 655
669 /** 656 /**
670 * This is a linked list. 657 * This is a doubly-linked list.
671 */ 658 */
672 struct ValidationList *next; 659 struct CheckHelloValidatedContext *next;
673 660
674 /** 661 /**
675 * Linked list with one entry per address from the HELLO 662 * This is a doubly-linked list.
676 * that needs to be validated.
677 */ 663 */
678 struct ValidationAddress *addresses; 664 struct CheckHelloValidatedContext *prev;
679
680 /**
681 * The public key of the peer.
682 */
683 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
684
685 /**
686 * When does this record time-out? (assuming the
687 * challenge goes unanswered)
688 */
689 struct GNUNET_TIME_Absolute timeout;
690
691};
692
693
694struct CheckHelloValidatedContext
695{
696 /**
697 * Plugin for which we are validating.
698 */
699 struct TransportPlugin *plugin;
700 665
701 /** 666 /**
702 * Hello that we are validating. 667 * Hello that we are validating.
703 */ 668 */
704 struct GNUNET_HELLO_Message *hello; 669 const struct GNUNET_HELLO_Message *hello;
705
706 /**
707 * Validation list being built.
708 */
709 struct ValidationList *e;
710 670
711 /** 671 /**
712 * Context for peerinfo iteration. 672 * Context for peerinfo iteration.
713 * NULL after we are done processing peerinfo's information. 673 * NULL after we are done processing peerinfo's information.
714 */ 674 */
715 struct GNUNET_PEERINFO_IteratorContext *piter; 675 struct GNUNET_PEERINFO_IteratorContext *piter;
676
677 /**
678 * Was a HELLO known for this peer to peerinfo?
679 */
680 int hello_known;
716 681
717}; 682};
718 683
719 684
720
721/**
722 * HELLOs awaiting validation.
723 */
724static struct ValidationList *pending_validations;
725
726/** 685/**
727 * Our HELLO message. 686 * Our HELLO message.
728 */ 687 */
729static struct GNUNET_HELLO_Message *our_hello; 688static struct GNUNET_HELLO_Message *our_hello;
730 689
731/** 690/**
732 * "version" of "our_hello". Used to see if a given 691 * "version" of "our_hello". Used to see if a given neighbor has
733 * neighbor has already been sent the latest version 692 * already been sent the latest version of our HELLO message.
734 * of our HELLO message.
735 */ 693 */
736static unsigned int our_hello_version; 694static unsigned int our_hello_version;
737 695
@@ -786,6 +744,25 @@ static struct NeighborList *neighbors;
786static uint32_t max_connect_per_transport; 744static uint32_t max_connect_per_transport;
787 745
788/** 746/**
747 * Head of linked list.
748 */
749static struct CheckHelloValidatedContext *chvc_head;
750
751/**
752 * Tail of linked list.
753 */
754static struct CheckHelloValidatedContext *chvc_tail;
755
756
757/**
758 * Map of PeerIdentities to 'struct ValidationEntry*'s (addresses
759 * of the given peer that we are currently validating).
760 */
761static struct GNUNET_CONTAINER_MultiHashMap *validation_map;
762
763
764
765/**
789 * The peer specified by the given neighbor has timed-out or a plugin 766 * The peer specified by the given neighbor has timed-out or a plugin
790 * has disconnected. We may either need to do nothing (other plugins 767 * has disconnected. We may either need to do nothing (other plugins
791 * still up), or trigger a full disconnect and clean up. This 768 * still up), or trigger a full disconnect and clean up. This
@@ -800,15 +777,13 @@ static uint32_t max_connect_per_transport;
800 */ 777 */
801static void disconnect_neighbor (struct NeighborList *n, int check); 778static void disconnect_neighbor (struct NeighborList *n, int check);
802 779
803
804/** 780/**
805 * Check the ready list for the given neighbor and 781 * Check the ready list for the given neighbor and if a plugin is
806 * if a plugin is ready for transmission (and if we 782 * ready for transmission (and if we have a message), do so!
807 * have a message), do so!
808 * 783 *
809 * @param neighbor target peer for which to check the plugins 784 * @param neighbor target peer for which to transmit
810 */ 785 */
811static ssize_t try_transmission_to_peer (struct NeighborList *neighbor); 786static void try_transmission_to_peer (struct NeighborList *neighbor);
812 787
813 788
814/** 789/**
@@ -827,7 +802,6 @@ find_neighbor (const struct GNUNET_PeerIdentity *key)
827 while ((head != NULL) && 802 while ((head != NULL) &&
828 (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity)))) 803 (0 != memcmp (key, &head->id, sizeof (struct GNUNET_PeerIdentity))))
829 head = head->next; 804 head = head->next;
830
831 return head; 805 return head;
832} 806}
833 807
@@ -891,10 +865,9 @@ update_quota (struct NeighborList *n)
891 865
892 866
893/** 867/**
894 * Function called to notify a client about the socket 868 * Function called to notify a client about the socket being ready to
895 * being ready to queue more data. "buf" will be 869 * queue more data. "buf" will be NULL and "size" zero if the socket
896 * NULL and "size" zero if the socket was closed for 870 * was closed for writing in the meantime.
897 * writing in the meantime.
898 * 871 *
899 * @param cls closure 872 * @param cls closure
900 * @param size number of bytes available in buf 873 * @param size number of bytes available in buf
@@ -1017,36 +990,6 @@ transmit_to_client (struct TransportClient *client,
1017 990
1018 991
1019/** 992/**
1020 * Find alternative plugins for communication.
1021 *
1022 * @param neighbor for which neighbor should we try to find
1023 * more plugins?
1024 */
1025static void
1026try_alternative_plugins (struct NeighborList *neighbor)
1027{
1028 struct ReadyList *rl;
1029
1030 if ((neighbor->plugins != NULL) &&
1031 (neighbor->retry_plugins_time.value >
1032 GNUNET_TIME_absolute_get ().value))
1033 return; /* don't try right now */
1034 neighbor->retry_plugins_time
1035 = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
1036
1037 rl = neighbor->plugins;
1038#if WTF /* FIXME: What is this supposed to do? */
1039 while (rl != NULL)
1040 {
1041 if (rl->connect_attempts > 0)
1042 rl->connect_attempts--; /* amnesty */
1043 rl = rl->next;
1044 }
1045#endif
1046}
1047
1048
1049/**
1050 * Function called by the GNUNET_TRANSPORT_TransmitFunction 993 * Function called by the GNUNET_TRANSPORT_TransmitFunction
1051 * upon "completion" of a send request. This tells the API 994 * upon "completion" of a send request. This tells the API
1052 * that it is now legal to send another message to the given 995 * that it is now legal to send another message to the given
@@ -1071,7 +1014,7 @@ transmit_send_continuation (void *cls,
1071 struct NeighborList *n; 1014 struct NeighborList *n;
1072 1015
1073 GNUNET_assert (mq != NULL); 1016 GNUNET_assert (mq != NULL);
1074 n = find_neighbor(mq->neighbor_id); 1017 n = find_neighbor(&mq->neighbor_id);
1075 if (n == NULL) /* Neighbor must have been removed asynchronously! */ 1018 if (n == NULL) /* Neighbor must have been removed asynchronously! */
1076 return; 1019 return;
1077 1020
@@ -1082,7 +1025,7 @@ transmit_send_continuation (void *cls,
1082 1025
1083 if (result == GNUNET_OK) 1026 if (result == GNUNET_OK)
1084 { 1027 {
1085 mq->specific_peer->timeout = 1028 mq->specific_address->timeout =
1086 GNUNET_TIME_relative_to_absolute 1029 GNUNET_TIME_relative_to_absolute
1087 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1030 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1088 } 1031 }
@@ -1091,7 +1034,7 @@ transmit_send_continuation (void *cls,
1091 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1092 "Transmission to peer `%s' failed, marking connection as down.\n", 1035 "Transmission to peer `%s' failed, marking connection as down.\n",
1093 GNUNET_i2s (target)); 1036 GNUNET_i2s (target));
1094 mq->specific_peer->connected = GNUNET_NO; 1037 mq->specific_address->connected = GNUNET_NO;
1095 } 1038 }
1096 if (!mq->internal_msg) 1039 if (!mq->internal_msg)
1097 { 1040 {
@@ -1099,7 +1042,7 @@ transmit_send_continuation (void *cls,
1099 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1100 "Setting transmit_ready on transport!\n"); 1043 "Setting transmit_ready on transport!\n");
1101#endif 1044#endif
1102 mq->specific_peer->transmit_ready = GNUNET_YES; 1045 mq->specific_address->transmit_ready = GNUNET_YES;
1103 } 1046 }
1104 1047
1105 if (mq->client != NULL) 1048 if (mq->client != NULL)
@@ -1113,8 +1056,6 @@ transmit_send_continuation (void *cls,
1113 send_ok_msg.peer = n->id; 1056 send_ok_msg.peer = n->id;
1114 transmit_to_client (mq->client, &send_ok_msg.header, GNUNET_NO); 1057 transmit_to_client (mq->client, &send_ok_msg.header, GNUNET_NO);
1115 } 1058 }
1116 GNUNET_free (mq->message_buf);
1117 GNUNET_free (mq->neighbor_id);
1118 GNUNET_free (mq); 1059 GNUNET_free (mq);
1119 /* one plugin just became ready again, try transmitting 1060 /* one plugin just became ready again, try transmitting
1120 another message (if available) */ 1061 another message (if available) */
@@ -1125,29 +1066,36 @@ transmit_send_continuation (void *cls,
1125} 1066}
1126 1067
1127 1068
1128 1069/**
1129 1070 * Find an address in any of the available transports for
1130struct PeerAddressList * 1071 * the given neighbor that would be good for message
1072 * transmission. This is essentially the transport selection
1073 * routine.
1074 *
1075 * @param neighbor for whom to select an address
1076 * @return selected address, NULL if we have none
1077 */
1078struct ForeignAddressList *
1131find_ready_address(struct NeighborList *neighbor) 1079find_ready_address(struct NeighborList *neighbor)
1132{ 1080{
1133 struct ReadyList *head = neighbor->plugins; 1081 struct ReadyList *head = neighbor->plugins;
1134 struct PeerAddressList *addresses; 1082 struct ForeignAddressList *addresses;
1135 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); 1083 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
1136 struct PeerAddressList *best_address; 1084 struct ForeignAddressList *best_address;
1137 1085
1138 best_address = NULL; 1086 best_address = NULL;
1139 while (head != NULL) 1087 while (head != NULL)
1140 { 1088 {
1141 addresses = head->addresses; 1089 addresses = head->addresses;
1142
1143 while (addresses != NULL) 1090 while (addresses != NULL)
1144 { 1091 {
1145 if ((addresses->timeout.value < now.value) && (addresses->connected == GNUNET_YES)) 1092 if ( (addresses->timeout.value < now.value) &&
1093 (addresses->connected == GNUNET_YES) )
1146 { 1094 {
1147#if DEBUG_TRANSPORT 1095#if DEBUG_TRANSPORT
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1149 "Marking long-time inactive connection to `%4s' as down.\n", 1097 "Marking long-time inactive connection to `%4s' as down.\n",
1150 GNUNET_i2s (&addresses->ready_list->neighbor->id)); 1098 GNUNET_i2s (&neighbor->id));
1151#endif 1099#endif
1152 addresses->connected = GNUNET_NO; 1100 addresses->connected = GNUNET_NO;
1153 } 1101 }
@@ -1157,17 +1105,15 @@ find_ready_address(struct NeighborList *neighbor)
1157 addresses = head->addresses; 1105 addresses = head->addresses;
1158 while (addresses != NULL) 1106 while (addresses != NULL)
1159 { 1107 {
1160 if ((addresses->connected == GNUNET_YES) && 1108 if ( ( (best_address == NULL) ||
1161 (addresses->transmit_ready == GNUNET_YES) && 1109 (addresses->connected == GNUNET_YES) ||
1162 ((best_address == NULL) || (addresses->latency.value < best_address->latency.value))) 1110 (best_address->connected == GNUNET_NO) ) &&
1163 { 1111 (addresses->transmit_ready == GNUNET_YES) &&
1164#if DEBUG_TRANSPORT 1112 ( (best_address == NULL) ||
1165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1113 (addresses->latency.value < best_address->latency.value)) )
1166 "Found address with latency %llu (previous best was %llu), setting as best found yet!\n", 1114 best_address = addresses;
1167 addresses->latency.value, best_address == NULL ? -1LL : best_address->latency.value); 1115 /* FIXME: also give lower-latency addresses that are not
1168#endif 1116 connected a chance some times... */
1169 best_address = addresses;
1170 }
1171 addresses = addresses->next; 1117 addresses = addresses->next;
1172 } 1118 }
1173 head = head->next; 1119 head = head->next;
@@ -1176,7 +1122,7 @@ find_ready_address(struct NeighborList *neighbor)
1176 if (best_address != NULL) 1122 if (best_address != NULL)
1177 { 1123 {
1178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1179 "Best address found has latency of %llu!\n", 1125 "Best address found has latency of %llu ms.\n",
1180 best_address->latency.value); 1126 best_address->latency.value);
1181 } 1127 }
1182#endif 1128#endif
@@ -1184,62 +1130,61 @@ find_ready_address(struct NeighborList *neighbor)
1184 1130
1185} 1131}
1186 1132
1133
1187/** 1134/**
1188 * Check the ready list for the given neighbor and 1135 * Check the ready list for the given neighbor and if a plugin is
1189 * if a plugin is ready for transmission (and if we 1136 * ready for transmission (and if we have a message), do so!
1190 * have a message), do so! 1137 *
1138 * @param neighbor target peer for which to transmit
1191 */ 1139 */
1192static ssize_t 1140static void
1193try_transmission_to_peer (struct NeighborList *neighbor) 1141try_transmission_to_peer (struct NeighborList *neighbor)
1194{ 1142{
1195 struct GNUNET_TIME_Relative min_latency; 1143 struct GNUNET_TIME_Relative min_latency;
1196 struct ReadyList *rl; 1144 struct ReadyList *rl;
1197 struct MessageQueue *mq; 1145 struct MessageQueue *mq;
1198 struct GNUNET_TIME_Absolute now;
1199 1146
1200 if (neighbor->messages == NULL) 1147 if (neighbor->messages == NULL)
1201 return 0; /* nothing to do */ 1148 return; /* nothing to do */
1202 try_alternative_plugins (neighbor);
1203 min_latency = GNUNET_TIME_UNIT_FOREVER_REL; 1149 min_latency = GNUNET_TIME_UNIT_FOREVER_REL;
1204 rl = NULL; 1150 rl = NULL;
1205 mq = neighbor->messages; 1151 mq = neighbor->messages;
1206 now = GNUNET_TIME_absolute_get (); 1152 if (mq->specific_address == NULL)
1207 1153 mq->specific_address = find_ready_address(neighbor);
1208 if (mq->specific_peer == NULL) 1154 if (mq->specific_address == NULL)
1209 mq->specific_peer = find_ready_address(neighbor); /* Find first available (or best!) address to transmit to */
1210
1211 if (mq->specific_peer == NULL)
1212 { 1155 {
1213#if DEBUG_TRANSPORT 1156#if DEBUG_TRANSPORT
1214 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1215 "No plugin ready to transmit message\n"); 1158 "No destination address available to transmit message of size %u to peer `%4s'\n",
1159 mq->message_buf_size,
1160 GNUNET_i2s (&mq->neighbor_id));
1216#endif 1161#endif
1217 return 0; /* nobody ready */ 1162 return; /* nobody ready */
1218 } 1163 }
1219 1164 rl = mq->specific_address->ready_list;
1220 rl = mq->specific_peer->ready_list;
1221 neighbor->messages = mq->next; 1165 neighbor->messages = mq->next;
1222 mq->plugin = rl->plugin; 1166 mq->plugin = rl->plugin;
1223 if (!mq->internal_msg) 1167 if (!mq->internal_msg)
1224 mq->specific_peer->transmit_ready = GNUNET_NO; 1168 mq->specific_address->transmit_ready = GNUNET_NO;
1225#if DEBUG_TRANSPORT 1169#if DEBUG_TRANSPORT
1226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227 "Giving message of size %u for `%4s' to plugin `%s'\n", 1171 "Sending message of size %u for `%4s' to `%s' via plugin `%s'\n",
1228 mq->message_buf_size, 1172 mq->message_buf_size,
1229 GNUNET_i2s (&neighbor->id), rl->plugin->short_name); 1173 GNUNET_i2s (&neighbor->id),
1174 GNUNET_a2s (mq->specific_address->addr,
1175 mq->specific_address->addrlen),
1176 rl->plugin->short_name);
1230#endif 1177#endif
1231 1178 rl->plugin->api->send (rl->plugin->api->cls,
1232 return rl->plugin->api->send (rl->plugin->api->cls, 1179 &mq->neighbor_id,
1233 mq->neighbor_id, 1180 mq->message_buf,
1234 mq->message_buf, 1181 mq->message_buf_size,
1235 mq->message_buf_size, 1182 mq->priority,
1236 mq->priority, 1183 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1237 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 1184 mq->specific_address->addr,
1238 mq->specific_peer->addr, 1185 mq->specific_address->addrlen,
1239 mq->specific_peer->addrlen, 1186 GNUNET_YES /* FIXME: sometimes, we want to be more tolerant here! */,
1240 GNUNET_YES, 1187 &transmit_send_continuation, mq);
1241 &transmit_send_continuation, mq);
1242
1243} 1188}
1244 1189
1245 1190
@@ -1247,16 +1192,16 @@ try_transmission_to_peer (struct NeighborList *neighbor)
1247 * Send the specified message to the specified peer. 1192 * Send the specified message to the specified peer.
1248 * 1193 *
1249 * @param client source of the transmission request (can be NULL) 1194 * @param client source of the transmission request (can be NULL)
1250 * @param peer_address PeerAddressList where we should send this message 1195 * @param peer_address ForeignAddressList where we should send this message
1251 * @param priority how important is the message 1196 * @param priority how important is the message
1252 * @param message_buf message(s) to send GNUNET_MessageHeader(s) 1197 * @param message_buf message(s) to send GNUNET_MessageHeader(s)
1253 * @param message_buf_size total size of all messages in message_buf 1198 * @param message_buf_size total size of all messages in message_buf
1254 * @param is_internal is this an internal message 1199 * @param is_internal is this an internal message
1255 * @param neighbor handle to the neighbor for transmission 1200 * @param neighbor handle to the neighbor for transmission
1256 */ 1201 */
1257static ssize_t 1202static void
1258transmit_to_peer (struct TransportClient *client, 1203transmit_to_peer (struct TransportClient *client,
1259 struct PeerAddressList *peer_address, 1204 struct ForeignAddressList *peer_address,
1260 unsigned int priority, 1205 unsigned int priority,
1261 const char *message_buf, 1206 const char *message_buf,
1262 size_t message_buf_size, 1207 size_t message_buf_size,
@@ -1264,7 +1209,6 @@ transmit_to_peer (struct TransportClient *client,
1264{ 1209{
1265 struct MessageQueue *mq; 1210 struct MessageQueue *mq;
1266 struct MessageQueue *mqe; 1211 struct MessageQueue *mqe;
1267 char *m;
1268 1212
1269 if (client != NULL) 1213 if (client != NULL)
1270 { 1214 {
@@ -1277,40 +1221,46 @@ transmit_to_peer (struct TransportClient *client,
1277 /* client transmitted to same peer twice 1221 /* client transmitted to same peer twice
1278 before getting SendOk! */ 1222 before getting SendOk! */
1279 GNUNET_break (0); 1223 GNUNET_break (0);
1280 return 0; 1224 return;
1281 } 1225 }
1282 mq = mq->next; 1226 mq = mq->next;
1283 } 1227 }
1284 } 1228 }
1285 mq = GNUNET_malloc (sizeof (struct MessageQueue)); 1229 mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
1286 mq->specific_peer = peer_address; 1230 mq->specific_address = peer_address;
1287 mq->client = client; 1231 mq->client = client;
1288 m = GNUNET_malloc (message_buf_size); 1232 memcpy (&mq[1], message_buf, message_buf_size);
1289 memcpy (m, message_buf, message_buf_size); 1233 mq->message_buf = (const char*) &mq[1];
1290 mq->message_buf = m;
1291 mq->message_buf_size = message_buf_size; 1234 mq->message_buf_size = message_buf_size;
1292 mq->neighbor_id = GNUNET_malloc(sizeof (struct GNUNET_PeerIdentity)); 1235 memcpy(&mq->neighbor_id, &neighbor->id, sizeof(struct GNUNET_PeerIdentity));
1293
1294 memcpy(mq->neighbor_id, &neighbor->id, sizeof(struct GNUNET_PeerIdentity));
1295 mq->internal_msg = is_internal; 1236 mq->internal_msg = is_internal;
1296 mq->priority = priority; 1237 mq->priority = priority;
1297 1238
1298 /* find tail */ 1239 if (is_internal)
1299 mqe = neighbor->messages;
1300 if (mqe != NULL)
1301 while (mqe->next != NULL)
1302 mqe = mqe->next;
1303 if (mqe == NULL)
1304 { 1240 {
1305 /* new head */ 1241 /* append at head */
1242 mq->next = neighbor->messages;
1306 neighbor->messages = mq; 1243 neighbor->messages = mq;
1307 } 1244 }
1308 else 1245 else
1309 { 1246 {
1310 /* append */ 1247 /* find tail */
1311 mqe->next = mq; 1248 mqe = neighbor->messages;
1249 if (mqe != NULL)
1250 while (mqe->next != NULL)
1251 mqe = mqe->next;
1252 if (mqe == NULL)
1253 {
1254 /* new head */
1255 neighbor->messages = mq;
1256 }
1257 else
1258 {
1259 /* append */
1260 mqe->next = mq;
1261 }
1312 } 1262 }
1313 return try_transmission_to_peer (neighbor); 1263 try_transmission_to_peer (neighbor);
1314} 1264}
1315 1265
1316 1266
@@ -1320,7 +1270,7 @@ transmit_to_peer (struct TransportClient *client,
1320struct GeneratorContext 1270struct GeneratorContext
1321{ 1271{
1322 struct TransportPlugin *plug_pos; 1272 struct TransportPlugin *plug_pos;
1323 struct AddressList *addr_pos; 1273 struct OwnAddressList *addr_pos;
1324 struct GNUNET_TIME_Absolute expiration; 1274 struct GNUNET_TIME_Absolute expiration;
1325}; 1275};
1326 1276
@@ -1393,10 +1343,11 @@ refresh_hello ()
1393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 1343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
1394 "Transmitting updated `%s' to neighbor `%4s'\n", 1344 "Transmitting updated `%s' to neighbor `%4s'\n",
1395 "HELLO", GNUNET_i2s (&npos->id)); 1345 "HELLO", GNUNET_i2s (&npos->id));
1396#endif // FIXME: just testing 1346#endif
1397 //transmit_to_peer (NULL, NULL, 0, 1347 transmit_to_peer (NULL, NULL, 0,
1398 // (const char *) our_hello, GNUNET_HELLO_size(our_hello), 1348 (const char *) our_hello,
1399 // GNUNET_YES, npos); 1349 GNUNET_HELLO_size(our_hello),
1350 GNUNET_NO, npos);
1400 npos = npos->next; 1351 npos = npos->next;
1401 } 1352 }
1402} 1353}
@@ -1428,9 +1379,9 @@ update_addresses (struct TransportPlugin *plugin, int fresh)
1428 struct GNUNET_TIME_Relative min_remaining; 1379 struct GNUNET_TIME_Relative min_remaining;
1429 struct GNUNET_TIME_Relative remaining; 1380 struct GNUNET_TIME_Relative remaining;
1430 struct GNUNET_TIME_Absolute now; 1381 struct GNUNET_TIME_Absolute now;
1431 struct AddressList *pos; 1382 struct OwnAddressList *pos;
1432 struct AddressList *prev; 1383 struct OwnAddressList *prev;
1433 struct AddressList *next; 1384 struct OwnAddressList *next;
1434 int expired; 1385 int expired;
1435 1386
1436 if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK) 1387 if (plugin->address_update_task != GNUNET_SCHEDULER_NO_TASK)
@@ -1509,7 +1460,7 @@ plugin_env_notify_address (void *cls,
1509 struct GNUNET_TIME_Relative expires) 1460 struct GNUNET_TIME_Relative expires)
1510{ 1461{
1511 struct TransportPlugin *p = cls; 1462 struct TransportPlugin *p = cls;
1512 struct AddressList *al; 1463 struct OwnAddressList *al;
1513 struct GNUNET_TIME_Absolute abex; 1464 struct GNUNET_TIME_Absolute abex;
1514 1465
1515 abex = GNUNET_TIME_relative_to_absolute (expires); 1466 abex = GNUNET_TIME_relative_to_absolute (expires);
@@ -1527,7 +1478,7 @@ plugin_env_notify_address (void *cls,
1527 al = al->next; 1478 al = al->next;
1528 } 1479 }
1529 1480
1530 al = GNUNET_malloc (sizeof (struct AddressList) + addrlen); 1481 al = GNUNET_malloc (sizeof (struct OwnAddressList) + addrlen);
1531 al->addr = &al[1]; 1482 al->addr = &al[1];
1532 al->next = p->addresses; 1483 al->next = p->addresses;
1533 p->addresses = al; 1484 p->addresses = al;
@@ -1585,109 +1536,209 @@ notify_clients_disconnect (const struct GNUNET_PeerIdentity *peer)
1585 1536
1586 1537
1587/** 1538/**
1588 * Copy any validated addresses to buf. 1539 * Find a ForeignAddressList entry for the given neighbour
1540 * that matches the given address and transport.
1589 * 1541 *
1590 * @return 0 once all addresses have been 1542 * @param neighbor which peer we care about
1591 * returned 1543 * @param tname name of the transport plugin
1544 * @param addr binary address
1545 * @param addrlen length of addr
1546 * @return NULL if no such entry exists
1547 */
1548static struct ForeignAddressList *
1549find_peer_address(struct NeighborList *neighbor,
1550 const char *tname,
1551 const char *addr,
1552 size_t addrlen)
1553{
1554 struct ReadyList *head;
1555 struct ForeignAddressList *address_head;
1556
1557 head = neighbor->plugins;
1558 while (head != NULL)
1559 {
1560 if (0 == strcmp (tname, head->plugin->short_name))
1561 break;
1562 head = head->next;
1563 }
1564 if (head == NULL)
1565 return NULL;
1566
1567 address_head = head->addresses;
1568 while ( (address_head != NULL) &&
1569 ( (address_head->addrlen != addrlen) ||
1570 (memcmp(address_head->addr, addr, addrlen) != 0) ) )
1571 address_head = address_head->next;
1572 return address_head;
1573}
1574
1575
1576/**
1577 * Get the peer address struct for the given neighbor and
1578 * address. If it doesn't yet exist, create it.
1579 *
1580 * @param neighbor which peer we care about
1581 * @param tname name of the transport plugin
1582 * @param addr binary address
1583 * @param addrlen length of addr
1584 * @return NULL if we do not have a transport plugin for 'tname'
1585 */
1586static struct ForeignAddressList *
1587add_peer_address(struct NeighborList *neighbor,
1588 const char *tname,
1589 const char *addr,
1590 size_t addrlen)
1591{
1592 struct ReadyList *head;
1593 struct ForeignAddressList *ret;
1594
1595 ret = find_peer_address (neighbor, tname, addr, addrlen);
1596 if (ret != NULL)
1597 return ret;
1598 head = neighbor->plugins;
1599 while (head != NULL)
1600 {
1601 if (0 == strcmp (tname, head->plugin->short_name))
1602 break;
1603 head = head->next;
1604 }
1605 if (head == NULL)
1606 return NULL;
1607 ret = GNUNET_malloc(sizeof(struct ForeignAddressList) + addrlen);
1608 ret->addr = (const char*) &ret[1];
1609 memcpy (&ret[1], addr, addrlen);
1610 ret->addrlen = addrlen;
1611 ret->expires = GNUNET_TIME_relative_to_absolute
1612 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1613 ret->latency = GNUNET_TIME_relative_get_forever();
1614 ret->transmit_ready = GNUNET_YES;
1615 ret->timeout = GNUNET_TIME_relative_to_absolute
1616 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1617 ret->ready_list = head;
1618 ret->next = head->addresses;
1619 head->addresses = ret;
1620 return ret;
1621}
1622
1623
1624/**
1625 * Closure for 'add_validated_address'.
1626 */
1627struct AddValidatedAddressContext
1628{
1629 /**
1630 * Entry that has been validated.
1631 */
1632 const struct ValidationEntry *ve;
1633
1634 /**
1635 * Flag set after we have added the address so
1636 * that we terminate the iteration next time.
1637 */
1638 int done;
1639};
1640
1641
1642/**
1643 * Callback function used to fill a buffer of max bytes with a list of
1644 * addresses in the format used by HELLOs. Should use
1645 * "GNUNET_HELLO_add_address" as a helper function.
1646 *
1647 * @param cls the 'struct AddValidatedAddressContext' with the validated address
1648 * @param max maximum number of bytes that can be written to buf
1649 * @param buf where to write the address information
1650 * @return number of bytes written, 0 to signal the
1651 * end of the iteration.
1592 */ 1652 */
1593static size_t 1653static size_t
1594list_validated_addresses (void *cls, size_t max, void *buf) 1654add_validated_address (void *cls,
1655 size_t max, void *buf)
1595{ 1656{
1596 struct ValidationAddress **va = cls; 1657 struct AddValidatedAddressContext *avac = cls;
1597 size_t ret; 1658 const struct ValidationEntry *ve = avac->ve;
1598 1659
1599 while ((NULL != *va) && ((*va)->ok != GNUNET_YES)) 1660 if (GNUNET_YES == avac->done)
1600 *va = (*va)->next;
1601 if (NULL == *va)
1602 return 0; 1661 return 0;
1603 ret = GNUNET_HELLO_add_address ((*va)->transport_name, 1662 avac->done = GNUNET_YES;
1604 (*va)->expiration, 1663 return GNUNET_HELLO_add_address (ve->transport_name,
1605 (*va)->peer_address->addr, (*va)->peer_address->addrlen, buf, max); 1664 GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION),
1606 *va = (*va)->next; 1665 ve->addr,
1607 return ret; 1666 ve->addrlen,
1667 buf,
1668 max);
1608} 1669}
1609 1670
1610 1671
1611/** 1672/**
1612 * HELLO validation cleanup task. 1673 * Iterator over hash map entries. Checks if the given
1674 * validation entry is for the same challenge as what
1675 * is given in the PONG.
1676 *
1677 * @param cls the 'struct TransportPongMessage*'
1678 * @param key peer identity
1679 * @param value value in the hash map ('struct ValidationEntry')
1680 * @return GNUNET_YES if we should continue to
1681 * iterate (mismatch), GNUNET_NO if not (entry matched)
1613 */ 1682 */
1614static void 1683static int
1615cleanup_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 1684check_pending_validation (void *cls,
1685 const GNUNET_HashCode * key,
1686 void *value)
1616{ 1687{
1617 struct ValidationAddress *va; 1688 const struct TransportPongMessage *pong = cls;
1618 struct ValidationList *pos; 1689 struct ValidationEntry *ve = value;
1619 struct ValidationList *prev; 1690 struct AddValidatedAddressContext avac;
1620 struct GNUNET_TIME_Absolute now; 1691 unsigned int challenge = ntohl(pong->challenge);
1621 struct GNUNET_TIME_Absolute first;
1622 struct GNUNET_HELLO_Message *hello; 1692 struct GNUNET_HELLO_Message *hello;
1623 struct GNUNET_PeerIdentity pid; 1693 struct GNUNET_PeerIdentity target;
1624 struct NeighborList *n; 1694 struct NeighborList *n;
1695 struct ForeignAddressList *fal;
1625 1696
1626 now = GNUNET_TIME_absolute_get (); 1697 if (ve->challenge != challenge)
1627 prev = NULL; 1698 return GNUNET_YES;
1628 pos = pending_validations; 1699
1629 while (pos != NULL)
1630 {
1631 if (pos->timeout.value < now.value)
1632 {
1633 if (prev == NULL)
1634 pending_validations = pos->next;
1635 else
1636 prev->next = pos->next;
1637 va = pos->addresses;
1638 hello = GNUNET_HELLO_create (&pos->publicKey,
1639 &list_validated_addresses, &va);
1640 GNUNET_CRYPTO_hash (&pos->publicKey,
1641 sizeof (struct
1642 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1643 &pid.hashPubKey);
1644#if DEBUG_TRANSPORT 1700#if DEBUG_TRANSPORT
1645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1701 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1646 "Creating persistent `%s' message for peer `%4s' based on confirmed addresses.\n", 1702 "Confirmed validity of address, peer `%4s' has address `%s' (%s).\n",
1647 "HELLO", GNUNET_i2s (&pid)); 1703 GNUNET_h2s (key),
1704 GNUNET_a2s ((const struct sockaddr *) ve->addr,
1705 ve->addrlen),
1706 ve->transport_name);
1648#endif 1707#endif
1649 GNUNET_PEERINFO_add_peer (cfg, sched, &pid, hello); 1708 /* create the updated HELLO */
1650 n = find_neighbor (&pid); 1709 GNUNET_CRYPTO_hash (&ve->publicKey,
1651 if (NULL != n) 1710 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1652 { 1711 &target.hashPubKey);
1653 try_transmission_to_peer (n); 1712 avac.done = GNUNET_NO;
1654 } 1713 avac.ve = ve;
1655 GNUNET_free (hello); 1714 hello = GNUNET_HELLO_create (&ve->publicKey,
1656 while (NULL != (va = pos->addresses)) 1715 &add_validated_address,
1657 { 1716 &avac);
1658 pos->addresses = va->next; 1717 GNUNET_PEERINFO_add_peer (cfg, sched,
1659 GNUNET_free (va->transport_name); 1718 &target,
1660 GNUNET_free (va); 1719 hello);
1661 } 1720 GNUNET_free (hello);
1662 GNUNET_free (pos); 1721 n = find_neighbor (&target);
1663 if (prev == NULL) 1722 if (n != NULL)
1664 pos = pending_validations; 1723 {
1665 else 1724 fal = add_peer_address (n, ve->transport_name,
1666 pos = prev->next; 1725 ve->addr,
1667 continue; 1726 ve->addrlen);
1668 } 1727 fal->expires = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1669 prev = pos; 1728 fal->validated = GNUNET_YES;
1670 pos = pos->next; 1729 fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
1671 } 1730 }
1672 1731
1673 /* finally, reschedule cleanup if needed; list is 1732 /* clean up validation entry */
1674 ordered by timeout, so we need the last element... */ 1733 GNUNET_assert (GNUNET_YES ==
1675 if (NULL != pending_validations) 1734 GNUNET_CONTAINER_multihashmap_remove (validation_map,
1676 { 1735 key,
1677 first = pending_validations->timeout; 1736 ve));
1678 pos = pending_validations; 1737 GNUNET_SCHEDULER_cancel (sched,
1679 while (pos != NULL) 1738 ve->timeout_task);
1680 { 1739 GNUNET_free (ve->transport_name);
1681 first = GNUNET_TIME_absolute_min (first, pos->timeout); 1740 GNUNET_free (ve);
1682 pos = pos->next; 1741 return GNUNET_NO;
1683 }
1684 if (tc->reason != GNUNET_SCHEDULER_REASON_SHUTDOWN)
1685 {
1686 GNUNET_SCHEDULER_add_delayed (sched,
1687 GNUNET_TIME_absolute_get_remaining
1688 (first), &cleanup_validation, NULL);
1689 }
1690 }
1691} 1742}
1692 1743
1693 1744
@@ -1712,129 +1763,43 @@ handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
1712 const char *sender_address, 1763 const char *sender_address,
1713 size_t sender_address_len) 1764 size_t sender_address_len)
1714{ 1765{
1715 unsigned int not_done;
1716 int matched;
1717 struct ValidationList *pos;
1718 struct ValidationAddress *va;
1719 struct GNUNET_PeerIdentity id;
1720 const struct TransportPongMessage *pong = (const struct TransportPongMessage *)message;
1721 int count = 0;
1722 unsigned int challenge = ntohl(pong->challenge);
1723 pos = pending_validations;
1724
1725 while (pos != NULL)
1726 {
1727 GNUNET_CRYPTO_hash (&pos->publicKey,
1728 sizeof (struct
1729 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1730 &id.hashPubKey);
1731 if (0 == memcmp (peer, &id, sizeof (struct GNUNET_PeerIdentity)))
1732 break;
1733 pos = pos->next;
1734 count++;
1735 }
1736 if (pos == NULL)
1737 {
1738 /* TODO: call statistics (unmatched PONG) */
1739 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1740 _
1741 ("Received validation response but have no record of any validation request for `%4s' (out of %d). Ignoring.\n"),
1742 GNUNET_i2s (peer), count);
1743 return;
1744 }
1745 not_done = 0;
1746 matched = GNUNET_NO;
1747 va = pos->addresses;
1748 while (va != NULL)
1749 {
1750 if (va->challenge == challenge)
1751 {
1752#if DEBUG_TRANSPORT
1753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1754 "Confirmed validity of address, peer `%4s' has address `%s'.\n",
1755 GNUNET_i2s (peer),
1756 GNUNET_a2s ((const struct sockaddr *) va->peer_address->addr,
1757 va->peer_address->addrlen));
1758#endif
1759 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1760 _
1761 ("Another peer saw us using the address `%s' via `%s'. If this is not plausible, this address should be listed in the configuration as implausible to avoid MiM attacks.\n"),
1762 GNUNET_a2s ((const struct sockaddr *) &pong[1],
1763 ntohs(pong->addrlen)), va->transport_name);
1764 va->ok = GNUNET_YES;
1765 va->expiration =
1766 GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
1767 matched = GNUNET_YES;
1768 va->peer_address->connected = GNUNET_YES;
1769 va->peer_address->latency = GNUNET_TIME_absolute_get_difference(va->send_time, GNUNET_TIME_absolute_get());
1770#if DEBUG_TRANSPORT 1766#if DEBUG_TRANSPORT
1771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1772 "Confirmed validity of address, peer `%4s' has address `%s', latency of %llu\n", 1768 "Receiving `%s' message from `%4s'.\n", "PONG",
1773 GNUNET_i2s (peer), 1769 GNUNET_i2s (peer));
1774 GNUNET_a2s ((const struct sockaddr *) va->peer_address->addr,
1775 va->peer_address->addrlen), (unsigned long long)va->peer_address->latency.value);
1776#endif 1770#endif
1777 va->peer_address->transmit_ready = GNUNET_YES; 1771 if (GNUNET_SYSERR !=
1778 va->peer_address->expires = GNUNET_TIME_relative_to_absolute 1772 GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
1779 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1773 &peer->hashPubKey,
1780 } 1774 &check_pending_validation,
1781 if (va->ok != GNUNET_YES) 1775 (void*) message))
1782 not_done++; 1776 {
1783 va = va->next; 1777 /* This is *expected* to happen a lot since we send
1784 } 1778 PONGs to *all* known addresses of the sender of
1785 if (GNUNET_NO == matched) 1779 the PING, so most likely we get multiple PONGs
1786 { 1780 per PING, and all but the first PONG will end up
1787 /* TODO: call statistics (unmatched PONG) */ 1781 here. So really we should not print anything here
1788 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1782 unless we want to be very, very verbose... */
1789 _ 1783#if DEBUG_TRANSPORT > 1
1790 ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
1791 "PONG", "PING");
1792 }
1793 if (0 == not_done)
1794 {
1795#if DEBUG_TRANSPORT
1796 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1784 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1797 "All addresses validated, will now construct `%s' for `%4s'.\n", 1785 "Received `%s' message from `%4s' but have no record of a matching `%s' message. Ignoring.\n",
1798 "HELLO", GNUNET_i2s (peer)); 1786 "PONG",
1787 GNUNET_i2s (peer),
1788 "PING");
1799#endif 1789#endif
1800 pos->timeout.value = 0; 1790 return;
1801 GNUNET_SCHEDULER_add_with_priority (sched,
1802 GNUNET_SCHEDULER_PRIORITY_IDLE,
1803 &cleanup_validation, NULL);
1804 } 1791 }
1805 1792#if 0
1793 /* FIXME: add given address to potential pool of our addresses
1794 (for voting) */
1795 GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
1796 _("Another peer saw us using the address `%s' via `%s'.\n"),
1797 GNUNET_a2s ((const struct sockaddr *) &pong[1],
1798 ntohs(pong->addrlen)),
1799 va->transport_name);
1800#endif
1806} 1801}
1807 1802
1808/**
1809 * Add an entry for each of our transport plugins
1810 * (that are able to send) to the list of plugins
1811 * for this neighbor.
1812 *
1813 * @param neighbor to initialize
1814 */
1815static void
1816add_plugins (struct NeighborList *neighbor)
1817{
1818 struct TransportPlugin *tp;
1819 struct ReadyList *rl;
1820
1821 neighbor->retry_plugins_time
1822 = GNUNET_TIME_relative_to_absolute (PLUGIN_RETRY_FREQUENCY);
1823 tp = plugins;
1824 while (tp != NULL)
1825 {
1826 if (tp->api->send != NULL)
1827 {
1828 rl = GNUNET_malloc (sizeof (struct ReadyList));
1829 rl->next = neighbor->plugins;
1830 neighbor->plugins = rl;
1831 rl->plugin = tp;
1832 rl->neighbor = neighbor;
1833 rl->addresses = NULL;
1834 }
1835 tp = tp->next;
1836 }
1837}
1838 1803
1839static void 1804static void
1840neighbor_timeout_task (void *cls, 1805neighbor_timeout_task (void *cls,
@@ -1850,6 +1815,7 @@ neighbor_timeout_task (void *cls,
1850 disconnect_neighbor (n, GNUNET_NO); 1815 disconnect_neighbor (n, GNUNET_NO);
1851} 1816}
1852 1817
1818
1853/** 1819/**
1854 * Create a fresh entry in our neighbor list for the given peer. 1820 * Create a fresh entry in our neighbor list for the given peer.
1855 * Will try to transmit our current HELLO to the new neighbor. Also 1821 * Will try to transmit our current HELLO to the new neighbor. Also
@@ -1862,6 +1828,8 @@ static struct NeighborList *
1862setup_new_neighbor (const struct GNUNET_PeerIdentity *peer) 1828setup_new_neighbor (const struct GNUNET_PeerIdentity *peer)
1863{ 1829{
1864 struct NeighborList *n; 1830 struct NeighborList *n;
1831 struct TransportPlugin *tp;
1832 struct ReadyList *rl;
1865 1833
1866 GNUNET_assert (our_hello != NULL); 1834 GNUNET_assert (our_hello != NULL);
1867 n = GNUNET_malloc (sizeof (struct NeighborList)); 1835 n = GNUNET_malloc (sizeof (struct NeighborList));
@@ -1873,77 +1841,124 @@ setup_new_neighbor (const struct GNUNET_PeerIdentity *peer)
1873 GNUNET_TIME_relative_to_absolute 1841 GNUNET_TIME_relative_to_absolute
1874 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 1842 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1875 n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000); 1843 n->quota_in = (GNUNET_CONSTANTS_DEFAULT_BPM_IN_OUT + 59999) / (60 * 1000);
1876 add_plugins (n); 1844 tp = plugins;
1845 while (tp != NULL)
1846 {
1847 if (tp->api->send != NULL)
1848 {
1849 rl = GNUNET_malloc (sizeof (struct ReadyList));
1850 rl->next = n->plugins;
1851 n->plugins = rl;
1852 rl->plugin = tp;
1853 rl->addresses = NULL;
1854 }
1855 tp = tp->next;
1856 }
1877 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched, 1857 n->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
1878 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 1858 GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
1879 &neighbor_timeout_task, n); 1859 &neighbor_timeout_task, n);
1880 transmit_to_peer (NULL, NULL, 0, 1860 transmit_to_peer (NULL, NULL, 0,
1881 (const char *) our_hello, GNUNET_HELLO_size(our_hello), 1861 (const char *) our_hello, GNUNET_HELLO_size(our_hello),
1882 GNUNET_YES, n); 1862 GNUNET_NO, n);
1883 notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL); 1863 notify_clients_connect (peer, GNUNET_TIME_UNIT_FOREVER_REL);
1884 return n; 1864 return n;
1885} 1865}
1886 1866
1887static struct PeerAddressList * 1867
1888add_peer_address(struct NeighborList *neighbor, const char *addr, size_t addrlen) 1868/**
1869 * Closure for 'check_address_exists'.
1870 */
1871struct CheckAddressExistsClosure
1889{ 1872{
1890 /* FIXME: should return a list of PeerAddressLists, support for multiple transports! */ 1873 /**
1891 struct ReadyList *head = neighbor->plugins; 1874 * Address to check for.
1892 struct PeerAddressList * new_address; 1875 */
1876 const void *addr;
1893 1877
1894 GNUNET_assert(addr != NULL); 1878 /**
1879 * Name of the transport.
1880 */
1881 const char *tname;
1895 1882
1896 new_address = NULL; 1883 /**
1897 while (head != NULL) 1884 * Length of addr.
1898 { 1885 */
1899 new_address = GNUNET_malloc(sizeof(struct PeerAddressList)); 1886 size_t addrlen;
1900 new_address->addr = GNUNET_malloc(addrlen); 1887
1901 memcpy(new_address->addr, addr, addrlen); 1888 /**
1902 new_address->addrlen = addrlen; 1889 * Set to GNUNET_YES if the address exists.
1903 new_address->connect_attempts = 0; 1890 */
1904 new_address->connected = GNUNET_YES; /* Set connected to GNUNET_YES, assuming that we're good */ 1891 int exists;
1905 new_address->expires = GNUNET_TIME_relative_to_absolute 1892};
1906 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1907 new_address->latency = GNUNET_TIME_relative_get_forever();
1908 new_address->neighbor = neighbor;
1909 new_address->plugin = head->plugin;
1910 new_address->transmit_ready = GNUNET_YES;
1911 new_address->timeout = GNUNET_TIME_relative_to_absolute
1912 (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); /* FIXME: Do we need this? */
1913 new_address->ready_list = head;
1914 new_address->next = head->addresses;
1915 head->addresses = new_address;
1916 head = head->next;
1917 }
1918 1893
1919 return new_address; 1894
1895/**
1896 * Iterator over hash map entries. Checks if the given
1897 * validation entry is for the same address as what is given
1898 * in the closure.
1899 *
1900 * @param cls the 'struct CheckAddressExistsClosure*'
1901 * @param key current key code (ignored)
1902 * @param value value in the hash map ('struct ValidationEntry')
1903 * @return GNUNET_YES if we should continue to
1904 * iterate (mismatch), GNUNET_NO if not (entry matched)
1905 */
1906static int
1907check_address_exists (void *cls,
1908 const GNUNET_HashCode * key,
1909 void *value)
1910{
1911 struct CheckAddressExistsClosure *caec = cls;
1912 struct ValidationEntry *ve = value;
1913 if ( (0 == strcmp (caec->tname,
1914 ve->transport_name)) &&
1915 (caec->addrlen == ve->addrlen) &&
1916 (0 == memcmp (caec->addr,
1917 ve->addr,
1918 caec->addrlen)) )
1919 {
1920 caec->exists = GNUNET_YES;
1921 return GNUNET_NO;
1922 }
1923 return GNUNET_YES;
1920} 1924}
1921 1925
1922static struct PeerAddressList * 1926
1923find_peer_address(struct NeighborList *neighbor, const char *addr, size_t addrlen) 1927/**
1928 * HELLO validation cleanup task (validation failed).
1929 *
1930 * @param cls the 'struct ValidationEntry' that failed
1931 * @param tc scheduler context (unused)
1932 */
1933static void
1934timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1924{ 1935{
1925 struct ReadyList *head = neighbor->plugins; 1936 struct ValidationEntry *va = cls;
1926 struct PeerAddressList *address_head; 1937 struct GNUNET_PeerIdentity pid;
1927 while (head != NULL)
1928 {
1929 address_head = head->addresses;
1930 while ((address_head != NULL) &&
1931 (address_head->addrlen != addrlen) &&
1932 (memcmp(address_head->addr, addr, addrlen) != 0))
1933 {
1934 address_head = address_head->next;
1935 }
1936 if (address_head != NULL)
1937 return address_head;
1938 1938
1939 head = head->next; 1939 GNUNET_CRYPTO_hash (&va->publicKey,
1940 } 1940 sizeof (struct
1941 return NULL; 1941 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1942 &pid.hashPubKey);
1943 GNUNET_CONTAINER_multihashmap_remove (validation_map,
1944 &pid.hashPubKey,
1945 va);
1946 GNUNET_free (va->transport_name);
1947 GNUNET_free (va);
1942} 1948}
1943 1949
1950
1944/** 1951/**
1945 * Append the given address to the list of entries 1952 * Check if the given address is already being validated; if not,
1946 * that need to be validated. 1953 * append the given address to the list of entries that are being be
1954 * validated and initiate validation.
1955 *
1956 * @param cls closure ('struct CheckHelloValidatedContext *')
1957 * @param tname name of the transport
1958 * @param expiration expiration time
1959 * @param addr the address
1960 * @param addrlen length of the address
1961 * @return GNUNET_OK (always)
1947 */ 1962 */
1948static int 1963static int
1949run_validation (void *cls, 1964run_validation (void *cls,
@@ -1951,14 +1966,15 @@ run_validation (void *cls,
1951 struct GNUNET_TIME_Absolute expiration, 1966 struct GNUNET_TIME_Absolute expiration,
1952 const void *addr, size_t addrlen) 1967 const void *addr, size_t addrlen)
1953{ 1968{
1954 struct ValidationList *e = cls; 1969 struct CheckHelloValidatedContext *chvc = cls;
1955 struct TransportPlugin *tp;
1956 struct ValidationAddress *va;
1957 struct GNUNET_PeerIdentity id; 1970 struct GNUNET_PeerIdentity id;
1971 struct TransportPlugin *tp;
1972 struct ValidationEntry *va;
1958 struct NeighborList *neighbor; 1973 struct NeighborList *neighbor;
1959 struct PeerAddressList *peer_address; 1974 struct ForeignAddressList *peer_address;
1960 ssize_t sent; 1975 struct TransportPingMessage ping;
1961 struct TransportPingMessage *ping; 1976 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
1977 struct CheckAddressExistsClosure caec;
1962 char * message_buf; 1978 char * message_buf;
1963 uint16_t hello_size; 1979 uint16_t hello_size;
1964 size_t tsize; 1980 size_t tsize;
@@ -1973,164 +1989,194 @@ run_validation (void *cls,
1973 tname); 1989 tname);
1974 return GNUNET_OK; 1990 return GNUNET_OK;
1975 } 1991 }
1976 GNUNET_CRYPTO_hash (&e->publicKey, 1992 GNUNET_HELLO_get_key (chvc->hello, &pk);
1993 GNUNET_CRYPTO_hash (&pk,
1977 sizeof (struct 1994 sizeof (struct
1978 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), 1995 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1979 &id.hashPubKey); 1996 &id.hashPubKey);
1980#if DEBUG_TRANSPORT 1997 caec.addr = addr;
1981 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1998 caec.addrlen = addrlen;
1982 "Scheduling validation of address `%s' via `%s' for `%4s'\n", 1999 caec.tname = tname;
1983 GNUNET_a2s (addr, addrlen), tname, GNUNET_i2s (&id)); 2000 caec.exists = GNUNET_NO;
2001 GNUNET_CONTAINER_multihashmap_iterate (validation_map,
2002 &check_address_exists,
2003 &caec);
2004 if (caec.exists == GNUNET_YES)
2005 {
2006 /* During validation attempts we will likely trigger the other
2007 peer trying to validate our address which in turn will cause
2008 it to send us its HELLO, so we expect to hit this case rather
2009 frequently. Only print something if we are very verbose. */
2010#if DEBUG_TRANSPORT > 1
2011 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2012 "Validation of address `%s' via `%s' for peer `%4s' already in progress.\n",
2013 GNUNET_a2s (addr, addrlen),
2014 tname,
2015 GNUNET_i2s (&id));
1984#endif 2016#endif
1985 va = GNUNET_malloc (sizeof (struct ValidationAddress)); 2017 return GNUNET_OK;
1986 va->next = e->addresses; 2018 }
1987 e->addresses = va; 2019 va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
1988 va->transport_name = GNUNET_strdup (tname); 2020 va->transport_name = GNUNET_strdup (tname);
1989 va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 2021 va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1990 (unsigned int) -1); 2022 (unsigned int) -1);
1991 va->send_time = GNUNET_TIME_absolute_get(); 2023 va->send_time = GNUNET_TIME_absolute_get();
1992 2024 va->addr = (const void*) &va[1];
1993 neighbor = find_neighbor(&id); 2025 memcpy (&va[1], addr, addrlen);
1994 2026 va->addrlen = addrlen;
2027 GNUNET_HELLO_get_key (chvc->hello,
2028 &va->publicKey);
2029 va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
2030 HELLO_VERIFICATION_TIMEOUT,
2031 &timeout_hello_validation,
2032 va);
2033 GNUNET_CONTAINER_multihashmap_put (validation_map,
2034 &id.hashPubKey,
2035 va,
2036 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2037 neighbor = find_neighbor(&id);
1995 if (neighbor == NULL) 2038 if (neighbor == NULL)
1996 neighbor = setup_new_neighbor(&id); 2039 neighbor = setup_new_neighbor(&id);
1997 2040 peer_address = add_peer_address(neighbor, tname, addr, addrlen);
1998 peer_address = find_peer_address(neighbor, addr, addrlen);
1999 if (peer_address == NULL)
2000 {
2001 peer_address = add_peer_address(neighbor, addr, addrlen);
2002 }
2003
2004 GNUNET_assert(peer_address != NULL); 2041 GNUNET_assert(peer_address != NULL);
2005
2006 va->peer_address = peer_address; /* Back pointer FIXME: remove this nonsense! */
2007 peer_address->validation = va;
2008
2009 hello_size = GNUNET_HELLO_size(our_hello); 2042 hello_size = GNUNET_HELLO_size(our_hello);
2010 tsize = sizeof(struct TransportPingMessage) + hello_size; 2043 tsize = sizeof(struct TransportPingMessage) + hello_size;
2011
2012 message_buf = GNUNET_malloc(tsize); 2044 message_buf = GNUNET_malloc(tsize);
2013 2045 ping.challenge = htonl(va->challenge);
2014 ping = GNUNET_malloc(sizeof(struct TransportPingMessage)); 2046 ping.header.size = htons(sizeof(struct TransportPingMessage));
2015 ping->challenge = htonl(va->challenge); 2047 ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2016 ping->header.size = htons(sizeof(struct TransportPingMessage)); 2048 memcpy(&ping.target, &id, sizeof(struct GNUNET_PeerIdentity));
2017 ping->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
2018 memcpy(&ping->target, &id, sizeof(struct GNUNET_PeerIdentity));
2019
2020#if DEBUG_TRANSPORT
2021 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
2022 "`%s' message size is %u, ping size is %u, total size is %u\n",
2023 "HELLO",
2024 hello_size,
2025 sizeof(struct TransportPingMessage),
2026 tsize);
2027#endif
2028 memcpy(message_buf, our_hello, hello_size); 2049 memcpy(message_buf, our_hello, hello_size);
2029 memcpy(&message_buf[hello_size], 2050 memcpy(&message_buf[hello_size],
2030 ping, 2051 &ping,
2031 sizeof(struct TransportPingMessage)); 2052 sizeof(struct TransportPingMessage));
2032
2033#if DEBUG_TRANSPORT 2053#if DEBUG_TRANSPORT
2034 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2035 "Sending `%s' message of size %u to address `%s' via `%s' for `%4s'\n", 2055 "Performing validation of address `%s' via `%s' for peer `%4s' sending `%s' (%u bytes) and `%s' (%u bytes)\n",
2036 "PING", 2056 GNUNET_a2s (addr, addrlen),
2037 tsize, GNUNET_a2s (addr, addrlen), 2057 tname,
2038 tname, GNUNET_i2s (&id)); 2058 GNUNET_i2s (&id),
2059 "HELLO", hello_size,
2060 "PING", sizeof (struct TransportPingMessage));
2039#endif 2061#endif
2040 sent = transmit_to_peer(NULL, peer_address, 2062 transmit_to_peer(NULL, peer_address,
2041 GNUNET_SCHEDULER_PRIORITY_DEFAULT, 2063 GNUNET_SCHEDULER_PRIORITY_DEFAULT,
2042 message_buf, tsize, GNUNET_NO, neighbor); 2064 message_buf, tsize,
2065 GNUNET_YES, neighbor);
2066 GNUNET_free(message_buf);
2067 return GNUNET_OK;
2068}
2069
2043 2070
2071/**
2072 * Add the given address to the list of foreign addresses
2073 * available for the given peer (check for duplicates).
2074 *
2075 * @param cls the respective 'struct NeighborList' to update
2076 * @param tname name of the transport
2077 * @param expiration expiration time
2078 * @param addr the address
2079 * @param addrlen length of the address
2080 * @return GNUNET_OK (always)
2081 */
2082static int
2083add_to_foreign_address_list (void *cls,
2084 const char *tname,
2085 struct GNUNET_TIME_Absolute expiration,
2086 const void *addr, size_t addrlen)
2087{
2088 struct NeighborList *n = cls;
2089 struct ForeignAddressList *fal;
2090
2091 fal = find_peer_address (n, tname, addr, addrlen);
2092 if (fal == NULL)
2093 {
2044#if DEBUG_TRANSPORT 2094#if DEBUG_TRANSPORT
2045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2095 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2046 "Transport returned %d from send!\n", sent); 2096 "Adding address `%s' (%s) for peer `%4s' due to peerinfo data.\n",
2097 GNUNET_a2s (addr, addrlen),
2098 tname,
2099 GNUNET_i2s (&n->id));
2047#endif 2100#endif
2048 2101 fal = add_peer_address (n, tname, addr, addrlen);
2049 GNUNET_free(ping); 2102 }
2050 GNUNET_free(message_buf); 2103 fal->expires = GNUNET_TIME_absolute_max (expiration,
2104 fal->expires);
2105 fal->validated = GNUNET_YES;
2051 return GNUNET_OK; 2106 return GNUNET_OK;
2052} 2107}
2053 2108
2054 2109
2055/** 2110/**
2056 * Check if addresses in validated hello "h" overlap with 2111 * Check if addresses in validated hello "h" overlap with
2057 * those in "chvc->hello" and update "chvc->hello" accordingly, 2112 * those in "chvc->hello" and validate the rest.
2058 * removing those addresses that have already been validated. 2113 *
2114 * @param cls closure
2115 * @param peer id of the peer, NULL for last call
2116 * @param hello hello message for the peer (can be NULL)
2117 * @param trust amount of trust we have in the peer (not used)
2059 */ 2118 */
2060static void 2119static void
2061check_hello_validated (void *cls, 2120check_hello_validated (void *cls,
2062 const struct GNUNET_PeerIdentity *peer, 2121 const struct GNUNET_PeerIdentity *peer,
2063 const struct GNUNET_HELLO_Message *h, uint32_t trust) 2122 const struct GNUNET_HELLO_Message *h,
2123 uint32_t trust)
2064{ 2124{
2065 struct CheckHelloValidatedContext *chvc = cls; 2125 struct CheckHelloValidatedContext *chvc = cls;
2066 struct ValidationAddress *va; 2126 struct GNUNET_HELLO_Message *plain_hello;
2067 struct TransportPlugin *tp; 2127 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
2068 int first_call; 2128 struct GNUNET_PeerIdentity target;
2069 int count; 2129 struct NeighborList *n;
2070 struct GNUNET_PeerIdentity apeer;
2071 2130
2072 first_call = GNUNET_NO; 2131 if (peer == NULL)
2073 if (chvc->e == NULL)
2074 { 2132 {
2075 chvc->piter = NULL; 2133 chvc->piter = NULL;
2076 first_call = GNUNET_YES; 2134 GNUNET_CONTAINER_DLL_remove (chvc_head,
2077 chvc->e = GNUNET_malloc (sizeof (struct ValidationList)); 2135 chvc_tail,
2078 GNUNET_assert (GNUNET_OK == 2136 chvc);
2079 GNUNET_HELLO_get_key (h != NULL ? h : chvc->hello, 2137 if (GNUNET_NO == chvc->hello_known)
2080 &chvc->e->publicKey)); 2138 {
2081 chvc->e->timeout = 2139 /* notify PEERINFO about the peer now, so that we at least
2082 GNUNET_TIME_relative_to_absolute (HELLO_VERIFICATION_TIMEOUT); 2140 have the public key if some other component needs it */
2083 chvc->e->next = pending_validations; 2141 GNUNET_HELLO_get_key (chvc->hello, &pk);
2084 pending_validations = chvc->e; 2142 GNUNET_CRYPTO_hash (&pk,
2085 } 2143 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
2086 2144 &target.hashPubKey);
2087 if (h != NULL) 2145 plain_hello = GNUNET_HELLO_create (&pk,
2088 { 2146 NULL,
2089 GNUNET_HELLO_iterate_new_addresses (chvc->hello, 2147 NULL);
2090 h, 2148 GNUNET_PEERINFO_add_peer (cfg, sched, &target, plain_hello);
2091 GNUNET_TIME_absolute_get (), 2149 GNUNET_free (plain_hello);
2092 &run_validation, chvc->e);
2093 }
2094 else if (GNUNET_YES == first_call)
2095 {
2096 /* no existing HELLO, all addresses are new */
2097 GNUNET_HELLO_iterate_addresses (chvc->hello,
2098 GNUNET_NO, &run_validation, chvc->e);
2099 }
2100
2101 if (h != NULL)
2102 return; /* wait for next call */
2103 /* finally, transmit validation attempts */
2104 GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (chvc->hello, &apeer));
2105
2106 va = chvc->e->addresses;
2107 count = 0;
2108 while (va != NULL)
2109 {
2110#if DEBUG_TRANSPORT 2150#if DEBUG_TRANSPORT
2111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2112 "Establishing `%s' connection to validate `%s' address `%s' of `%4s'\n", 2152 "Peerinfo had no `%s' message for peer `%4s', full validation needed.\n",
2113 va->transport_name, 2153 "HELLO",
2114 "HELLO", 2154 GNUNET_i2s (&target));
2115 GNUNET_a2s ((const struct sockaddr *) va->peer_address->addr,
2116 va->peer_address->addrlen), GNUNET_i2s (&apeer));
2117#endif 2155#endif
2118 tp = find_transport (va->transport_name); 2156 GNUNET_HELLO_iterate_addresses (chvc->hello,
2119 GNUNET_assert (tp != NULL); 2157 GNUNET_NO,
2120 /* This validation should happen inside the transport, not from the plugin! */ 2158 &run_validation,
2121 va->ok = GNUNET_SYSERR; 2159 chvc);
2122 va = va->next; 2160 }
2123 count++; 2161 GNUNET_free (chvc);
2162 return;
2124 } 2163 }
2125 2164 if (h == NULL)
2126 GNUNET_SCHEDULER_add_delayed (sched, 2165 return;
2127 GNUNET_TIME_absolute_get_remaining (chvc-> 2166 chvc->hello_known = GNUNET_YES;
2128 e->timeout), 2167 n = find_neighbor (peer);
2129 &cleanup_validation, NULL); 2168 if (n != NULL)
2130 GNUNET_free (chvc); 2169 GNUNET_HELLO_iterate_addresses (h,
2170 GNUNET_NO,
2171 &add_to_foreign_address_list,
2172 n);
2173 GNUNET_HELLO_iterate_new_addresses (chvc->hello,
2174 h,
2175 GNUNET_TIME_absolute_get (),
2176 &run_validation,
2177 chvc);
2131} 2178}
2132 2179
2133
2134/** 2180/**
2135 * Process HELLO-message. 2181 * Process HELLO-message.
2136 * 2182 *
@@ -2142,7 +2188,6 @@ static int
2142process_hello (struct TransportPlugin *plugin, 2188process_hello (struct TransportPlugin *plugin,
2143 const struct GNUNET_MessageHeader *message) 2189 const struct GNUNET_MessageHeader *message)
2144{ 2190{
2145 struct ValidationList *e;
2146 uint16_t hsize; 2191 uint16_t hsize;
2147 struct GNUNET_PeerIdentity target; 2192 struct GNUNET_PeerIdentity target;
2148 const struct GNUNET_HELLO_Message *hello; 2193 const struct GNUNET_HELLO_Message *hello;
@@ -2157,7 +2202,8 @@ process_hello (struct TransportPlugin *plugin,
2157 return GNUNET_SYSERR; 2202 return GNUNET_SYSERR;
2158 } 2203 }
2159 /* first, check if load is too high */ 2204 /* first, check if load is too high */
2160 if (GNUNET_OS_load_cpu_get (cfg) > 100) 2205 if (GNUNET_SCHEDULER_get_load (sched,
2206 GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
2161 { 2207 {
2162 /* TODO: call to stats? */ 2208 /* TODO: call to stats? */
2163 return GNUNET_OK; 2209 return GNUNET_OK;
@@ -2173,40 +2219,18 @@ process_hello (struct TransportPlugin *plugin,
2173 &target.hashPubKey); 2219 &target.hashPubKey);
2174#if DEBUG_TRANSPORT 2220#if DEBUG_TRANSPORT
2175 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2176 "Processing `%s' message for `%4s' of size %d (hsize is %d)\n", 2222 "Processing `%s' message for `%4s' of size %u\n",
2177 "HELLO", GNUNET_i2s (&target), GNUNET_HELLO_size(hello), hsize); 2223 "HELLO",
2178#endif 2224 GNUNET_i2s (&target),
2179 2225 GNUNET_HELLO_size(hello));
2180#if DEBUG_TRANSPORT
2181 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2182 "Notifying peerinfo about peer %s\n",
2183 GNUNET_i2s (&target));
2184#endif 2226#endif
2185 2227
2186 /* check if a HELLO for this peer is already on the validation list */
2187 e = pending_validations;
2188 while (e != NULL)
2189 {
2190 if (0 == memcmp (&e->publicKey,
2191 &publicKey,
2192 sizeof (struct
2193 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
2194 {
2195 /* TODO: call to stats? */
2196#if DEBUG_TRANSPORT
2197 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2198 "`%s' message for peer `%4s' is already pending; ignoring new message\n",
2199 "HELLO", GNUNET_i2s (&target));
2200#endif
2201 return GNUNET_OK;
2202 }
2203 e = e->next;
2204 }
2205 chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize); 2228 chvc = GNUNET_malloc (sizeof (struct CheckHelloValidatedContext) + hsize);
2206 chvc->plugin = plugin; 2229 chvc->hello = (const struct GNUNET_HELLO_Message *) &chvc[1];
2207 chvc->hello = (struct GNUNET_HELLO_Message *) &chvc[1]; 2230 memcpy (&chvc[1], hello, hsize);
2208 chvc->e = NULL; 2231 GNUNET_CONTAINER_DLL_insert (chvc_head,
2209 memcpy (chvc->hello, hello, hsize); 2232 chvc_tail,
2233 chvc);
2210 /* finally, check if HELLO was previously validated 2234 /* finally, check if HELLO was previously validated
2211 (continuation will then schedule actual validation) */ 2235 (continuation will then schedule actual validation) */
2212 chvc->piter = GNUNET_PEERINFO_iterate (cfg, 2236 chvc->piter = GNUNET_PEERINFO_iterate (cfg,
@@ -2240,8 +2264,8 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2240 struct NeighborList *nprev; 2264 struct NeighborList *nprev;
2241 struct NeighborList *n; 2265 struct NeighborList *n;
2242 struct MessageQueue *mq; 2266 struct MessageQueue *mq;
2243 struct PeerAddressList *peer_addresses; 2267 struct ForeignAddressList *peer_addresses;
2244 struct PeerAddressList *peer_pos; 2268 struct ForeignAddressList *peer_pos;
2245 2269
2246 if (neighbors == NULL) 2270 if (neighbors == NULL)
2247 return; /* We don't have any neighbors, so client has an already removed handle! */ 2271 return; /* We don't have any neighbors, so client has an already removed handle! */
@@ -2296,7 +2320,6 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2296 while (NULL != (rpos = n->plugins)) 2320 while (NULL != (rpos = n->plugins))
2297 { 2321 {
2298 n->plugins = rpos->next; 2322 n->plugins = rpos->next;
2299 GNUNET_assert (rpos->neighbor == n);
2300 if (GNUNET_YES == rpos->connected) 2323 if (GNUNET_YES == rpos->connected)
2301 rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id); 2324 rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
2302 2325
@@ -2304,7 +2327,6 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2304 { 2327 {
2305 peer_pos = rpos->addresses; 2328 peer_pos = rpos->addresses;
2306 rpos->addresses = peer_pos->next; 2329 rpos->addresses = peer_pos->next;
2307 GNUNET_free(peer_pos->addr);
2308 GNUNET_free(peer_pos); 2330 GNUNET_free(peer_pos);
2309 } 2331 }
2310 GNUNET_free (rpos); 2332 GNUNET_free (rpos);
@@ -2314,8 +2336,9 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2314 while (NULL != (mq = n->messages)) 2336 while (NULL != (mq = n->messages))
2315 { 2337 {
2316 n->messages = mq->next; 2338 n->messages = mq->next;
2317 GNUNET_assert (0 == memcmp(mq->neighbor_id, &n->id, sizeof(struct GNUNET_PeerIdentity))); 2339 GNUNET_assert (0 == memcmp(&mq->neighbor_id,
2318 GNUNET_free (mq->neighbor_id); 2340 &n->id,
2341 sizeof(struct GNUNET_PeerIdentity)));
2319 GNUNET_free (mq); 2342 GNUNET_free (mq);
2320 } 2343 }
2321 if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK) 2344 if (n->timeout_task != GNUNET_SCHEDULER_NO_TASK)
@@ -2325,29 +2348,27 @@ disconnect_neighbor (struct NeighborList *current_handle, int check)
2325} 2348}
2326 2349
2327 2350
2328/* 2351/**
2329 * We have received a PING message from someone. Need to send a PONG message 2352 * We have received a PING message from someone. Need to send a PONG message
2330 * in response to the peer by any means necessary. Of course, with something 2353 * in response to the peer by any means necessary.
2331 * like TCP where a connection exists, we may want to send it that way. But 2354 *
2332 * we may not be able to make that distinction... 2355 * FIXME: With something like TCP where a connection exists, we may
2333 */ 2356 * want to send it that way. But the current API does not seem to
2334static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message, 2357 * allow us to do so (can't tell this to the transport!)
2335 const struct GNUNET_PeerIdentity *peer, 2358 */
2336 const char *sender_address, 2359static int
2337 size_t sender_address_len) 2360handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2361 const struct GNUNET_PeerIdentity *peer,
2362 const char *sender_address,
2363 size_t sender_address_len)
2338{ 2364{
2339 struct TransportPlugin *plugin = cls; 2365 struct TransportPlugin *plugin = cls;
2340 struct TransportPingMessage *ping; 2366 struct TransportPingMessage *ping;
2341 struct TransportPongMessage *pong; 2367 struct TransportPongMessage *pong;
2342 struct PeerAddressList *peer_address;
2343 uint16_t msize; 2368 uint16_t msize;
2344 struct NeighborList *n; 2369 struct NeighborList *n;
2345 2370 struct ReadyList *rl;
2346#if DEBUG_TRANSPORT 2371 struct ForeignAddressList *fal;
2347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2348 "Processing `%s' from `%s'\n",
2349 "PING", GNUNET_a2s ((const struct sockaddr *)sender_address, sender_address_len));
2350#endif
2351 2372
2352 msize = ntohs (message->size); 2373 msize = ntohs (message->size);
2353 if (msize < sizeof (struct TransportPingMessage)) 2374 if (msize < sizeof (struct TransportPingMessage))
@@ -2361,12 +2382,18 @@ static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2361 sizeof (struct GNUNET_PeerIdentity))) 2382 sizeof (struct GNUNET_PeerIdentity)))
2362 { 2383 {
2363 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2384 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2364 _("Received `%s' message not destined for me!\n"), "PING"); 2385 _("Received `%s' message not destined for me!\n"),
2386 "PING");
2365 return GNUNET_SYSERR; 2387 return GNUNET_SYSERR;
2366 } 2388 }
2367 2389#if DEBUG_TRANSPORT
2390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2391 "Processing `%s' from `%s'\n",
2392 "PING",
2393 GNUNET_a2s ((const struct sockaddr *)sender_address,
2394 sender_address_len));
2395#endif
2368 msize -= sizeof (struct TransportPingMessage); 2396 msize -= sizeof (struct TransportPingMessage);
2369
2370 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len); 2397 pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
2371 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len); 2398 pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
2372 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG); 2399 pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
@@ -2377,8 +2404,9 @@ static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2377 pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING); 2404 pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
2378 pong->challenge = ping->challenge; 2405 pong->challenge = ping->challenge;
2379 pong->addrlen = htons(sender_address_len); 2406 pong->addrlen = htons(sender_address_len);
2380 2407 memcpy(&pong->signer,
2381 memcpy(&pong->signer, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); 2408 &my_public_key,
2409 sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2382 memcpy (&pong[1], sender_address, sender_address_len); 2410 memcpy (&pong[1], sender_address, sender_address_len);
2383 GNUNET_assert (GNUNET_OK == 2411 GNUNET_assert (GNUNET_OK ==
2384 GNUNET_CRYPTO_rsa_sign (my_private_key, 2412 GNUNET_CRYPTO_rsa_sign (my_private_key,
@@ -2387,23 +2415,28 @@ static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
2387 n = find_neighbor(peer); 2415 n = find_neighbor(peer);
2388 if (n == NULL) 2416 if (n == NULL)
2389 n = setup_new_neighbor(peer); 2417 n = setup_new_neighbor(peer);
2390 2418 /* broadcast 'PONG' to all available addresses */
2391 peer_address = find_peer_address(n, sender_address, sender_address_len); 2419 rl = n->plugins;
2392 if (peer_address == NULL) 2420 while (rl != NULL)
2393 peer_address = add_peer_address(n, sender_address, sender_address_len); 2421 {
2394 2422 fal = rl->addresses;
2395 peer_address->timeout = GNUNET_TIME_relative_to_absolute(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 2423 while (fal != NULL)
2396 2424 {
2397 /* We don't use the peer_address because the address we received the message from may not 2425 transmit_to_peer(NULL, fal,
2398 * be a reliable way to send it back! We add it to the list which should queue up a separate 2426 TRANSPORT_DEFAULT_PRIORITY,
2399 * ping to determine if the address is viable. 2427 (const char *)pong,
2400 */ 2428 ntohs(pong->header.size),
2401 transmit_to_peer(NULL, NULL, TRANSPORT_DEFAULT_PRIORITY, (char *)pong, ntohs(pong->header.size), GNUNET_NO, n); 2429 GNUNET_YES,
2402 2430 n);
2431 fal = fal->next;
2432 }
2433 rl = rl->next;
2434 }
2403 GNUNET_free(pong); 2435 GNUNET_free(pong);
2404 return GNUNET_OK; 2436 return GNUNET_OK;
2405} 2437}
2406 2438
2439
2407/** 2440/**
2408 * Function called by the plugin for each received message. 2441 * Function called by the plugin for each received message.
2409 * Update data volumes, possibly notify plugins about 2442 * Update data volumes, possibly notify plugins about
@@ -2432,7 +2465,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2432 struct TransportPlugin *plugin = cls; 2465 struct TransportPlugin *plugin = cls;
2433 struct TransportClient *cpos; 2466 struct TransportClient *cpos;
2434 struct InboundMessage *im; 2467 struct InboundMessage *im;
2435 struct PeerAddressList *peer_address; 2468 struct ForeignAddressList *peer_address;
2436 uint16_t msize; 2469 uint16_t msize;
2437 struct NeighborList *n; 2470 struct NeighborList *n;
2438 2471
@@ -2444,11 +2477,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2444 n = setup_new_neighbor (peer); 2477 n = setup_new_neighbor (peer);
2445 2478
2446 } 2479 }
2447
2448 peer_address = find_peer_address(n, sender_address, sender_address_len);
2449 if (peer_address == NULL)
2450 peer_address = add_peer_address(n, sender_address, sender_address_len);
2451
2452 service_context = n->plugins; 2480 service_context = n->plugins;
2453 while ((service_context != NULL) && (plugin != service_context->plugin)) 2481 while ((service_context != NULL) && (plugin != service_context->plugin))
2454 service_context = service_context->next; 2482 service_context = service_context->next;
@@ -2466,19 +2494,18 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2466 disconnect_neighbor (n, GNUNET_YES); 2494 disconnect_neighbor (n, GNUNET_YES);
2467 return; 2495 return;
2468 } 2496 }
2469#if DEBUG_TRANSPORT 2497 peer_address = add_peer_address(n,
2470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 2498 plugin->short_name,
2471 "Processing message of type %u received by plugin...\n", 2499 sender_address,
2472 ntohs (message->type)); 2500 sender_address_len);
2473#endif
2474 if (service_context != NULL) 2501 if (service_context != NULL)
2475 { 2502 {
2476 if (service_context->connected == GNUNET_NO) 2503 if (service_context->connected == GNUNET_NO)
2477 { 2504 {
2478 /*service_context->connected = GNUNET_YES;*/ 2505 service_context->connected = GNUNET_YES;
2479 /* FIXME: What to do here? Should we use these as well, to specify some Address 2506 /* FIXME: What to do here? Should we use these as well,
2480 * in the AddressList should be available? 2507 to specify some Address in the AddressList should be
2481 */ 2508 available? */
2482 peer_address->transmit_ready = GNUNET_YES; 2509 peer_address->transmit_ready = GNUNET_YES;
2483 peer_address->connect_attempts++; 2510 peer_address->connect_attempts++;
2484 } 2511 }
@@ -2507,41 +2534,23 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2507 _ 2534 _
2508 ("Dropping incoming message due to repeated bandwidth quota violations (total of %u).\n"), n->quota_violation_count); 2535 ("Dropping incoming message due to repeated bandwidth quota violations (total of %u).\n"), n->quota_violation_count);
2509 /* TODO: call stats */ 2536 /* TODO: call stats */
2510 GNUNET_assert ((service_context == NULL) ||
2511 (NULL != service_context->neighbor));
2512
2513 return; 2537 return;
2514 } 2538 }
2515 switch (ntohs (message->type)) 2539 switch (ntohs (message->type))
2516 { 2540 {
2517 case GNUNET_MESSAGE_TYPE_HELLO: 2541 case GNUNET_MESSAGE_TYPE_HELLO:
2518#if DEBUG_TRANSPORT
2519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2520 "Receiving `%s' message from `%4s'.\n", "HELLO",
2521 GNUNET_i2s (peer));
2522#endif
2523 process_hello (plugin, message); 2542 process_hello (plugin, message);
2524 break; 2543 break;
2525 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: 2544 case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
2526#if DEBUG_TRANSPORT
2527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2528 "Receiving `%s' message from `%4s'.\n", "PING",
2529 GNUNET_i2s (peer));
2530#endif
2531 handle_ping(plugin, message, peer, sender_address, sender_address_len); 2545 handle_ping(plugin, message, peer, sender_address, sender_address_len);
2532 break; 2546 break;
2533 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: 2547 case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
2534#if DEBUG_TRANSPORT
2535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2536 "Receiving `%s' message from `%4s'.\n", "PONG",
2537 GNUNET_i2s (peer));
2538#endif
2539 handle_pong(plugin, message, peer, sender_address, sender_address_len); 2548 handle_pong(plugin, message, peer, sender_address, sender_address_len);
2540 break; 2549 break;
2541 default: 2550 default:
2542#if DEBUG_TRANSPORT 2551#if DEBUG_TRANSPORT
2543 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2544 "Received REAL MESSAGE type %u from `%4s', sending to all clients.\n", 2553 "Received message of type %u from `%4s', sending to all clients.\n",
2545 ntohs (message->type), GNUNET_i2s (peer)); 2554 ntohs (message->type), GNUNET_i2s (peer));
2546#endif 2555#endif
2547 /* transmit message to all clients */ 2556 /* transmit message to all clients */
@@ -2560,8 +2569,6 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
2560 } 2569 }
2561 GNUNET_free (im); 2570 GNUNET_free (im);
2562 } 2571 }
2563 GNUNET_assert ((service_context == NULL) ||
2564 (NULL != service_context->neighbor));
2565} 2572}
2566 2573
2567 2574
@@ -2725,7 +2732,8 @@ handle_send (void *cls,
2725 ntohs (obmm->size), 2732 ntohs (obmm->size),
2726 ntohs (obmm->type), GNUNET_i2s (&obm->peer)); 2733 ntohs (obmm->type), GNUNET_i2s (&obm->peer));
2727#endif 2734#endif
2728 transmit_to_peer (tc, NULL, ntohl (obm->priority), (char *)obmm, ntohs (obmm->size), GNUNET_NO, n); 2735 transmit_to_peer (tc, NULL, ntohl (obm->priority), (char *)obmm,
2736 ntohs (obmm->size), GNUNET_NO, n);
2729 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2737 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2730} 2738}
2731 2739
@@ -2798,24 +2806,12 @@ handle_try_connect (void *cls,
2798 "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer)); 2806 "TRY_CONNECT", client, GNUNET_i2s (&tcm->peer));
2799#endif 2807#endif
2800 neighbor = find_neighbor(&tcm->peer); 2808 neighbor = find_neighbor(&tcm->peer);
2801
2802 if (neighbor == NULL) 2809 if (neighbor == NULL)
2803 setup_new_neighbor (&tcm->peer); 2810 setup_new_neighbor (&tcm->peer);
2804 else
2805 {
2806#if DEBUG_TRANSPORT
2807 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2808 "Client asked to connect to `%4s', but connection already exists\n",
2809 "TRY_CONNECT", GNUNET_i2s (&tcm->peer));
2810#endif
2811 transmit_to_peer (NULL, NULL, 0,
2812 (const char *) our_hello, GNUNET_HELLO_size(our_hello),
2813 GNUNET_YES, neighbor);
2814 notify_clients_connect (&tcm->peer, GNUNET_TIME_UNIT_FOREVER_REL);
2815 }
2816 GNUNET_SERVER_receive_done (client, GNUNET_OK); 2811 GNUNET_SERVER_receive_done (client, GNUNET_OK);
2817} 2812}
2818 2813
2814
2819static void 2815static void
2820transmit_address_to_client (void *cls, const char *address) 2816transmit_address_to_client (void *cls, const char *address)
2821{ 2817{
@@ -2832,6 +2828,7 @@ transmit_address_to_client (void *cls, const char *address)
2832 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); 2828 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
2833} 2829}
2834 2830
2831
2835/** 2832/**
2836 * Handle AddressLookup-message. 2833 * Handle AddressLookup-message.
2837 * 2834 *
@@ -3017,16 +3014,40 @@ client_disconnect_notification (void *cls,
3017 3014
3018 3015
3019/** 3016/**
3020 * Function called when the service shuts down. Unloads our plugins. 3017 * Iterator to free entries in the validation_map.
3018 *
3019 * @param cls closure (unused)
3020 * @param key current key code
3021 * @param value value in the hash map (validation to abort)
3022 * @return GNUNET_YES (always)
3023 */
3024static int
3025abort_validation (void *cls,
3026 const GNUNET_HashCode * key,
3027 void *value)
3028{
3029 struct ValidationEntry *va = value;
3030
3031 GNUNET_SCHEDULER_cancel (sched, va->timeout_task);
3032 GNUNET_free (va->transport_name);
3033 GNUNET_free (va);
3034 return GNUNET_YES;
3035}
3036
3037
3038/**
3039 * Function called when the service shuts down. Unloads our plugins
3040 * and cancels pending validations.
3021 * 3041 *
3022 * @param cls closure, unused 3042 * @param cls closure, unused
3023 * @param tc task context (unused) 3043 * @param tc task context (unused)
3024 */ 3044 */
3025static void 3045static void
3026unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 3046shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3027{ 3047{
3028 struct TransportPlugin *plug; 3048 struct TransportPlugin *plug;
3029 struct AddressList *al; 3049 struct OwnAddressList *al;
3050 struct CheckHelloValidatedContext *chvc;
3030 3051
3031#if DEBUG_TRANSPORT 3052#if DEBUG_TRANSPORT
3032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -3048,6 +3069,20 @@ unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3048 if (my_private_key != NULL) 3069 if (my_private_key != NULL)
3049 GNUNET_CRYPTO_rsa_key_free (my_private_key); 3070 GNUNET_CRYPTO_rsa_key_free (my_private_key);
3050 GNUNET_free_non_null (our_hello); 3071 GNUNET_free_non_null (our_hello);
3072
3073 /* free 'chvc' data structure */
3074 while (NULL != (chvc = chvc_head))
3075 {
3076 chvc_head = chvc->next;
3077 GNUNET_PEERINFO_iterate_cancel (chvc->piter);
3078 GNUNET_free (chvc);
3079 }
3080 chvc_tail = NULL;
3081
3082 GNUNET_CONTAINER_multihashmap_iterate (validation_map,
3083 &abort_validation,
3084 NULL);
3085 GNUNET_CONTAINER_multihashmap_destroy (validation_map);
3051} 3086}
3052 3087
3053 3088
@@ -3073,6 +3108,7 @@ run (void *cls,
3073 3108
3074 sched = s; 3109 sched = s;
3075 cfg = c; 3110 cfg = c;
3111 validation_map = GNUNET_CONTAINER_multihashmap_create (64);
3076 /* parse configuration */ 3112 /* parse configuration */
3077 if ((GNUNET_OK != 3113 if ((GNUNET_OK !=
3078 GNUNET_CONFIGURATION_get_value_number (c, 3114 GNUNET_CONFIGURATION_get_value_number (c,
@@ -3127,7 +3163,7 @@ run (void *cls,
3127 } 3163 }
3128 GNUNET_SCHEDULER_add_delayed (sched, 3164 GNUNET_SCHEDULER_add_delayed (sched,
3129 GNUNET_TIME_UNIT_FOREVER_REL, 3165 GNUNET_TIME_UNIT_FOREVER_REL,
3130 &unload_plugins, NULL); 3166 &shutdown_task, NULL);
3131 if (no_transports) 3167 if (no_transports)
3132 refresh_hello (); 3168 refresh_hello ();
3133 3169
diff --git a/src/transport/plugin_transport.h b/src/transport/plugin_transport.h
index 5fa630483..e00c97799 100644
--- a/src/transport/plugin_transport.h
+++ b/src/transport/plugin_transport.h
@@ -197,7 +197,7 @@ typedef ssize_t
197 (*GNUNET_TRANSPORT_TransmitFunction) (void *cls, 197 (*GNUNET_TRANSPORT_TransmitFunction) (void *cls,
198 const struct GNUNET_PeerIdentity * 198 const struct GNUNET_PeerIdentity *
199 target, 199 target,
200 char *msgbuf, 200 const char *msgbuf,
201 size_t msgbuf_size, 201 size_t msgbuf_size,
202 uint32_t priority, 202 uint32_t priority,
203 struct GNUNET_TIME_Relative timeout, 203 struct GNUNET_TIME_Relative timeout,
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 76c9b6df0..783cd5047 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -416,7 +416,8 @@ do_transmit (void *cls, size_t size, void *buf)
416 &session->target, GNUNET_OK); 416 &session->target, GNUNET_OK);
417 GNUNET_free (pm); 417 GNUNET_free (pm);
418 } 418 }
419 process_pending_messages (session); 419 if (session->client != NULL)
420 process_pending_messages (session);
420#if DEBUG_TCP 421#if DEBUG_TCP
421 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 422 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
422 "tcp", "Transmitting %u bytes\n", ret); 423 "tcp", "Transmitting %u bytes\n", ret);
@@ -1112,22 +1113,18 @@ handle_tcp_data (void *cls,
1112 session = find_session_by_client (plugin, client); 1113 session = find_session_by_client (plugin, client);
1113 1114
1114 if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) 1115 if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type))
1115 { 1116 {
1116#if DEBUG_TCP 1117#if DEBUG_TCP
1117 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1118 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1118 "tcp", "Received a welcome, NOT sending to clients!\n"); 1119 "tcp", "Received a welcome, NOT sending to clients!\n");
1119#endif 1120#endif
1120 GNUNET_SERVER_receive_done (client, GNUNET_OK); 1121 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1121 return; /* We don't want to propagate WELCOME messages up! */ 1122 return; /* We don't want to propagate WELCOME messages up! */
1122 } 1123 }
1123 else
1124 {
1125#if DEBUG_TCP 1124#if DEBUG_TCP
1126 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 1125 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
1127 "tcp", "Received DATA message, checking session!\n"); 1126 "tcp", "Received DATA message, checking session!\n");
1128#endif 1127#endif
1129 }
1130
1131 if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome)) 1128 if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome))
1132 { 1129 {
1133 GNUNET_break_op (0); 1130 GNUNET_break_op (0);
diff --git a/src/transport/plugin_transport_template.c b/src/transport/plugin_transport_template.c
index ab4149c90..bac9bcd82 100644
--- a/src/transport/plugin_transport_template.c
+++ b/src/transport/plugin_transport_template.c
@@ -148,7 +148,7 @@ static ssize_t
148template_plugin_send (void *cls, 148template_plugin_send (void *cls,
149 const struct GNUNET_PeerIdentity * 149 const struct GNUNET_PeerIdentity *
150 target, 150 target,
151 char *msgbuf, 151 const char *msgbuf,
152 size_t msgbuf_size, 152 size_t msgbuf_size,
153 unsigned int priority, 153 unsigned int priority,
154 struct GNUNET_TIME_Relative timeout, 154 struct GNUNET_TIME_Relative timeout,
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 7f3566c59..94222bd6d 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -206,7 +206,7 @@ udp_transport_server_stop (void *cls)
206static ssize_t 206static ssize_t
207udp_plugin_send (void *cls, 207udp_plugin_send (void *cls,
208 const struct GNUNET_PeerIdentity *target, 208 const struct GNUNET_PeerIdentity *target,
209 char *msgbuf, 209 const char *msgbuf,
210 size_t msgbuf_size, 210 size_t msgbuf_size,
211 unsigned int priority, 211 unsigned int priority,
212 struct GNUNET_TIME_Relative timeout, 212 struct GNUNET_TIME_Relative timeout,
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index 85d6c244c..bc9971877 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -103,6 +103,7 @@ stop_arm (struct PeerContext *p)
103 GNUNET_CONFIGURATION_destroy (p->cfg); 103 GNUNET_CONFIGURATION_destroy (p->cfg);
104} 104}
105 105
106
106static void 107static void
107end_badly () 108end_badly ()
108{ 109{
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
index 189e933b4..334545c05 100644
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ b/src/transport/test_transport_api_tcp_peer1.conf
@@ -61,13 +61,14 @@ PORT = 2092
61 61
62[transport] 62[transport]
63PLUGINS = tcp 63PLUGINS = tcp
64DEBUG = NO 64DEBUG = YES
65#PREFIX = valgrind --leak-check=full --log-file=valgrind_tcp_peer1.log 65#PREFIX = xterm -T transport2 -e gdb --command=cmd --args
66#PREFIX = valgrind --leak-check=full
66ALLOW_SHUTDOWN = YES 67ALLOW_SHUTDOWN = YES
67ACCEPT_FROM6 = ::1; 68ACCEPT_FROM6 = ::1;
68ACCEPT_FROM = 127.0.0.1; 69ACCEPT_FROM = 127.0.0.1;
69NEIGHBOUR_LIMIT = 50 70NEIGHBOUR_LIMIT = 50
70BINARY = gnunet-service-transport 71BINARY = /home/grothoff/bin/gnunet-service-transport
71CONFIG = $DEFAULTCONFIG 72CONFIG = $DEFAULTCONFIG
72HOME = $SERVICEHOME 73HOME = $SERVICEHOME
73HOSTNAME = localhost 74HOSTNAME = localhost
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf
index 34fa8cf64..f05f36719 100644
--- a/src/transport/test_transport_api_tcp_peer2.conf
+++ b/src/transport/test_transport_api_tcp_peer2.conf
@@ -61,17 +61,19 @@ PORT = 2092
61 61
62[transport] 62[transport]
63PLUGINS = tcp 63PLUGINS = tcp
64DEBUG = NO 64DEBUG = YES
65PREFIX = 65PREFIX =
66ALLOW_SHUTDOWN = YES 66ALLOW_SHUTDOWN = YES
67ACCEPT_FROM6 = ::1; 67ACCEPT_FROM6 = ::1;
68ACCEPT_FROM = 127.0.0.1; 68ACCEPT_FROM = 127.0.0.1;
69NEIGHBOUR_LIMIT = 50 69NEIGHBOUR_LIMIT = 50
70BINARY = gnunet-service-transport 70BINARY = /home/grothoff/bin/gnunet-service-transport
71CONFIG = $DEFAULTCONFIG 71CONFIG = $DEFAULTCONFIG
72HOME = $SERVICEHOME 72HOME = $SERVICEHOME
73HOSTNAME = localhost 73HOSTNAME = localhost
74PORT = 22365 74PORT = 22365
75#PREFIX = xterm -T transport1 -e gdb --command=cmd --args
76#PREFIX = valgrind --leak-check=full
75 77
76[peerinfo] 78[peerinfo]
77TRUST = $SERVICEHOME/data/credit/ 79TRUST = $SERVICEHOME/data/credit/