<s> import gevent , gevent . queue , socket , time <EOL> from node import Node <EOL> def addr_2_host_port ( addr ) : <EOL> host = "<STR_LIT::>" . join ( addr . split ( '<STR_LIT::>' ) [ : - <NUM_LIT:1> ] ) <EOL> port = addr . split ( '<STR_LIT::>' ) [ - <NUM_LIT:1> ] <EOL> return host , int ( port ) <EOL> def Connect ( finger , set_handler , addr ) : <EOL> s = socket . socket ( socket . AF_INET , socket . SOCK_STREAM ) <EOL> s . connect ( ( addr_2_host_port ( addr ) ) ) <EOL> return Protocol ( s , addr , finger , set_handler ) <EOL> class Protocol ( ) : <EOL> def __init__ ( self , conn , addr , finger , set_handler ) : <EOL> self . remote_addr = addr <EOL> self . remote_conn = conn <EOL> self . finger = finger <EOL> self . Node = None <EOL> self . set_handler = set_handler <EOL> self . recv_gen = self . recv_generator ( conn ) <EOL> self . send_queue = gevent . queue . Queue ( ) <EOL> self . host , self . port = addr_2_host_port ( addr ) <EOL> gevent . spawn ( self . local_handle ) <EOL> gevent . spawn ( self . net_handle ) <EOL> gevent . spawn ( self . check_alive ) <EOL> self . send ( '<STR_LIT>' + self . finger . self . uid ) <EOL> def check_alive ( self ) : <EOL> while True : <EOL> gevent . sleep ( <NUM_LIT> * <NUM_LIT:1> ) <EOL> if ( time . time ( ) - self . Node . last_seen ) > <NUM_LIT> : <EOL> self . send ( '<STR_LIT>' ) <EOL> if ( time . time ( ) - self . Node . last_seen ) > <NUM_LIT> * <NUM_LIT:5> : <EOL> if self . Node : <EOL> self . finger . remove ( self . Node ) <EOL> del self <EOL> return <EOL> def send ( self , msg ) : <EOL> self . send_queue . put ( msg ) <EOL> def recv_generator ( self , conn ) : <EOL> msg = '<STR_LIT>' <EOL> while True : <EOL> new_data = conn . recv ( <NUM_LIT:32> ) <EOL> if new_data == '<STR_LIT>' : <EOL> self . finger . remove ( self . Node ) <EOL> self . remote_conn . close ( ) <EOL> break <EOL> msg += new_data <EOL> if '<STR_LIT:|>' in msg : <EOL> length , remainder = msg . split ( '<STR_LIT:|>' , <NUM_LIT:1> ) <EOL> length = int ( length ) <EOL> if len ( remainder ) < length : <EOL> continue <EOL> yield remainder [ <NUM_LIT:0> : length ] <EOL> msg = remainder [ length : len ( remainder ) ] <EOL> def net_handle ( self ) : <EOL> "<STR_LIT>" <EOL> for msg in self . recv_gen : <EOL> self . net_msg_handle ( msg ) <EOL> def local_handle ( self ) : <EOL> "<STR_LIT>" <EOL> for item in self . send_queue : <EOL> self . net_msg_send ( item ) <EOL> def net_msg_send ( self , item ) : <EOL> "<STR_LIT>" <EOL> msg = str ( len ( item ) ) + '<STR_LIT:|>' + item <EOL> self . remote_conn . send ( msg ) <EOL> def net_msg_handle ( self , msg ) : <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:7> ] in [ '<STR_LIT>' ] : <EOL> _ , uid = msg . split ( '<STR_LIT:U+0020>' , <NUM_LIT:1> ) <EOL> if self . Node == None : <EOL> self . Node = Node ( uid , self . host , self . port , self ) <EOL> self . finger . add ( self . Node ) <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:6> ] in [ '<STR_LIT>' ] : <EOL> resp = '<STR_LIT>' + self . finger . self . uid <EOL> self . send ( resp ) <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:4> ] in [ '<STR_LIT>' ] : <EOL> self . send ( '<STR_LIT>' ) <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:4> ] in [ '<STR_LIT>' ] : <EOL> pass <EOL> if self . Node == None : <EOL> self . send ( '<STR_LIT>' ) <EOL> return <EOL> else : <EOL> self . Node . seen ( ) <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:9> ] in [ '<STR_LIT>' ] : <EOL> _ , level = msg . split ( '<STR_LIT:U+0020>' , <NUM_LIT:1> ) <EOL> node = self . finger . get_node_from_level ( int ( level ) , self . Node . uid ) <EOL> if node : <EOL> resp = '<STR_LIT>' + str ( node . uid ) + "<STR_LIT:U+0020>" + self . host + "<STR_LIT::>" + str ( self . port ) <EOL> self . send ( resp ) <EOL> if msg [ <NUM_LIT:0> : <NUM_LIT:10> ] in [ '<STR_LIT>' ] : <EOL> _ , uid , addr = msg . split ( '<STR_LIT:U+0020>' , <NUM_LIT:1> ) <EOL> Connect ( self . finger , self . set_handler , addr ) <EOL> self . set_handler . handle_msg ( self , msg ) <EOL> def __del__ ( self ) : <EOL> self . send_queue . put ( StopIteration ) <EOL> self . remote_conn . shutdown ( ) <EOL> self . remote_conn . close ( ) <EOL> class LoopBackProtocol ( Protocol ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , addr , finger , set_handler ) : <EOL> self . remote_addr = addr <EOL> self . finger = finger <EOL> self . Node = None <EOL> self . set_handler = set_handler <EOL> self . recv_gen = gevent . queue . Queue ( ) <EOL> self . send_queue = gevent . queue . Queue ( ) <EOL> self . host , self . port = addr_2_host_port ( addr ) <EOL> gevent . spawn ( self . local_handle ) <EOL> gevent . spawn ( self . net_handle ) <EOL> gevent . spawn ( self . check_alive ) <EOL> self . send ( '<STR_LIT>' + self . finger . self . uid ) <EOL> def net_msg_send ( self , item ) : <EOL> "<STR_LIT>" <EOL> self . recv_gen . put ( item ) <EOL> import unittest <EOL> class TestProtocol ( unittest . TestCase ) : <EOL> def testaddr ( self ) : <EOL> self . assertTrue ( addr_2_host_port ( "<STR_LIT>" ) == ( "<STR_LIT:127.0.0.1>" , <NUM_LIT> ) ) <EOL> self . assertTrue ( addr_2_host_port ( "<STR_LIT>" ) == ( "<STR_LIT>" , <NUM_LIT> ) ) <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> unittest . main ( ) </s>
