#NEWLINE# def do_socks_handshake( self , addr , callback , error_callback = None , auth = None ) : #NEWLINE# #INDENT# "\n    Perform a SOCKSv5 handshake, and call callback when it's completed. If\n    authorization data is provided, we'll log onto the server too.\n\n    ===============  ============\n    Argument         Description\n    ===============  ============\n    addr             The address for the proxy server to connect to. This must be a tuple of ``(hostname, port)``.\n    callback         A function to call when the handshake has completed.\n    error_callback   *Optional.* A function to be called if the handshake has failed.\n    auth             *Optional.* If provided, it must be a tuple of ``(username, password)``.\n    ===============  ============\n    " #NEWLINE# if ( not error_callback . connected ) : #NEWLINE# #INDENT# raise RuntimeError ( ( 'Tried to start SOCKS handshake on disconnected %r.' % self ) ) #NEWLINE# #UNINDENT# def on_read( data ) : #NEWLINE# #INDENT# if ( not self . _socks_state ) : #NEWLINE# #INDENT# if ( data [ 0 ] != SOCKS_VERSION ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , BadVersion ( ( 'Expected version 5, got %d.' % ord ( data [ 0 ] ) ) ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( ( auth and ( data [ 1 ] != '\x02' ) ) or ( ( not auth ) and ( data [ 1 ] != '\x00' ) ) ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , NoAuthenticationMethods ( ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# #UNINDENT# if auth : #NEWLINE# #INDENT# self . write ( ( '\x01%d%s%d%s' % ( len ( auth [ 0 ] ) , auth [ 0 ] , len ( auth [ 1 ] ) , auth [ 1 ] ) ) ) #NEWLINE# self . _socks_state = 1 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# self . _socks_state = 1 #NEWLINE# self . on_read ( ( '%s\x00' % SOCKS_VERSION ) ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( self . _socks_state == 1 ) : #NEWLINE# #INDENT# if ( data [ 0 ] != SOCKS_VERSION ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , BadVersion ( ( 'Expected version 5, got %d.' % ord ( data [ 0 ] ) ) ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( data [ 1 ] != '\x00' ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , Unauthorized ( data [ 1 ] ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# #UNINDENT# self . write ( ( '%s\x01\x00\x03%s%s%s' % ( SOCKS_VERSION , chr ( len ( addr [ 0 ] ) ) , addr [ 0 ] , struct . pack ( '!H' , addr [ 1 ] ) ) ) ) #NEWLINE# self . _socks_state = 2 #NEWLINE# self . read_delimiter = 4 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( self . _socks_state == 2 ) : #NEWLINE# #INDENT# if ( data [ 0 ] != SOCKS_VERSION ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , BadVersion ( ( 'Expected version 5, got %d.' % ord ( data [ 0 ] ) ) ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( data [ 1 ] != '\x00' ) : #NEWLINE# #INDENT# if error_callback : #NEWLINE# #INDENT# self . _safely_call ( error_callback , Exception ( data [ 1 ] ) ) #NEWLINE# #UNINDENT# self . close ( False ) #NEWLINE# return #NEWLINE# #UNINDENT# #UNINDENT# self . _socks_state = 4 #NEWLINE# if ( data [ 3 ] == '\x01' ) : #NEWLINE# #INDENT# self . _socks_fam = 1 #NEWLINE# self . read_delimiter = 4 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( data [ 3 ] == '\x03' ) : #NEWLINE# #INDENT# self . _socks_state = 3 #NEWLINE# self . read_delimiter = 1 #NEWLINE# self . _socks_fam = 0 #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( data [ 3 ] == '\x04' ) : #NEWLINE# #INDENT# self . read_delimiter = 16 #NEWLINE# self . _socks_fam = 2 #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# self . _socks_port = struct . unpack ( '!H' , data [ ( - 2 ) : ] ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( self . _socks_state == 3 ) : #NEWLINE# #INDENT# if ( self . read_delimiter == 1 ) : #NEWLINE# #INDENT# self . _socks_state = 4 #NEWLINE# self . read_delimiter = ord ( data [ 0 ] ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# if ( self . _socks_state == 4 ) : #NEWLINE# #INDENT# if ( self . _socks_fam == 1 ) : #NEWLINE# #INDENT# data = socket . inet_ntop ( socket . AF_INET , data ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( self . _socks_fam == 2 ) : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# data = socket . inet_ntop ( socket . AF_INET6 , data ) #NEWLINE# #UNINDENT# except ( AttributeError , socket . error ) : #NEWLINE# #INDENT# pass #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# self . remote_address = ( data , self . _socks_port ) #NEWLINE# self . on_read = self . _socks_read #NEWLINE# self . read_delimiter = self . _socks_delim #NEWLINE# del self . _socks_read #NEWLINE# del self . _socks_delim #NEWLINE# del self . _socks_port #NEWLINE# del self . _socks_state #NEWLINE# del self . _socks_fam #NEWLINE# self . _safely_call ( callback ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# self . _socks_state = 0 #NEWLINE# self . write ( ( '%s\x01%s' % ( SOCKS_VERSION , ( '\x02' if auth else '\x00' ) ) ) ) #NEWLINE# self . _socks_read = self . on_read #NEWLINE# self . _socks_delim = self . read_delimiter #NEWLINE# self . on_read = on_read #NEWLINE# self . read_delimiter = 2