@@ -7,8 +7,6 @@ module Bitcoin::Network
77 # Node network connection to a peer. Handles all the communication with a specific peer.
88 class ConnectionHandler < EM ::Connection
99
10- LATENCY_MAX = ( 5 *60 *1000 ) # 5min in ms
11-
1210 include Bitcoin
1311 include Bitcoin ::Storage
1412
@@ -35,10 +33,10 @@ def initialize node, host, port, direction
3533 @parser = Bitcoin ::Protocol ::Parser . new ( self )
3634 @state = :new
3735 @version = nil
38- @started = nil
36+ @started = Time . now
3937 @port , @host = *Socket . unpack_sockaddr_in ( get_peername ) if get_peername
4038 @ping_nonce = nil
41- @latency_ms = nil
39+ @latency_ms = @node . config [ :connection_timeout ] * 1000
4240 @lock = Monitor . new
4341 @last_getblocks = [ ] # the last few getblocks messages received
4442 rescue
@@ -48,9 +46,7 @@ def initialize node, host, port, direction
4846
4947 # check if connection is wanted, begin handshake if it is, disconnect if not
5048 def post_init
51- if incoming?
52- begin_handshake
53- end
49+ begin_handshake if incoming?
5450 rescue
5551 log . fatal { "Error in #post_init" }
5652 p $!; puts *$@
@@ -83,15 +79,23 @@ def unbind
8379 end
8480
8581 # begin handshake
86- # TODO: disconnect if we don't complete within a reasonable time
8782 def begin_handshake
8883 if incoming? && !@node . accept_connections?
8984 return close_connection unless @node . config [ :connect ] . include? ( [ @host , @port . to_s ] )
9085 end
9186 log . info { "Established #{ @direction } connection" }
9287 @node . connections << self
9388 @state = :handshake
89+
90+ EM . add_timer ( @node . config [ :connection_timeout ] ) do
91+ unless @state == :connected
92+ log . debug { "Handshake timed out." }
93+ close_connection
94+ end
95+ end
96+
9497 send_version
98+
9599 rescue
96100 log . fatal { "Error in #begin_handshake" }
97101 p $!; puts *$@
@@ -102,6 +106,7 @@ def complete_handshake
102106 if @state == :handshake
103107 log . debug { 'Handshake completed' }
104108 @state = :connected
109+ @latency_ms = Time . now - @started
105110 @started = Time . now
106111 @node . push_notification ( :connection , info . merge ( type : :connected ) )
107112 @node . addrs << addr
@@ -301,18 +306,23 @@ def send_getaddr
301306 send_data ( Protocol . pkt ( "getaddr" , "" ) )
302307 end
303308
304- # send +ping+ message
305- # TODO: wait for pong and disconnect if it doesn't arrive (and version is new enough)
306- def send_ping
309+ # send +ping+ message. if +wait+ is true, wait for pong and disconnect
310+ # if it doesn't arrive in time (and version is new enough)
311+ def send_ping wait = true
307312 if @version . version > Bitcoin ::Protocol ::BIP0031_VERSION
308- @latency_ms = LATENCY_MAX
309313 @ping_nonce = rand ( 0xffffffff )
310314 @ping_time = Time . now
311315 log . debug { "<< ping (#{ @ping_nonce } )" }
316+ EM . add_timer ( @node . config [ :connection_timeout ] ) do
317+ unless @latency_ms / 1000 < @node . config [ :connection_timeout ]
318+ log . debug { "Ping #{ @ping_nonce } timed out." }
319+ close_connection
320+ end
321+ end
312322 send_data ( Protocol . ping_pkt ( @ping_nonce ) )
313323 else
314- # set latency to 5 seconds , terrible but this version should be obsolete now
315- @latency_ms = ( 5 * 1000 )
324+ # set latency to maximum allowed , terrible but this version should be obsolete now
325+ @latency_ms = @node . config [ :connection_timeout ]
316326 log . debug { "<< ping" }
317327 send_data ( Protocol . ping_pkt )
318328 end
0 commit comments