<s> """<STR_LIT>""" <EOL> from __future__ import absolute_import <EOL> import time <EOL> from . import state , xml , xmppstream , features , interfaces as i <EOL> from . prelude import * <EOL> try : <EOL> import ssl <EOL> except ImportError : <EOL> ssl = None <EOL> __all__ = ( <EOL> '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' <EOL> ) <EOL> class Core ( i . CoreInterface ) : <EOL> def __init__ ( self , stream , jid , features = None , plugins = None , lang = '<STR_LIT>' ) : <EOL> self . stream = stream . read ( self . _read ) <EOL> self . serverJID = jid <EOL> self . lang = lang <EOL> self . state = state . State ( self , plugins ) <EOL> self . parser = xml . Parser ( xmppstream . XMPPTarget ( self ) ) . start ( ) <EOL> self . E = xml . ElementMaker ( namespace = self . __xmlns__ , nsmap = self . nsmap ) <EOL> self . install_features ( features ) <EOL> self . _reset ( ) <EOL> self . closed = False <EOL> self . stream . on_close ( self . handle_stream_closed ) <EOL> def __repr__ ( self ) : <EOL> peer = self . stream and self . stream . socket and self . stream . socket . getpeername ( ) <EOL> return '<STR_LIT>' % ( type ( self ) . __name__ , peer ) <EOL> __xmlns__ = property ( lambda s : s . state . plugins . __xmlns__ ) <EOL> nsmap = property ( lambda s : s . state . plugins . nsmap ) <EOL> def initiate ( self ) : <EOL> """<STR_LIT>""" <EOL> def listen ( self ) : <EOL> """<STR_LIT>""" <EOL> ( self . state <EOL> . bind_stanza ( self . ERROR , self . handle_stream_error ) <EOL> . bind_stanza ( '<STR_LIT>' , self . info_query ) <EOL> . one ( features . StreamSecured , self . on_stream_secured ) <EOL> . one ( features . StreamAuthorized , self . on_stream_authorized ) <EOL> . one ( features . StreamBound , self . on_stream_bound ) ) <EOL> return self <EOL> def activate ( self ) : <EOL> """<STR_LIT>""" <EOL> self . parser . stop_tokenizing ( ) <EOL> self . state . activate ( ) <EOL> return self <EOL> def on_stream_secured ( self , tls ) : <EOL> self . secured = True <EOL> def on_stream_authorized ( self , auth ) : <EOL> self . authJID = auth . jid <EOL> def on_stream_bound ( self , bindings ) : <EOL> self . authJID = bindings . jid <EOL> self . resources = bindings . resources <EOL> def add_timeout ( self , delay , callback ) : <EOL> self . stream . io . add_timeout ( time . time ( ) + delay , callback ) <EOL> return self <EOL> def remove_timeout ( self , callback ) : <EOL> self . stream . io . remove_timeout ( callback ) <EOL> return self <EOL> def is_stanza ( self , name ) : <EOL> return self . state . is_stanza ( name ) <EOL> def handle_open_stream ( self , attr ) : <EOL> self . state . trigger ( ReceivedOpenStream , attr ) <EOL> def handle_stanza ( self , elem ) : <EOL> self . state . trigger_stanza ( elem . tag , elem ) <EOL> def handle_close_stream ( self ) : <EOL> self . state . trigger ( ReceivedCloseStream ) <EOL> self . close ( ) <EOL> def handle_stream_closed ( self ) : <EOL> if self . closed : <EOL> return <EOL> self . root = None <EOL> self . close ( ) <EOL> STREAM = '<STR_LIT>' <EOL> LANG = '<STR_LIT>' <EOL> @ abc . abstractmethod <EOL> def make_stream ( self ) : <EOL> """<STR_LIT>""" <EOL> def close ( self ) : <EOL> if self . stream : <EOL> if self . root is not None : <EOL> self . close_stream ( ) <EOL> self . state . run ( self . _close ) <EOL> def writer ( method ) : <EOL> """<STR_LIT>""" <EOL> @ wraps ( method ) <EOL> def queue_write ( self , * args , ** kwargs ) : <EOL> self . state . run ( method , self , * args , ** kwargs ) <EOL> return self <EOL> return queue_write <EOL> @ writer <EOL> def write ( self , data , * args ) : <EOL> if self . root is None : <EOL> return <EOL> if xml . is_element ( data ) : <EOL> data = xml . stanza_tostring ( self . root , data ) <EOL> self . stream . write ( data , * args ) <EOL> @ writer <EOL> def open_stream ( self , * args ) : <EOL> if self . root is None : <EOL> self . root = self . make_stream ( ) <EOL> self . stream . write ( xml . open_tag ( self . root ) , * args ) <EOL> self . state . trigger ( SentOpenStream ) <EOL> @ writer <EOL> def reset ( self , clear_events = False ) : <EOL> if self . stream : <EOL> self . _reset ( clear_events ) <EOL> @ writer <EOL> def close_stream ( self , * args ) : <EOL> if self . root is not None : <EOL> self . stream . write ( xml . close_tag ( self . root ) , * args ) <EOL> self . root = None <EOL> self . state . trigger ( SentCloseStream ) <EOL> del writer <EOL> ERROR = '<STR_LIT>' <EOL> ERROR_NS = '<STR_LIT>' <EOL> TEXT = '<STR_LIT>' % ERROR_NS <EOL> def stream_error ( self , name , text = None , exc = None ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> log . error ( '<STR_LIT>' % ( name , text ) , exc_info = bool ( exc ) ) <EOL> with self . state . clear ( ) . lock ( ) : <EOL> self . open_stream ( ) <EOL> elem = self . E ( self . ERROR , self . E ( name , xmlns = self . ERROR_NS ) ) <EOL> if text is not None : <EOL> elem . append ( self . E . text ( <EOL> { self . LANG : '<STR_LIT>' , '<STR_LIT>' : self . ERROR_NS } , <EOL> text <EOL> ) ) <EOL> self . write ( elem ) <EOL> except : <EOL> log . exception ( '<STR_LIT>' ) <EOL> try : <EOL> self . close ( ) <EOL> except : <EOL> log . exception ( '<STR_LIT>' ) <EOL> return self <EOL> def handle_stream_error ( self , elem ) : <EOL> """<STR_LIT>""" <EOL> log . error ( '<STR_LIT>' % ( <EOL> xml . tag ( xml . child ( elem , <NUM_LIT:0> ) , '<STR_LIT>' ) , <EOL> xml . text ( xml . child ( elem , self . TEXT ) , '<STR_LIT>' ) <EOL> ) ) <EOL> with self . state . clear ( ) . lock ( ) : <EOL> self . close ( ) <EOL> def stanza_error ( self , elem , kind , condition , text = None ) : <EOL> """<STR_LIT>""" <EOL> error = self . E . error ( type = kind ) <EOL> error . append ( self . E ( condition , { '<STR_LIT>' : self . STANZAS } ) ) <EOL> if text : <EOL> error . append ( self . E . text ( { '<STR_LIT>' : self . STANZAS } , text ) ) <EOL> reply_info = { <EOL> '<STR_LIT:type>' : '<STR_LIT:error>' , <EOL> '<STR_LIT:id>' : elem . get ( '<STR_LIT:id>' ) <EOL> } <EOL> if ( elem . get ( '<STR_LIT:to>' ) != None ) : <EOL> reply_info [ '<STR_LIT>' ] = elem . get ( '<STR_LIT:to>' ) <EOL> stanza = self . E ( elem . tag , reply_info ) <EOL> if len ( elem ) > <NUM_LIT:0> : <EOL> stanza . append ( elem [ <NUM_LIT:0> ] ) <EOL> stanza . append ( error ) <EOL> return self . write ( stanza ) <EOL> FEATURES = '<STR_LIT>' <EOL> def install_features ( self , features = None ) : <EOL> self . secured = False <EOL> self . authJID = None <EOL> self . resources = None <EOL> self . features = features . install ( self . state ) if features else ( ) <EOL> return self <EOL> def send_features ( self ) : <EOL> possible = self . features and self . features . include ( ) <EOL> self . write ( self . E ( self . FEATURES , * filter ( xml . is_element , possible ) ) ) <EOL> return self . authJID is None <EOL> def wait_for_features ( self ) : <EOL> active = dict ( self . features and self . features . active ( ) ) <EOL> self . state . bind_stanza ( self . FEATURES , partial ( self . negotiate , active ) ) <EOL> return self . authJID is None <EOL> def negotiate ( self , active , elem ) : <EOL> stop_after_first = self . authJID is None <EOL> for clause in elem : <EOL> feature = active . get ( clause . tag ) <EOL> if feature and feature . active ( ) : <EOL> feature . reply ( clause ) <EOL> if stop_after_first : break <EOL> return self <EOL> def use_tls ( self ) : <EOL> return bool ( ssl and self . stream . socket ) <EOL> def starttls ( self , callback , ** options ) : <EOL> self . stream . starttls ( callback , ** options ) <EOL> return self <EOL> STANZAS = '<STR_LIT>' <EOL> def info_query ( self , elem ) : <EOL> if not self . authJID : <EOL> return self . stream_error ( '<STR_LIT>' ) <EOL> kind = elem . get ( '<STR_LIT:type>' ) <EOL> if kind == '<STR_LIT:error>' : <EOL> log . exception ( '<STR_LIT>' , xml . tostring ( elem ) ) <EOL> return <EOL> if kind == '<STR_LIT:result>' : <EOL> name = self . iq_ident ( elem ) <EOL> else : <EOL> child = xml . child ( elem ) <EOL> if child is None : <EOL> log . exception ( '<STR_LIT>' % xml . tostring ( elem ) ) <EOL> return self . stanza_error ( <EOL> elem , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> ) <EOL> name = '<STR_LIT>' % child . tag <EOL> try : <EOL> self . state . trigger_stanza ( name , elem ) <EOL> except i . StreamError as exc : <EOL> log . debug ( <EOL> '<STR_LIT>' , name , <EOL> exc_info = True <EOL> ) <EOL> self . stanza_error ( elem , '<STR_LIT>' , '<STR_LIT>' ) <EOL> def iq ( self , kind , elem_or_callback , * data ) : <EOL> if xml . is_element ( elem_or_callback ) : <EOL> if ( not elem_or_callback . get ( '<STR_LIT:id>' ) ) : <EOL> id = make_nonce ( ) <EOL> else : <EOL> id = elem_or_callback . get ( '<STR_LIT:id>' ) <EOL> return self . iq_send ( kind , id , * data ) <EOL> return self . iq_send ( kind , self . iq_bind ( elem_or_callback ) , * data ) <EOL> def iq_bind ( self , callback ) : <EOL> ident = make_nonce ( ) <EOL> self . state . one_stanza ( self . iq_ident ( ident ) , callback , replace = False ) <EOL> return ident <EOL> def iq_ident ( self , ident ) : <EOL> if xml . is_element ( ident ) : <EOL> ident = ident . get ( '<STR_LIT:id>' ) <EOL> return '<STR_LIT>' % ident <EOL> def iq_send ( self , kind , ident , * data ) : <EOL> return self . write ( self . E . iq ( <EOL> { '<STR_LIT:id>' : ident , '<STR_LIT:type>' : kind } , <EOL> * data <EOL> ) ) <EOL> def routes ( self , jid ) : <EOL> if self . resources is None : <EOL> raise state . NoRoute ( jid ) <EOL> return self . resources . routes ( xml . jid ( jid ) ) <EOL> def _read ( self , data ) : <EOL> if not self . stream : <EOL> return <EOL> try : <EOL> self . parser . feed ( data ) <EOL> except i . StreamError as exc : <EOL> self . stream_error ( exc . condition , exc . text , exc ) <EOL> except xml . XMLSyntaxError as exc : <EOL> self . stream_error ( '<STR_LIT>' , str ( exc ) , exc ) <EOL> except Exception as exc : <EOL> self . stream_error ( '<STR_LIT>' , str ( exc ) , exc ) <EOL> def _reset ( self , clear_events = False ) : <EOL> self . state . reset ( clear_events ) <EOL> self . root = None <EOL> self . listen ( ) <EOL> self . parser . reset ( ) <EOL> self . initiate ( ) <EOL> return self <EOL> def _close ( self ) : <EOL> self . closed = True <EOL> if self . stream : <EOL> try : <EOL> self . state . trigger ( StreamClosed ) . flush ( True ) . clear ( ) <EOL> self . stream . shutdown ( ) <EOL> finally : <EOL> self . stream = None <EOL> class SentOpenStream ( i . Event ) : <EOL> """<STR_LIT>""" <EOL> class SentCloseStream ( i . Event ) : <EOL> """<STR_LIT>""" <EOL> class ReceivedOpenStream ( i . Event ) : <EOL> """<STR_LIT>""" <EOL> class ReceivedCloseStream ( i . Event ) : <EOL> """<STR_LIT>""" <EOL> class StreamClosed ( i . Event ) : <EOL> """<STR_LIT>""" <EOL> class ClientCore ( Core ) : <EOL> def handle_open_stream ( self , attr ) : <EOL> self . id = attr . get ( '<STR_LIT:id>' ) <EOL> self . state . trigger ( ReceivedOpenStream ) . run ( self . _opened ) <EOL> def _opened ( self ) : <EOL> self . state . one ( features . SessionStarted , thunk ( self . activate ) ) <EOL> self . wait_for_features ( ) <EOL> def make_stream ( self ) : <EOL> return self . E ( self . STREAM , { <EOL> '<STR_LIT:to>' : unicode ( self . serverJID ) , <EOL> self . LANG : self . lang , <EOL> '<STR_LIT:version>' : '<STR_LIT:1.0>' <EOL> } ) <EOL> def initiate ( self ) : <EOL> self . open_stream ( ) <EOL> class ServerCore ( Core ) : <EOL> def handle_open_stream ( self , attr ) : <EOL> self . state . trigger ( ReceivedOpenStream ) . run ( self . _opened ) <EOL> def _opened ( self ) : <EOL> self . open_stream ( ) <EOL> if not self . send_features ( ) : <EOL> self . state . one ( features . SessionStarted , thunk ( self . activate ) ) <EOL> pass <EOL> def handle_stanza ( self , elem ) : <EOL> if self . authJID : <EOL> if not elem . get ( '<STR_LIT>' ) : <EOL> elem . set ( '<STR_LIT>' , unicode ( self . authJID ) ) <EOL> self . state . trigger_stanza ( elem . tag , elem ) <EOL> def handle_close_stream ( self ) : <EOL> self . state . trigger ( ReceivedCloseStream ) <EOL> self . close ( ) <EOL> def close ( self ) : <EOL> if self . stream : <EOL> if self . root is not None : <EOL> self . close_stream ( self . _close ) <EOL> else : <EOL> self . state . run ( self . _close ) <EOL> def make_stream ( self ) : <EOL> self . id = make_nonce ( ) <EOL> return self . E ( self . STREAM , { <EOL> '<STR_LIT>' : unicode ( self . serverJID ) , <EOL> '<STR_LIT:id>' : self . id , <EOL> self . LANG : self . lang , <EOL> '<STR_LIT:version>' : '<STR_LIT:1.0>' <EOL> } ) <EOL> def make_nonce ( ) : <EOL> import random , hashlib <EOL> random . seed ( ) <EOL> return hashlib . md5 ( str ( random . getrandbits ( <NUM_LIT:64> ) ) ) . hexdigest ( ) </s>
