24
24
25
25
from hathor .conf import HathorSettings
26
26
from hathor .p2p .netfilter .factory import NetfilterFactory
27
+ from hathor .p2p .peer_discovery import PeerDiscovery
27
28
from hathor .p2p .peer_id import PeerId
28
29
from hathor .p2p .peer_storage import PeerStorage
29
30
from hathor .p2p .protocol import HathorProtocol
@@ -114,6 +115,12 @@ def __init__(self,
114
115
115
116
self .network = network
116
117
118
+ # List of addresses to listen for new connections (eg: [tcp:8000])
119
+ self .listen_addresses : list [str ] = []
120
+
121
+ # List of peer discovery methods.
122
+ self .peer_discoveries : list [PeerDiscovery ] = []
123
+
117
124
# Options
118
125
self .localhost_only = False
119
126
@@ -202,6 +209,21 @@ def set_manager(self, manager: 'HathorManager') -> None:
202
209
indexes .enable_deps_index ()
203
210
indexes .enable_mempool_index ()
204
211
212
+ def add_listen_address (self , addr : str ) -> None :
213
+ """Add address to listen for incoming connections."""
214
+ self .listen_addresses .append (addr )
215
+
216
+ def add_peer_discovery (self , peer_discovery : PeerDiscovery ) -> None :
217
+ """Add a peer discovery method."""
218
+ self .peer_discoveries .append (peer_discovery )
219
+
220
+ def do_discovery (self ) -> None :
221
+ """
222
+ Do a discovery and connect on all discovery strategies.
223
+ """
224
+ for peer_discovery in self .peer_discoveries :
225
+ peer_discovery .discover_and_connect (self .connect_to )
226
+
205
227
def disable_rate_limiter (self ) -> None :
206
228
"""Disable global rate limiter."""
207
229
self .rate_limiter .unset_limit (self .GlobalRateLimiter .SEND_TIPS )
@@ -217,9 +239,15 @@ def enable_rate_limiter(self, max_hits: int = 16, window_seconds: float = 1) ->
217
239
def start (self ) -> None :
218
240
self .lc_reconnect .start (5 , now = False )
219
241
self .lc_sync_update .start (self .lc_sync_update_interval , now = False )
242
+
220
243
if settings .ENABLE_PEER_WHITELIST :
221
244
self ._start_whitelist_reconnect ()
222
245
246
+ for description in self .listen_addresses :
247
+ self .listen (description )
248
+
249
+ self .do_discovery ()
250
+
223
251
def _start_whitelist_reconnect (self ) -> None :
224
252
# The deferred returned by the LoopingCall start method
225
253
# executes when the looping call stops running
@@ -442,7 +470,7 @@ def on_receive_peer(self, peer: PeerId, origin: Optional[ReadyState] = None) ->
442
470
if peer .id == self .my_peer .id :
443
471
return
444
472
peer = self .received_peer_storage .add_or_merge (peer )
445
- self .connect_to_if_not_connected (peer , 0 )
473
+ self .connect_to_if_not_connected (peer , int ( self . reactor . seconds ()) )
446
474
447
475
def peers_cleanup (self ) -> None :
448
476
"""Clean up aged peers."""
@@ -469,7 +497,7 @@ def reconnect_to_all(self) -> None:
469
497
# when we have no connected peers left, run the discovery process again
470
498
assert self .manager is not None
471
499
if len (self .connected_peers ) < 1 :
472
- self .manager . do_discovery ()
500
+ self .do_discovery ()
473
501
now = int (self .reactor .seconds ())
474
502
# We need to use list() here because the dict might change inside connect_to_if_not_connected
475
503
# when the peer is disconnected and without entrypoint
@@ -614,7 +642,7 @@ def connect_to(self, description: str, peer: Optional[PeerId] = None, use_ssl: O
614
642
)
615
643
616
644
def listen (self , description : str , use_ssl : Optional [bool ] = None ) -> IStreamServerEndpoint :
617
- """ Start to listen to new connection according to the description.
645
+ """ Start to listen for new connection according to the description.
618
646
619
647
If `ssl` is True, then the connection will be wraped by a TLS.
620
648
@@ -641,6 +669,17 @@ def listen(self, description: str, use_ssl: Optional[bool] = None) -> IStreamSer
641
669
642
670
self .log .info ('listen on' , endpoint = description )
643
671
endpoint .listen (factory )
672
+
673
+ # XXX: endpoint: IStreamServerEndpoint does not intrinsically have a port, but in practice all concrete cases
674
+ # that we have will have a _port attribute
675
+ port = getattr (endpoint , '_port' , None )
676
+ assert self .manager is not None
677
+ if self .manager .hostname and port is not None :
678
+ proto , _ , _ = description .partition (':' )
679
+ address = '{}://{}:{}' .format (proto , self .manager .hostname , port )
680
+ assert self .manager .my_peer is not None
681
+ self .manager .my_peer .entrypoints .append (address )
682
+
644
683
return endpoint
645
684
646
685
def get_connection_to_drop (self , protocol : HathorProtocol ) -> HathorProtocol :
0 commit comments