mirror of
https://git.ugnet.gay/CrossTalk/azul.git
synced 2026-05-27 22:59:49 +00:00
103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
from typing import Dict
|
|
import time, asyncio, settings
|
|
from aiohttp import web
|
|
|
|
from util.misc import Logger, gen_uuid
|
|
from front.msn.msnp import MSNPCtrl
|
|
|
|
def register(loop: asyncio.AbstractEventLoop, app: web.Application) -> None:
|
|
gateway_sessions = {} # type: Dict[str, GatewaySession]
|
|
app['gateway_sessions'] = gateway_sessions
|
|
app.router.add_route('OPTIONS', '/gateway/gateway.dll', handle_http_gateway_options)
|
|
app.router.add_post('/gateway/gateway.dll', handle_http_gateway)
|
|
|
|
loop.create_task(_clean_gateway_sessions(gateway_sessions))
|
|
|
|
async def _clean_gateway_sessions(gateway_sessions: Dict[str, 'GatewaySession']) -> None:
|
|
while True:
|
|
await asyncio.sleep(10)
|
|
now = time.time()
|
|
closed = []
|
|
for session_id, gwsess in gateway_sessions.items():
|
|
if gwsess.time_last_connect + gwsess.timeout <= now:
|
|
gwsess.controller.close()
|
|
closed.append(session_id)
|
|
for session_id in closed:
|
|
del gateway_sessions[session_id]
|
|
|
|
class GatewaySession:
|
|
__slots__ = ('logger', 'hostname', 'controller', 'timeout', 'time_last_connect')
|
|
|
|
logger: Logger
|
|
hostname: str
|
|
controller: MSNPCtrl
|
|
timeout: float
|
|
time_last_connect: float
|
|
|
|
def __init__(self, logger: Logger, hostname: str, controller: MSNPCtrl, now: float) -> None:
|
|
self.logger = logger
|
|
self.hostname = hostname
|
|
self.controller = controller
|
|
self.timeout = 60
|
|
self.time_last_connect = now
|
|
|
|
def _on_close(self) -> None:
|
|
self.time_last_connect = 0
|
|
|
|
async def handle_http_gateway_options(req: web.Request) -> web.Response:
|
|
return web.HTTPOk(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',
|
|
})
|
|
|
|
async def handle_http_gateway(req: web.Request) -> web.Response:
|
|
query = req.query
|
|
session_id = query.get('SessionID')
|
|
action = query.get('Action')
|
|
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') or ''
|
|
session_id = gen_uuid()
|
|
|
|
logger = Logger('MSN {} via HTTP Gateway'.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
|
|
if gwsess.time_last_connect != now:
|
|
gwsess.time_last_connect = now
|
|
if action != 'poll':
|
|
gwsess.logger.log_connect()
|
|
gwsess.controller.data_received(await req.read(), transport = req.transport)
|
|
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, settings.TARGET_IP),
|
|
'Content-Type': 'application/x-msn-messenger',
|
|
}, body = body)
|