… | |
… | |
62 | |
62 | |
63 | ############################################################################# |
63 | ############################################################################# |
64 | # seednodes |
64 | # seednodes |
65 | |
65 | |
66 | our $MASTER; # our current master (which we regularly query for net updates) |
66 | our $MASTER; # our current master (which we regularly query for net updates) |
67 | |
|
|
68 | our %SEEDME; # $node => $port |
|
|
69 | our @SEEDS; |
67 | our %SEEDME; |
70 | our %SEEDS; # just to check whether a seed is a seed |
|
|
71 | our %SEED_CONNECT; |
|
|
72 | our $SEED_WATCHER; |
|
|
73 | |
|
|
74 | push @AnyEvent::MP::Transport::HOOK_CONNECT, sub { |
|
|
75 | my $peer = $_[0]{local_greeting}{peeraddr}; |
|
|
76 | return unless exists $SEEDS{$peer}; |
|
|
77 | $SEED_CONNECT{$peer} = 2; |
|
|
78 | }; |
|
|
79 | |
|
|
80 | push @AnyEvent::MP::Transport::HOOK_GREETING, sub { |
|
|
81 | # we rely on untrusted data here (the remote node name) |
|
|
82 | # this is hopefully ok, as we override it on successful |
|
|
83 | # connects, and this can at most be used for DOSing, |
|
|
84 | # which is easy when you can do MITM. |
|
|
85 | my $peer = $_[0]{local_greeting}{peeraddr}; |
|
|
86 | return unless exists $SEEDS{$peer}; |
|
|
87 | $SEEDS{$peer} ||= $_[0]{remote_node}; |
|
|
88 | }; |
|
|
89 | |
|
|
90 | push @AnyEvent::MP::Transport::HOOK_CONNECTED, sub { |
|
|
91 | my $peer = $_[0]{local_greeting}{peeraddr}; |
|
|
92 | return unless exists $SEEDS{$peer}; |
|
|
93 | $SEEDS{$peer} = $_[0]{remote_node}; |
|
|
94 | }; |
|
|
95 | |
|
|
96 | push @AnyEvent::MP::Transport::HOOK_DESTROY, sub { |
|
|
97 | delete $SEED_CONNECT{$_[0]{local_greeting}{peeraddr}}; |
|
|
98 | |
|
|
99 | # check if we contacted ourselves, so nuke this seed |
|
|
100 | if (exists $_[0]{seed} && $_[0]{remote_node} eq $AnyEvent::MP::Kernel::NODE) { |
|
|
101 | # $AnyEvent::MP::Kernel::WARN->(0,"avoiding seed $_[0]{seed}\n");#d# |
|
|
102 | delete $SEEDS{$_[0]{seed}}; |
|
|
103 | } |
|
|
104 | }; |
|
|
105 | |
|
|
106 | sub seed_connect { |
|
|
107 | my ($seed) = @_; |
|
|
108 | |
|
|
109 | my ($host, $port) = AnyEvent::Socket::parse_hostport $seed |
|
|
110 | or Carp::croak "$seed: unparsable seed address"; |
|
|
111 | |
|
|
112 | return if $SEED_CONNECT{$seed}; |
|
|
113 | return if defined $SEEDS{$seed} && node_is_up $SEEDS{$seed}; |
|
|
114 | |
|
|
115 | $AnyEvent::MP::Kernel::WARN->(9, "trying connect to seed node $seed."); |
|
|
116 | |
|
|
117 | # ughhh |
|
|
118 | $SEED_CONNECT{$seed} ||= AnyEvent::MP::Transport::mp_connect $host, $port, |
|
|
119 | seed => $seed, |
|
|
120 | sub { |
|
|
121 | $SEED_CONNECT{$seed} = 1; |
|
|
122 | }, |
|
|
123 | ; |
|
|
124 | } |
|
|
125 | |
|
|
126 | sub more_seeding { |
|
|
127 | my $int = List::Util::max 1, |
|
|
128 | $AnyEvent::MP::Kernel::CONFIG->{connect_interval} |
|
|
129 | * ($nodecnt ? keys %AnyEvent::MP::Kernel::NODE : 1) |
|
|
130 | - rand; |
|
|
131 | |
|
|
132 | $SEED_WATCHER = AE::timer $int, 0, \&more_seeding; |
|
|
133 | |
|
|
134 | @SEEDS = keys %SEEDS unless @SEEDS; |
|
|
135 | return unless @SEEDS; |
|
|
136 | |
|
|
137 | seed_connect splice @SEEDS, rand @SEEDS, 1; |
|
|
138 | } |
|
|
139 | |
|
|
140 | sub set_seeds(@) { |
|
|
141 | @SEEDS{@_} = (); |
|
|
142 | |
|
|
143 | $SEED_WATCHER ||= AE::timer 5, $AnyEvent::MP::Kernel::MONITOR_TIMEOUT, \&more_seeding; |
|
|
144 | |
|
|
145 | after 0.100 * rand, \&more_seeding |
|
|
146 | for 1 .. keys %SEEDS; |
|
|
147 | } |
|
|
148 | |
68 | |
149 | sub up_seeds() { |
69 | sub up_seeds() { |
150 | grep node_is_up $_, values %SEEDS |
70 | grep node_is_up $_, keys %AnyEvent::MP::Kernel::NODE_SEED |
151 | } |
71 | } |
152 | |
72 | |
153 | sub node_is_seed($) { |
73 | sub node_is_seed($) { |
154 | grep $_ eq $_[0], grep defined, values %SEEDS |
74 | grep $_ eq $_[0], grep defined, keys %AnyEvent::MP::Kernel::NODE_SEED |
155 | } |
75 | } |
156 | |
76 | |
157 | # returns all (up) seed nodes, or all nodes if no seednodes are up/known |
77 | # returns all (up) seed nodes, or all nodes if no seednodes are up/known |
158 | sub route_nodes { |
78 | sub route_nodes { |
159 | my @seeds = up_seeds; |
79 | my @seeds = up_seeds; |
… | |
… | |
433 | } |
353 | } |
434 | } |
354 | } |
435 | |
355 | |
436 | unless ($is_up) { |
356 | unless ($is_up) { |
437 | --$nodecnt; |
357 | --$nodecnt; |
438 | more_seeding unless $nodecnt; |
358 | #d#more_seeding unless $nodecnt; |
439 | unreg_groups $node; |
359 | unreg_groups $node; |
440 | |
360 | |
441 | # forget about the node |
361 | # forget about the node |
442 | delete $addr{$node}; |
362 | delete $addr{$node}; |
443 | |
363 | |