diff options
-rw-r--r-- | src/transport/gnunet-service-transport.c | 1556 | ||||
-rw-r--r-- | src/transport/plugin_transport.h | 2 | ||||
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 19 | ||||
-rw-r--r-- | src/transport/plugin_transport_template.c | 2 | ||||
-rw-r--r-- | src/transport/plugin_transport_udp.c | 2 | ||||
-rw-r--r-- | src/transport/test_transport_api.c | 1 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer1.conf | 7 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer2.conf | 6 |
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 | */ |
104 | struct PeerAddressList | 115 | struct 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 | */ |
196 | struct AddressList | 195 | struct 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 | */ |
622 | struct ValidationAddress | 606 | struct 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 | */ |
666 | struct ValidationList | 653 | struct 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 | |||
694 | struct 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 | */ | ||
724 | static struct ValidationList *pending_validations; | ||
725 | |||
726 | /** | 685 | /** |
727 | * Our HELLO message. | 686 | * Our HELLO message. |
728 | */ | 687 | */ |
729 | static struct GNUNET_HELLO_Message *our_hello; | 688 | static 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 | */ |
736 | static unsigned int our_hello_version; | 694 | static unsigned int our_hello_version; |
737 | 695 | ||
@@ -786,6 +744,25 @@ static struct NeighborList *neighbors; | |||
786 | static uint32_t max_connect_per_transport; | 744 | static uint32_t max_connect_per_transport; |
787 | 745 | ||
788 | /** | 746 | /** |
747 | * Head of linked list. | ||
748 | */ | ||
749 | static struct CheckHelloValidatedContext *chvc_head; | ||
750 | |||
751 | /** | ||
752 | * Tail of linked list. | ||
753 | */ | ||
754 | static 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 | */ | ||
761 | static 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 | */ |
801 | static void disconnect_neighbor (struct NeighborList *n, int check); | 778 | static 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 | */ |
811 | static ssize_t try_transmission_to_peer (struct NeighborList *neighbor); | 786 | static 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 | */ | ||
1025 | static void | ||
1026 | try_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 | |
1130 | struct 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 | */ | ||
1078 | struct ForeignAddressList * | ||
1131 | find_ready_address(struct NeighborList *neighbor) | 1079 | find_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 | */ |
1192 | static ssize_t | 1140 | static void |
1193 | try_transmission_to_peer (struct NeighborList *neighbor) | 1141 | try_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 | */ |
1257 | static ssize_t | 1202 | static void |
1258 | transmit_to_peer (struct TransportClient *client, | 1203 | transmit_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, | |||
1320 | struct GeneratorContext | 1270 | struct 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 | */ | ||
1548 | static struct ForeignAddressList * | ||
1549 | find_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 | */ | ||
1586 | static struct ForeignAddressList * | ||
1587 | add_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 | */ | ||
1627 | struct 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 | */ |
1593 | static size_t | 1653 | static size_t |
1594 | list_validated_addresses (void *cls, size_t max, void *buf) | 1654 | add_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 | */ |
1614 | static void | 1683 | static int |
1615 | cleanup_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 1684 | check_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 | */ | ||
1815 | static void | ||
1816 | add_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 | ||
1839 | static void | 1804 | static void |
1840 | neighbor_timeout_task (void *cls, | 1805 | neighbor_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 * | |||
1862 | setup_new_neighbor (const struct GNUNET_PeerIdentity *peer) | 1828 | setup_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 | ||
1887 | static struct PeerAddressList * | 1867 | |
1888 | add_peer_address(struct NeighborList *neighbor, const char *addr, size_t addrlen) | 1868 | /** |
1869 | * Closure for 'check_address_exists'. | ||
1870 | */ | ||
1871 | struct 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 | */ | ||
1906 | static int | ||
1907 | check_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 | ||
1922 | static struct PeerAddressList * | 1926 | |
1923 | find_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 | */ | ||
1933 | static void | ||
1934 | timeout_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 | */ |
1948 | static int | 1963 | static int |
1949 | run_validation (void *cls, | 1964 | run_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 | */ | ||
2082 | static int | ||
2083 | add_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 | */ |
2060 | static void | 2119 | static void |
2061 | check_hello_validated (void *cls, | 2120 | check_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 | |||
2142 | process_hello (struct TransportPlugin *plugin, | 2188 | process_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 |
2334 | static 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, | 2359 | static int |
2337 | size_t sender_address_len) | 2360 | handle_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 | |||
2819 | static void | 2815 | static void |
2820 | transmit_address_to_client (void *cls, const char *address) | 2816 | transmit_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 | */ | ||
3024 | static int | ||
3025 | abort_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 | */ |
3025 | static void | 3045 | static void |
3026 | unload_plugins (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 3046 | shutdown_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 | |||
148 | template_plugin_send (void *cls, | 148 | template_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) | |||
206 | static ssize_t | 206 | static ssize_t |
207 | udp_plugin_send (void *cls, | 207 | udp_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 | |||
106 | static void | 107 | static void |
107 | end_badly () | 108 | end_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] |
63 | PLUGINS = tcp | 63 | PLUGINS = tcp |
64 | DEBUG = NO | 64 | DEBUG = 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 | ||
66 | ALLOW_SHUTDOWN = YES | 67 | ALLOW_SHUTDOWN = YES |
67 | ACCEPT_FROM6 = ::1; | 68 | ACCEPT_FROM6 = ::1; |
68 | ACCEPT_FROM = 127.0.0.1; | 69 | ACCEPT_FROM = 127.0.0.1; |
69 | NEIGHBOUR_LIMIT = 50 | 70 | NEIGHBOUR_LIMIT = 50 |
70 | BINARY = gnunet-service-transport | 71 | BINARY = /home/grothoff/bin/gnunet-service-transport |
71 | CONFIG = $DEFAULTCONFIG | 72 | CONFIG = $DEFAULTCONFIG |
72 | HOME = $SERVICEHOME | 73 | HOME = $SERVICEHOME |
73 | HOSTNAME = localhost | 74 | HOSTNAME = 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] |
63 | PLUGINS = tcp | 63 | PLUGINS = tcp |
64 | DEBUG = NO | 64 | DEBUG = YES |
65 | PREFIX = | 65 | PREFIX = |
66 | ALLOW_SHUTDOWN = YES | 66 | ALLOW_SHUTDOWN = YES |
67 | ACCEPT_FROM6 = ::1; | 67 | ACCEPT_FROM6 = ::1; |
68 | ACCEPT_FROM = 127.0.0.1; | 68 | ACCEPT_FROM = 127.0.0.1; |
69 | NEIGHBOUR_LIMIT = 50 | 69 | NEIGHBOUR_LIMIT = 50 |
70 | BINARY = gnunet-service-transport | 70 | BINARY = /home/grothoff/bin/gnunet-service-transport |
71 | CONFIG = $DEFAULTCONFIG | 71 | CONFIG = $DEFAULTCONFIG |
72 | HOME = $SERVICEHOME | 72 | HOME = $SERVICEHOME |
73 | HOSTNAME = localhost | 73 | HOSTNAME = localhost |
74 | PORT = 22365 | 74 | PORT = 22365 |
75 | #PREFIX = xterm -T transport1 -e gdb --command=cmd --args | ||
76 | #PREFIX = valgrind --leak-check=full | ||
75 | 77 | ||
76 | [peerinfo] | 78 | [peerinfo] |
77 | TRUST = $SERVICEHOME/data/credit/ | 79 | TRUST = $SERVICEHOME/data/credit/ |