<s> """<STR_LIT>""" <EOL> import logging <EOL> import socket <EOL> import time <EOL> from cryptography . hazmat . backends import default_backend <EOL> from cryptography . hazmat . primitives import ciphers <EOL> from cryptography . hazmat . primitives . ciphers import algorithms , modes <EOL> from spockbot . mcp import mcpacket , proto <EOL> from spockbot . mcp . bbuff import BoundBuffer , BufferUnderflowException <EOL> from spockbot . plugins . base import PluginBase , pl_announce <EOL> logger = logging . getLogger ( '<STR_LIT>' ) <EOL> backend = default_backend ( ) <EOL> class AESCipher ( object ) : <EOL> def __init__ ( self , shared_secret ) : <EOL> cipher = ciphers . Cipher ( algorithms . AES ( shared_secret ) , <EOL> modes . CFB8 ( shared_secret ) , backend ) <EOL> self . encryptifier = cipher . encryptor ( ) <EOL> self . decryptifier = cipher . decryptor ( ) <EOL> def encrypt ( self , data ) : <EOL> return self . encryptifier . update ( data ) <EOL> def decrypt ( self , data ) : <EOL> return self . decryptifier . update ( data ) <EOL> class NetCore ( object ) : <EOL> def __init__ ( self , sock , event , select ) : <EOL> self . sock = sock <EOL> self . event = event <EOL> self . select = select <EOL> self . host = None <EOL> self . port = None <EOL> self . connected = False <EOL> self . encrypted = False <EOL> self . proto_state = proto . HANDSHAKE_STATE <EOL> self . comp_state = proto . PROTO_COMP_OFF <EOL> self . comp_threshold = - <NUM_LIT:1> <EOL> self . sbuff = b'<STR_LIT>' <EOL> self . rbuff = BoundBuffer ( ) <EOL> def reset ( self , sock ) : <EOL> self . __init__ ( sock , self . event , self . select ) <EOL> def connect ( self , host = '<STR_LIT:localhost>' , port = <NUM_LIT> ) : <EOL> self . host = host <EOL> self . port = port <EOL> try : <EOL> logger . debug ( '<STR_LIT>' , <EOL> host , port ) <EOL> self . sock . setblocking ( True ) <EOL> self . sock . connect ( ( host , port ) ) <EOL> self . sock . setblocking ( False ) <EOL> self . connected = True <EOL> self . event . emit ( '<STR_LIT>' , ( host , port ) ) <EOL> logger . debug ( '<STR_LIT>' , host , port ) <EOL> except socket . error as error : <EOL> logger . error ( '<STR_LIT>' ) <EOL> self . event . emit ( '<STR_LIT>' , error ) <EOL> def set_proto_state ( self , state ) : <EOL> self . proto_state = state <EOL> self . event . emit ( proto . state_lookup [ state ] + '<STR_LIT>' ) <EOL> def set_comp_state ( self , threshold ) : <EOL> self . comp_threshold = threshold <EOL> if threshold >= <NUM_LIT:0> : <EOL> self . comp_state = proto . PROTO_COMP_ON <EOL> def push ( self , packet ) : <EOL> data = packet . encode ( self . comp_state , self . comp_threshold ) <EOL> self . sbuff += ( self . cipher . encrypt ( data ) if self . encrypted else data ) <EOL> self . event . emit ( packet . ident , packet ) <EOL> self . event . emit ( packet . str_ident , packet ) <EOL> self . select . schedule_sending ( self . sock ) <EOL> def push_packet ( self , ident , data ) : <EOL> self . push ( mcpacket . Packet ( ident , data ) ) <EOL> def read_packet ( self , data = b'<STR_LIT>' ) : <EOL> self . rbuff . append ( <EOL> self . cipher . decrypt ( data ) if self . encrypted else data ) <EOL> while self . rbuff : <EOL> self . rbuff . save ( ) <EOL> try : <EOL> packet = mcpacket . Packet ( ident = ( <EOL> self . proto_state , <EOL> proto . SERVER_TO_CLIENT <EOL> ) ) . decode ( self . rbuff , self . comp_state ) <EOL> except BufferUnderflowException : <EOL> self . rbuff . revert ( ) <EOL> break <EOL> except mcpacket . PacketDecodeFailure as err : <EOL> logger . warning ( '<STR_LIT>' ) <EOL> logger . warning ( <EOL> '<STR_LIT>' , <EOL> err . packet . str_ident <EOL> ) <EOL> self . event . emit ( '<STR_LIT>' , err ) <EOL> break <EOL> self . event . emit ( packet . ident , packet ) <EOL> self . event . emit ( packet . str_ident , packet ) <EOL> def enable_crypto ( self , secret_key ) : <EOL> self . cipher = AESCipher ( secret_key ) <EOL> self . encrypted = True <EOL> def disable_crypto ( self ) : <EOL> self . cipher = None <EOL> self . encrypted = False <EOL> @ pl_announce ( '<STR_LIT>' ) <EOL> class NetPlugin ( PluginBase ) : <EOL> requires = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ) <EOL> defaults = { <EOL> '<STR_LIT>' : <NUM_LIT> , <EOL> '<STR_LIT>' : True , <EOL> } <EOL> events = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> } <EOL> def __init__ ( self , ploader , settings ) : <EOL> super ( NetPlugin , self ) . __init__ ( ploader , settings ) <EOL> self . bufsize = self . settings [ '<STR_LIT>' ] <EOL> self . sock_quit = self . settings [ '<STR_LIT>' ] <EOL> self . sock = None <EOL> self . net = NetCore ( self . sock , self . event , self . select ) <EOL> self . reset_sock ( ) <EOL> self . sock_dead = False <EOL> ploader . provides ( '<STR_LIT>' , self . net ) <EOL> def tick ( self , name , data ) : <EOL> if self . net . connected : <EOL> self . net . select . poll ( ) <EOL> else : <EOL> timeout = self . timers . get_timeout ( ) <EOL> if timeout == - <NUM_LIT:1> : <EOL> time . sleep ( <NUM_LIT:1> ) <EOL> else : <EOL> time . sleep ( timeout ) <EOL> def handle_recv ( self , name , fileno ) : <EOL> """<STR_LIT>""" <EOL> if self . net . connected and fileno == self . net . sock . fileno ( ) : <EOL> try : <EOL> data = self . sock . recv ( self . bufsize ) <EOL> if not data : <EOL> self . event . emit ( '<STR_LIT>' ) <EOL> return <EOL> self . net . read_packet ( data ) <EOL> except socket . error as error : <EOL> self . event . emit ( '<STR_LIT>' , error ) <EOL> def handle_send ( self , name , fileno ) : <EOL> """<STR_LIT>""" <EOL> if self . net . connected and fileno == self . net . sock . fileno ( ) : <EOL> try : <EOL> sent = self . sock . send ( self . net . sbuff ) <EOL> self . net . sbuff = self . net . sbuff [ sent : ] <EOL> if self . net . sbuff : <EOL> self . net . select . schedule_sending ( self . sock ) <EOL> except socket . error as error : <EOL> self . event . emit ( '<STR_LIT>' , error ) <EOL> def handle_select_err ( self , name , fileno ) : <EOL> if self . net . connected and fileno == self . net . sock . fileno ( ) : <EOL> self . event . emit ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def handle_err ( self , name , error ) : <EOL> """<STR_LIT>""" <EOL> logger . error ( '<STR_LIT>' , error ) <EOL> self . reset_sock ( ) <EOL> self . event . emit ( '<STR_LIT>' , error ) <EOL> self . check_quit ( ) <EOL> def handle_hup ( self , name , data ) : <EOL> """<STR_LIT>""" <EOL> logger . error ( '<STR_LIT>' ) <EOL> self . reset_sock ( ) <EOL> self . event . emit ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . check_quit ( ) <EOL> def reset_sock ( self ) : <EOL> if self . sock : <EOL> self . sock . close ( ) <EOL> self . sock = socket . socket ( socket . AF_INET , socket . SOCK_STREAM ) <EOL> self . net . select . register_socket ( self . sock ) <EOL> self . net . reset ( self . sock ) <EOL> def check_quit ( self ) : <EOL> if self . sock_quit and not self . event . kill_event : <EOL> self . sock_dead = True <EOL> self . event . kill ( ) <EOL> def handle_handshake ( self , name , packet ) : <EOL> """<STR_LIT>""" <EOL> self . net . set_proto_state ( packet . data [ '<STR_LIT>' ] ) <EOL> def handle_login_success ( self , name , packet ) : <EOL> """<STR_LIT>""" <EOL> self . net . set_proto_state ( proto . PLAY_STATE ) <EOL> def handle_comp ( self , name , packet ) : <EOL> """<STR_LIT>""" <EOL> self . net . set_comp_state ( packet . data [ '<STR_LIT>' ] ) <EOL> def handle_disconnect ( self , name , packet ) : <EOL> logger . debug ( '<STR_LIT>' , packet . data [ '<STR_LIT>' ] ) <EOL> self . event . emit ( '<STR_LIT>' , packet . data [ '<STR_LIT>' ] ) <EOL> def handle_login_disconnect ( self , name , packet ) : <EOL> reason = packet . data . get ( '<STR_LIT>' , { } ) . get ( '<STR_LIT:text>' , '<STR_LIT>' ) <EOL> logger . debug ( "<STR_LIT>" , reason ) <EOL> self . event . emit ( '<STR_LIT>' , reason ) <EOL> def handle_kill ( self , name , data ) : <EOL> """<STR_LIT>""" <EOL> if self . net . connected : <EOL> logger . debug ( '<STR_LIT>' ) <EOL> if not self . sock_dead : <EOL> self . sock . shutdown ( socket . SHUT_WR ) <EOL> self . sock . close ( ) <EOL> self . net . select . unregister_socket ( self . net . sock ) </s>
