<s> import struct <EOL> import oppy . connection . definitions as CONN_DEFS <EOL> import oppy . cell . definitions as DEF <EOL> from oppy . cell . cell import Cell <EOL> from oppy . cell . exceptions import BadCellHeader , BadPayloadData <EOL> from oppy . cell . util import CertsCellPayloadItem <EOL> class VarLenCell ( Cell ) : <EOL> '''<STR_LIT>''' <EOL> _subclass_map = None <EOL> def __init__ ( self , header , payload = None ) : <EOL> '''<STR_LIT>''' <EOL> if not isinstance ( header , VarLenCell . Header ) : <EOL> msg = '<STR_LIT>' <EOL> msg += '<STR_LIT>' . format ( type ( header ) ) <EOL> raise BadCellHeader ( msg ) <EOL> self . header = header <EOL> self . payload = payload <EOL> def getBytes ( self , trimmed = False ) : <EOL> '''<STR_LIT>''' <EOL> return self . header . getBytes ( ) + self . payload <EOL> def _parseHeader ( self , data ) : <EOL> already_parsed = ( self . header . circ_id , <EOL> self . header . cmd , <EOL> self . header . link_version ) <EOL> for field in already_parsed : <EOL> assert field is not None <EOL> if self . header . link_version <= <NUM_LIT:3> : <EOL> start = DEF . PAYLOAD_START_V3 <EOL> else : <EOL> start = DEF . PAYLOAD_START_V4 <EOL> end = start + DEF . PAYLOAD_FIELD_LEN <EOL> length = struct . unpack ( "<STR_LIT>" , data [ start : end ] ) [ <NUM_LIT:0> ] <EOL> self . header . payload_len = length <EOL> def _parsePayload ( self , data ) : <EOL> start , end = self . payloadRange ( ) <EOL> self . payload = data [ start : end ] <EOL> def payloadRange ( self ) : <EOL> '''<STR_LIT>''' <EOL> circ_len = <NUM_LIT:2> if self . header . link_version <= <NUM_LIT:3> else <NUM_LIT:4> <EOL> start = circ_len + <NUM_LIT:1> + <NUM_LIT:2> <EOL> end = start + self . header . payload_len <EOL> return start , end <EOL> @ staticmethod <EOL> def _initSubclassMap ( ) : <EOL> VarLenCell . _subclass_map = { <EOL> DEF . VERSIONS_CMD : VersionsCell , <EOL> DEF . VPADDING_CMD : VPaddingCell , <EOL> DEF . CERTS_CMD : CertsCell , <EOL> DEF . AUTH_CHALLENGE_CMD : AuthChallengeCell , <EOL> DEF . AUTHENTICATE_CMD : AuthenticateCell , <EOL> DEF . AUTHORIZE_CMD : AuthorizeCell <EOL> } <EOL> class Header ( object ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , circ_id = None , cmd = None , payload_len = None , <EOL> link_version = <NUM_LIT:3> ) : <EOL> '''<STR_LIT>''' <EOL> self . circ_id = circ_id <EOL> self . cmd = cmd <EOL> self . payload_len = payload_len <EOL> self . link_version = link_version <EOL> def getBytes ( self ) : <EOL> '''<STR_LIT>''' <EOL> fmt = "<STR_LIT>" if self . link_version <= <NUM_LIT:3> else "<STR_LIT>" <EOL> return struct . pack ( fmt , self . circ_id , self . cmd , self . payload_len ) <EOL> def __repr__ ( self ) : <EOL> fmt = "<STR_LIT>" <EOL> fmt = "<STR_LIT>" . format ( fmt ) <EOL> return fmt . format ( self . circ_id , self . cmd , self . payload_len , <EOL> self . link_version ) <EOL> def __eq__ ( self , other ) : <EOL> if type ( self ) is type ( other ) : <EOL> return self . __dict__ == other . __dict__ <EOL> return False <EOL> CHALLENGE_LEN = <NUM_LIT:32> <EOL> N_METHODS_LEN = <NUM_LIT:2> <EOL> NUM_SUPPORTED_METHODS = <NUM_LIT:1> <EOL> SUPPORTED_METHODS = ( struct . pack ( '<STR_LIT>' , <NUM_LIT:1> ) , ) <EOL> class AuthChallengeCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , header , challenge = None , n_methods = None , methods = None ) : <EOL> '''<STR_LIT>''' <EOL> self . header = header <EOL> self . challenge = challenge <EOL> self . n_methods = n_methods <EOL> self . methods = methods <EOL> @ staticmethod <EOL> def make ( circ_id , challenge , methods , link_version = <NUM_LIT:3> ) : <EOL> AuthChallengeCell . _checkChallenge ( challenge ) <EOL> AuthChallengeCell . _checkNMethods ( len ( methods ) ) <EOL> AuthChallengeCell . _checkMethods ( methods ) <EOL> n_methods = len ( methods ) <EOL> payload_len = len ( challenge ) + N_METHODS_LEN + n_methods * <NUM_LIT:2> <EOL> h = VarLenCell . Header ( circ_id = circ_id , cmd = DEF . AUTH_CHALLENGE_CMD , <EOL> payload_len = payload_len , <EOL> link_version = link_version ) <EOL> return AuthChallengeCell ( h , challenge , n_methods , methods ) <EOL> def getBytes ( self , trimmed = False ) : <EOL> '''<STR_LIT>''' <EOL> ret = self . header . getBytes ( ) <EOL> ret += self . challenge <EOL> ret += struct . pack ( '<STR_LIT>' , self . n_methods ) <EOL> for method in self . methods : <EOL> ret += method <EOL> return ret <EOL> def _parsePayload ( self , data ) : <EOL> '''<STR_LIT>''' <EOL> start , end = self . payloadRange ( ) <EOL> offset = start <EOL> challenge = data [ offset : offset + CHALLENGE_LEN ] <EOL> offset += CHALLENGE_LEN <EOL> n_methods = data [ offset : offset + N_METHODS_LEN ] <EOL> n_methods = struct . unpack ( "<STR_LIT>" , n_methods ) [ <NUM_LIT:0> ] <EOL> offset += N_METHODS_LEN <EOL> methods = [ ] <EOL> for method in xrange ( n_methods ) : <EOL> methods . append ( data [ offset : offset + <NUM_LIT:2> ] ) <EOL> offset += <NUM_LIT:2> <EOL> AuthChallengeCell . _checkChallenge ( challenge ) <EOL> AuthChallengeCell . _checkNMethods ( len ( methods ) ) <EOL> AuthChallengeCell . _checkMethods ( methods ) <EOL> self . challenge = challenge <EOL> self . n_methods = n_methods <EOL> self . methods = methods <EOL> @ staticmethod <EOL> def _checkChallenge ( challenge ) : <EOL> if len ( challenge ) != CHALLENGE_LEN : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( CHALLENGE_LEN , len ( challenge ) ) ) <EOL> @ staticmethod <EOL> def _checkNMethods ( n_methods ) : <EOL> if n_methods != NUM_SUPPORTED_METHODS : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( NUM_SUPPORTED_METHODS , <EOL> n_methods ) ) <EOL> @ staticmethod <EOL> def _checkMethods ( methods ) : <EOL> for method in methods : <EOL> if len ( method ) != <NUM_LIT:2> : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( len ( method ) ) ) <EOL> if method not in SUPPORTED_METHODS : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( method , SUPPORTED_METHODS ) ) <EOL> def __repr__ ( self ) : <EOL> fmt = '<STR_LIT>' <EOL> fmt = '<STR_LIT>' . format ( fmt ) <EOL> return fmt . format ( repr ( self . header ) , repr ( self . challenge ) , <EOL> repr ( self . n_methods ) , repr ( self . methods ) ) <EOL> class AuthenticateCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , header ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> class AuthorizeCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , header ) : <EOL> raise NotImplementedError ( "<STR_LIT>" ) <EOL> NUM_CERT_LEN = <NUM_LIT:1> <EOL> CERT_TYPE_LEN = <NUM_LIT:1> <EOL> CERT_LEN_LEN = <NUM_LIT:2> <EOL> MAX_CERTS_PER_CELL = <NUM_LIT:3> <EOL> class CertsCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , header , num_certs = None , cert_payload_items = None ) : <EOL> '''<STR_LIT>''' <EOL> self . header = header <EOL> self . num_certs = num_certs <EOL> self . cert_payload_items = cert_payload_items <EOL> def getBytes ( self , trimmed = False ) : <EOL> '''<STR_LIT>''' <EOL> ret = self . header . getBytes ( ) <EOL> ret += struct . pack ( '<STR_LIT>' , self . num_certs ) <EOL> for cert_item in self . cert_payload_items : <EOL> ret += cert_item . getBytes ( ) <EOL> return ret <EOL> @ staticmethod <EOL> def make ( circ_id , cert_payload_items , link_version = <NUM_LIT:3> ) : <EOL> num_certs = len ( cert_payload_items ) <EOL> if num_certs > MAX_CERTS_PER_CELL : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( MAX_CERTS_PER_CELL , num_certs ) ) <EOL> payload_len = NUM_CERT_LEN <EOL> for cert_item in cert_payload_items : <EOL> payload_len += len ( cert_item ) <EOL> h = VarLenCell . Header ( circ_id = circ_id , cmd = DEF . CERTS_CMD , <EOL> payload_len = payload_len , <EOL> link_version = link_version ) <EOL> return CertsCell ( h , num_certs , cert_payload_items ) <EOL> def _parsePayload ( self , data ) : <EOL> '''<STR_LIT>''' <EOL> start , end = self . payloadRange ( ) <EOL> offset = start <EOL> if end - start < CERT_TYPE_LEN + CERT_LEN_LEN : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg ) <EOL> self . num_certs = struct . unpack ( '<STR_LIT>' , <EOL> data [ offset : offset + NUM_CERT_LEN ] ) [ <NUM_LIT:0> ] <EOL> offset += NUM_CERT_LEN <EOL> if self . num_certs > MAX_CERTS_PER_CELL : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg . format ( MAX_CERTS_PER_CELL , <EOL> self . num_certs ) ) <EOL> self . cert_payload_items = [ ] <EOL> try : <EOL> for i in xrange ( self . num_certs ) : <EOL> cert_payload_item = CertsCellPayloadItem . parse ( data , offset ) <EOL> offset += len ( cert_payload_item ) <EOL> self . cert_payload_items . append ( cert_payload_item ) <EOL> if offset > end : <EOL> raise IndexError <EOL> except IndexError : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> raise BadPayloadData ( msg ) <EOL> def __repr__ ( self ) : <EOL> fmt = '<STR_LIT>' <EOL> fmt = '<STR_LIT>' . format ( fmt ) <EOL> return fmt . format ( repr ( self . header ) , repr ( self . num_certs ) , <EOL> repr ( self . cert_payload_items ) ) <EOL> VERSIONS_LEN = <NUM_LIT:2> <EOL> class VersionsCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , header , versions = None ) : <EOL> '''<STR_LIT>''' <EOL> self . header = header <EOL> self . versions = versions <EOL> @ staticmethod <EOL> def make ( versions ) : <EOL> '''<STR_LIT>''' <EOL> for version in versions : <EOL> if version not in CONN_DEFS . SUPPORTED_LINK_PROTOCOLS : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" <EOL> msg = msg . format ( versions , CONN_DEFS . SUPPORTED_LINK_PROTOCOLS ) <EOL> raise BadPayloadData ( msg ) <EOL> h = VarLenCell . Header ( circ_id = <NUM_LIT:0> , cmd = DEF . VERSIONS_CMD , <EOL> payload_len = len ( versions ) * <NUM_LIT:2> , <EOL> link_version = <NUM_LIT:3> ) <EOL> return VersionsCell ( h , versions ) <EOL> def getBytes ( self , trimmed = False ) : <EOL> '''<STR_LIT>''' <EOL> ret = self . header . getBytes ( ) <EOL> for i in xrange ( len ( self . versions ) ) : <EOL> ret += struct . pack ( '<STR_LIT>' , self . versions [ i ] ) <EOL> return ret <EOL> def _parsePayload ( self , data ) : <EOL> '''<STR_LIT>''' <EOL> start , end = self . payloadRange ( ) <EOL> offset = start <EOL> self . versions = [ ] <EOL> while offset < end : <EOL> v = struct . unpack ( '<STR_LIT>' , data [ offset : offset + VERSIONS_LEN ] ) [ <NUM_LIT:0> ] <EOL> if v not in CONN_DEFS . KNOWN_LINK_PROTOCOLS : <EOL> msg = "<STR_LIT>" <EOL> msg += "<STR_LIT>" . format ( v ) <EOL> raise BadPayloadData ( msg ) <EOL> self . versions . append ( v ) <EOL> offset += VERSIONS_LEN <EOL> def __repr__ ( self ) : <EOL> fmt = '<STR_LIT>' <EOL> fmt = '<STR_LIT>' . format ( fmt ) <EOL> return fmt . format ( repr ( self . header ) , repr ( self . versions ) ) <EOL> class VPaddingCell ( VarLenCell ) : <EOL> '''<STR_LIT>''' <EOL> @ staticmethod <EOL> def make ( circ_id , padding_len , link_version = <NUM_LIT:3> ) : <EOL> '''<STR_LIT>''' <EOL> h = VarLenCell . Header ( circ_id = circ_id , cmd = DEF . VPADDING_CMD , <EOL> payload_len = padding_len , <EOL> link_version = link_version ) <EOL> return VPaddingCell ( h , payload = "<STR_LIT:\x00>" * padding_len ) </s>
