<s> """<STR_LIT>""" <EOL> from __future__ import print_function <EOL> from __future__ import division <EOL> from time import time <EOL> from collections import deque <EOL> from twisted . internet import reactor <EOL> from django . conf import settings <EOL> from evennia . server . sessionhandler import SessionHandler , PCONN , PDISCONN , PCONNSYNC <EOL> _MOD_IMPORT = None <EOL> _MAX_CONNECTION_RATE = float ( settings . MAX_CONNECTION_RATE ) <EOL> _MAX_COMMAND_RATE = float ( settings . MAX_COMMAND_RATE ) <EOL> _MIN_TIME_BETWEEN_CONNECTS = <NUM_LIT:1.0> / float ( settings . MAX_CONNECTION_RATE ) <EOL> _ERROR_COMMAND_OVERFLOW = settings . COMMAND_RATE_WARNING <EOL> _CONNECTION_QUEUE = deque ( ) <EOL> class PortalSessionHandler ( SessionHandler ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( PortalSessionHandler , self ) . __init__ ( * args , ** kwargs ) <EOL> self . portal = None <EOL> self . latest_sessid = <NUM_LIT:0> <EOL> self . uptime = time ( ) <EOL> self . connection_time = <NUM_LIT:0> <EOL> self . connection_last = time ( ) <EOL> self . connection_task = None <EOL> self . command_counter = <NUM_LIT:0> <EOL> self . command_counter_reset = time ( ) <EOL> self . command_overflow = False <EOL> def at_server_connection ( self ) : <EOL> """<STR_LIT>""" <EOL> self . connection_time = time ( ) <EOL> def connect ( self , session ) : <EOL> """<STR_LIT>""" <EOL> global _CONNECTION_QUEUE <EOL> if session : <EOL> self . latest_sessid += <NUM_LIT:1> <EOL> session . sessid = self . latest_sessid <EOL> session . server_connected = False <EOL> _CONNECTION_QUEUE . appendleft ( session ) <EOL> if len ( _CONNECTION_QUEUE ) > <NUM_LIT:1> : <EOL> session . data_out ( "<STR_LIT>" % ( <EOL> settings . SERVERNAME , <EOL> len ( _CONNECTION_QUEUE ) * _MIN_TIME_BETWEEN_CONNECTS ) ) <EOL> now = time ( ) <EOL> if ( now - self . connection_last < _MIN_TIME_BETWEEN_CONNECTS ) or not self . portal . amp_protocol : <EOL> if not session or not self . connection_task : <EOL> self . connection_task = reactor . callLater ( _MIN_TIME_BETWEEN_CONNECTS , self . connect , None ) <EOL> self . connection_last = now <EOL> return <EOL> elif not session : <EOL> if _CONNECTION_QUEUE : <EOL> self . connection_task = reactor . callLater ( _MIN_TIME_BETWEEN_CONNECTS , self . connect , None ) <EOL> else : <EOL> self . connection_task = None <EOL> self . connection_last = now <EOL> if _CONNECTION_QUEUE : <EOL> session = _CONNECTION_QUEUE . pop ( ) <EOL> sessdata = session . get_sync_data ( ) <EOL> self [ session . sessid ] = session <EOL> session . server_connected = True <EOL> self . portal . amp_protocol . send_AdminPortal2Server ( session , <EOL> operation = PCONN , <EOL> sessiondata = sessdata ) <EOL> def sync ( self , session ) : <EOL> """<STR_LIT>""" <EOL> if session . sessid and session . server_connected : <EOL> sessdata = session . get_sync_data ( ) <EOL> if self . portal . amp_protocol : <EOL> sessdata = dict ( ( key , val ) for key , val in sessdata . items ( ) if key in ( "<STR_LIT>" , <EOL> "<STR_LIT:address>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , ) ) <EOL> self . portal . amp_protocol . send_AdminPortal2Server ( session , <EOL> operation = PCONNSYNC , <EOL> sessiondata = sessdata ) <EOL> def disconnect ( self , session ) : <EOL> """<STR_LIT>""" <EOL> global _CONNECTION_QUEUE <EOL> if session in _CONNECTION_QUEUE : <EOL> _CONNECTION_QUEUE . remove ( session ) <EOL> return <EOL> self . portal . amp_protocol . send_AdminPortal2Server ( session , <EOL> operation = PDISCONN ) <EOL> def server_connect ( self , protocol_path = "<STR_LIT>" , config = dict ( ) ) : <EOL> """<STR_LIT>""" <EOL> global _MOD_IMPORT <EOL> if not _MOD_IMPORT : <EOL> from evennia . utils . utils import variable_from_module as _MOD_IMPORT <EOL> path , clsname = protocol_path . rsplit ( "<STR_LIT:.>" , <NUM_LIT:1> ) <EOL> cls = _MOD_IMPORT ( path , clsname ) <EOL> if not cls : <EOL> raise RuntimeError ( "<STR_LIT>" % protocol_path ) <EOL> protocol = cls ( self , ** config ) <EOL> protocol . start ( ) <EOL> def server_disconnect ( self , session , reason = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> if session : <EOL> session . disconnect ( reason ) <EOL> if session . sessid in self : <EOL> del self [ session . sessid ] <EOL> del session <EOL> def server_disconnect_all ( self , reason = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> for session in self . values ( ) : <EOL> session . disconnect ( reason ) <EOL> del session <EOL> self = { } <EOL> def server_logged_in ( self , session , data ) : <EOL> """<STR_LIT>""" <EOL> session . load_sync_data ( data ) <EOL> def server_session_sync ( self , serversessions ) : <EOL> """<STR_LIT>""" <EOL> to_save = [ sessid for sessid in serversessions if sessid in self ] <EOL> to_delete = [ sessid for sessid in self if sessid not in to_save ] <EOL> for sessid in to_save : <EOL> self [ sessid ] . load_sync_data ( serversessions [ sessid ] ) <EOL> for sessid in to_delete : <EOL> self . server_disconnect ( sessid ) <EOL> def count_loggedin ( self , include_unloggedin = False ) : <EOL> """<STR_LIT>""" <EOL> return len ( self . get_sessions ( include_unloggedin = include_unloggedin ) ) <EOL> def session_from_suid ( self , suid ) : <EOL> """<STR_LIT>""" <EOL> return [ sess for sess in self . get_sessions ( include_unloggedin = True ) <EOL> if hasattr ( sess , '<STR_LIT>' ) and sess . suid == suid ] <EOL> def announce_all ( self , message ) : <EOL> """<STR_LIT>""" <EOL> for session in self . values ( ) : <EOL> session . data_out ( message ) <EOL> def oobstruct_parser ( self , oobstruct ) : <EOL> """<STR_LIT>""" <EOL> def _parse ( oobstruct ) : <EOL> slen = len ( oobstruct ) <EOL> if not oobstruct : <EOL> return tuple ( None , ( ) , { } ) <EOL> elif not hasattr ( oobstruct , "<STR_LIT>" ) : <EOL> return ( oobstruct , ( ) , { } ) <EOL> if slen == <NUM_LIT:1> : <EOL> return ( oobstruct [ <NUM_LIT:0> ] , ( ) , { } ) <EOL> elif slen == <NUM_LIT:2> : <EOL> if isinstance ( oobstruct [ <NUM_LIT:1> ] , dict ) : <EOL> return ( oobstruct [ <NUM_LIT:0> ] , ( ) , dict ( oobstruct [ <NUM_LIT:1> ] ) ) <EOL> elif isinstance ( oobstruct [ <NUM_LIT:1> ] , ( tuple , list ) ) : <EOL> return ( oobstruct [ <NUM_LIT:0> ] , tuple ( oobstruct [ <NUM_LIT:1> ] ) , { } ) <EOL> else : <EOL> return ( oobstruct [ <NUM_LIT:0> ] , ( oobstruct [ <NUM_LIT:1> ] , ) , { } ) <EOL> else : <EOL> return ( oobstruct [ <NUM_LIT:0> ] , tuple ( oobstruct [ <NUM_LIT:1> ] ) , dict ( oobstruct [ <NUM_LIT:2> ] ) ) <EOL> if hasattr ( oobstruct , "<STR_LIT>" ) : <EOL> if oobstruct and isinstance ( oobstruct [ <NUM_LIT:0> ] , basestring ) : <EOL> return ( list ( _parse ( oobstruct ) ) , ) <EOL> else : <EOL> out = [ ] <EOL> for oobpart in oobstruct : <EOL> out . append ( _parse ( oobpart ) ) <EOL> return ( list ( out ) , ) <EOL> return ( _parse ( oobstruct ) , ) <EOL> def data_in ( self , session , text = "<STR_LIT>" , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if session : <EOL> now = time ( ) <EOL> if self . command_counter > _MAX_COMMAND_RATE : <EOL> dT = now - self . command_counter_reset <EOL> self . command_counter = <NUM_LIT:0> <EOL> self . command_counter_reset = now <EOL> self . command_overflow = dT < <NUM_LIT:1.0> <EOL> if self . command_overflow : <EOL> reactor . callLater ( <NUM_LIT:1.0> , self . data_in , None ) <EOL> if self . command_overflow : <EOL> self . data_out ( session , text = _ERROR_COMMAND_OVERFLOW ) <EOL> return <EOL> self . command_counter += <NUM_LIT:1> <EOL> session . cmd_last = now <EOL> self . portal . amp_protocol . send_MsgPortal2Server ( session , <EOL> text = text , <EOL> ** kwargs ) <EOL> else : <EOL> if self . command_overflow : <EOL> self . command_overflow = False <EOL> reactor . callLater ( <NUM_LIT:1.0> , self . data_in , None ) <EOL> def data_out ( self , session , text = None , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if session : <EOL> if "<STR_LIT>" in kwargs : <EOL> kwargs [ "<STR_LIT>" ] = self . oobstruct_parser ( kwargs [ "<STR_LIT>" ] ) <EOL> session . data_out ( text = text , ** kwargs ) <EOL> PORTAL_SESSIONS = PortalSessionHandler ( ) </s>
