class ListenerMSNP(asyncio.Protocol): def __init__(self, logger_prefix, backend, sess_state_factory): super().__init__() self.logger_prefix = logger_prefix self.backend = backend self.sess_state_factory = sess_state_factory self.transport = None self.logger = None self.sess = None def connection_made(self, transport): self.transport = transport self.logger = Logger(self.logger_prefix, transport) sess_state = self.sess_state_factory(MSNPReader(self.logger), self.backend) self.sess = PersistentSession(sess_state, MSNPWriter(self.logger, sess_state), transport) self.logger.log_connect() def connection_lost(self, exc): self.logger.log_disconnect() self.sess.close() self.sess = None self.logger = None self.transport = None def data_received(self, data): self.sess.state.data_received(data, self.sess)
def __init__( self, logger_prefix: str, backend: Backend, controller_factory: Callable[[Logger, str, Backend], YMSGCtrlBase] ) -> None: super().__init__() self.logger = Logger(logger_prefix, self) self.backend = backend self.controller = controller_factory(self.logger, 'direct', backend) self.controller.close_callback = self._on_close self.transport = None
class ListenerYMSG(asyncio.Protocol): logger: Logger backend: Backend controller: YMSGCtrlBase transport: Optional[asyncio.WriteTransport] def __init__( self, logger_prefix: str, backend: Backend, controller_factory: Callable[[Logger, str, Backend], YMSGCtrlBase] ) -> None: super().__init__() self.logger = Logger(logger_prefix, self) self.backend = backend self.controller = controller_factory(self.logger, 'direct', backend) self.controller.close_callback = self._on_close self.transport = None def connection_made(self, transport: asyncio.BaseTransport) -> None: assert isinstance(transport, asyncio.WriteTransport) self.transport = transport self.logger.log_connect() def connection_lost(self, exc: Optional[Exception]) -> None: self.controller.close() self.logger.log_disconnect() self.transport = None def data_received(self, data: bytes) -> None: transport = self.transport assert transport is not None if self.backend.maintenance_mode: transport.close() return self.controller.transport = None self.controller.data_received(transport, data) transport.write(self.controller.flush()) self.controller.transport = transport def _on_close(self) -> None: if self.transport is None: return self.transport.close()
def _truncated_log(logger: Logger, pre: str, m: Sequence[Any]) -> None: if m[0] in ('UUX', 'MSG', 'ADL'): logger.info(pre, *m[:-1], len(m[-1])) elif m[0] in ('CHG', 'ILN', 'NLN') and 'msnobj' in m[-1]: logger.info(pre, *m[:-1], '<truncated>') else: logger.info(pre, *m)
class ListenerMSNP(asyncio.Protocol): logger: Logger backend: Backend controller: MSNPCtrl transport: Optional[asyncio.WriteTransport] def __init__( self, logger_prefix: str, backend: Backend, controller_factory: Callable[[Logger, str, Backend], MSNPCtrl]) -> None: super().__init__() self.logger = Logger(logger_prefix, self) self.backend = backend self.controller = controller_factory(self.logger, 'direct', backend) self.controller.close_callback = self._on_close self.transport = None def connection_made(self, transport: asyncio.BaseTransport) -> None: assert isinstance(transport, asyncio.WriteTransport) self.transport = transport self.logger.log_connect() self.controller.on_connect() def connection_lost(self, exc: Optional[Exception]) -> None: self.controller.close(hard=True) self.logger.log_disconnect() self.transport = None def data_received(self, data: bytes) -> None: transport = self.transport assert transport is not None # Setting `transport` to None so all data is held until the flush self.controller.transport = None self.controller.data_received(transport, data) transport.write(self.controller.flush()) self.controller.transport = transport def _on_close(self) -> None: if self.transport is None: return self.transport.close()
async def handle_http_gateway(req): if req.method == 'OPTIONS': return web.Response(status = 200, headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Expose-Headers': 'X-MSN-Messenger', 'Access-Control-Max-Age': '86400', }) from util.misc import Logger from core.session import PollingSession from .msnp import MSNP_NS_SessState, MSNP_SB_SessState, MSNPReader, MSNPWriter query = req.query session_id = query.get('SessionID') backend = req.app['backend'] if not session_id: # Create new PollingSession server_type = query.get('Server') server_ip = query.get('IP') session_id = util.misc.gen_uuid() logger = Logger('GW-{}'.format(server_type), session_id) reader = MSNPReader(logger) if server_type == 'NS': sess_state = MSNP_NS_SessState(reader, backend) else: sess_state = MSNP_SB_SessState(reader, backend) sess = PollingSession(sess_state, logger, MSNPWriter(logger, sess_state), server_ip) backend.util_set_sess_token(sess, ('msn-gw', session_id)) sess = backend.util_get_sess_by_token(('msn-gw', session_id)) if not sess or sess.closed: return web.Response(status = 400, text = '') sess.on_connect(req.transport) # Read incoming messages sess.state.data_received(await req.read(), sess) # Write outgoing messages body = sess.on_disconnect() return web.Response(headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST', 'Access-Control-Expose-Headers': 'X-MSN-Messenger', 'X-MSN-Messenger': 'SessionID={}; GW-IP={}'.format(session_id, sess.hostname), 'Content-Type': 'application/x-msn-messenger', }, body = body)
async def handle_http_gateway(req: web.Request) -> web.Response: query = req.query session_id = query.get('SessionID') backend = req.app['backend'] gateway_sessions = req.app['gateway_sessions'] # type: Dict[str, GatewaySession] now = time.time() if not session_id: from front.msn.msnp_ns import MSNPCtrlNS from front.msn.msnp_sb import MSNPCtrlSB # Create new GatewaySession server_type = query.get('Server') server_ip = query.get('IP') session_id = gen_uuid() logger = Logger('GW-{}'.format(server_type), session_id) if server_type == 'NS': controller = MSNPCtrlNS(logger, 'gw', backend) # type: MSNPCtrl else: controller = MSNPCtrlSB(logger, 'gw', backend) tmp = GatewaySession(logger, server_ip, controller, now) controller.close_callback = tmp._on_close gateway_sessions[session_id] = tmp gwsess = gateway_sessions.get(session_id) if gwsess is None: raise web.HTTPBadRequest() assert req.transport is not None gwsess.logger.log_connect() gwsess.controller.data_received(req.transport, await req.read()) gwsess.logger.log_disconnect() body = gwsess.controller.flush() return web.HTTPOk(headers = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST', 'Access-Control-Expose-Headers': 'X-MSN-Messenger', 'X-MSN-Messenger': 'SessionID={}; GW-IP={}'.format(session_id, gwsess.hostname), 'Content-Type': 'application/x-msn-messenger', }, body = body)
def connection_made(self, transport): self.transport = transport self.logger = Logger(self.logger_prefix, transport) self.logger.log_connect()
class ListenerYMSG(asyncio.Protocol): def __init__(self, logger_prefix, backend): super().__init__() self.logger_prefix = logger_prefix self.backend = backend self.transport = None self.logger = None def connection_made(self, transport): self.transport = transport self.logger = Logger(self.logger_prefix, transport) self.logger.log_connect() def connection_lost(self, exc): self.logger.log_disconnect() self.logger = None self.transport = None def data_received(self, data): self.logger.info('>>>', data) (version, vendor_id, service, status, session_id, kvs) = _decode_ymsg(data) if service == YMSGService.Verify: msg = _encode_ymsg(service, status, session_id) self.logger.info('<<<', msg) self.transport.write(msg) return if service == YMSGService.Auth: session_id = 1239999999 email = kvs[1] auth_dict = {1: email} if version in (9, 10): auth_dict[94] = _generate_challenge_v1() elif version in (11): auth_dict[ 94] = '' # Implement V2 challenge string generation later auth_dict[13] = 1 msg = _encode_ymsg(YMSGService.Auth, status, session_id, auth_dict) self.logger.info('<<<', msg) self.transport.write(msg) return if service == YMSGService.AuthResp: print(kvs) print("session_id", session_id) self.logger.info("unknown", service) self.transport.write(_encode_ymsg(YMSGService.LogOff, 0, 0)) self.transport.close()
def connection_made(self, transport): self.transport = transport self.logger = Logger(self.logger_prefix, transport) sess_state = self.sess_state_factory(MSNPReader(self.logger), self.backend) self.sess = PersistentSession(sess_state, MSNPWriter(self.logger, sess_state), transport) self.logger.log_connect()