@@ -1008,6 +1008,20 @@ def __repr__(self):
10081008 return "msg_reject: %s %d %s [%064x]" \
10091009 % (self .message , self .code , self .reason , self .data )
10101010
1011+ # Helper function
1012+ def wait_until (predicate , attempts = float ('inf' ), timeout = float ('inf' )):
1013+ attempt = 0
1014+ elapsed = 0
1015+
1016+ while attempt < attempts and elapsed < timeout :
1017+ with mininode_lock :
1018+ if predicate ():
1019+ return True
1020+ attempt += 1
1021+ elapsed += 0.05
1022+ time .sleep (0.05 )
1023+
1024+ return False
10111025
10121026# This is what a callback should look like for NodeConn
10131027# Reimplement the on_* functions to provide handling for events
@@ -1085,6 +1099,32 @@ def on_close(self, conn): pass
10851099 def on_mempool (self , conn ): pass
10861100 def on_pong (self , conn , message ): pass
10871101
1102+ # More useful callbacks and functions for NodeConnCB's which have a single NodeConn
1103+ class SingleNodeConnCB (NodeConnCB ):
1104+ def __init__ (self ):
1105+ NodeConnCB .__init__ (self )
1106+ self .connection = None
1107+ self .ping_counter = 1
1108+ self .last_pong = msg_pong ()
1109+
1110+ def add_connection (self , conn ):
1111+ self .connection = conn
1112+
1113+ # Wrapper for the NodeConn's send_message function
1114+ def send_message (self , message ):
1115+ self .connection .send_message (message )
1116+
1117+ def on_pong (self , conn , message ):
1118+ self .last_pong = message
1119+
1120+ # Sync up with the node
1121+ def sync_with_ping (self , timeout = 30 ):
1122+ def received_pong ():
1123+ return (self .last_pong .nonce == self .ping_counter )
1124+ self .send_message (msg_ping (nonce = self .ping_counter ))
1125+ success = wait_until (received_pong , timeout )
1126+ self .ping_counter += 1
1127+ return success
10881128
10891129# The actual NodeConn class
10901130# This class provides an interface for a p2p connection to a specified node
0 commit comments