Commit 4047472c by Owo Sugiana

Koneksi client sebelumnya akan diputus bila ada yang sama

1 parent ba3cd5e4
test-* test-*
*egg-info *egg-info
__pycache__ __pycache__
*~
*.bak
...@@ -43,6 +43,15 @@ def login(d: dict): ...@@ -43,6 +43,15 @@ def login(d: dict):
return dict(action='login', client_id=client_id, code=0, message='OK') return dict(action='login', client_id=client_id, code=0, message='OK')
def logout(client_id):
pass
def log_message(
ip: str, protocol: str, method: str, data: dict, client_id=None):
pass
def parse(d: dict): def parse(d: dict):
action = d.get('action') action = d.get('action')
if not action: if not action:
...@@ -53,6 +62,10 @@ def parse(d: dict): ...@@ -53,6 +62,10 @@ def parse(d: dict):
raise ErrAction(msg) raise ErrAction(msg)
def get_data():
pass
def init(conf: dict): def init(conf: dict):
d = str2dict(conf['keys']) d = str2dict(conf['keys'])
keys.update(d) keys.update(d)
import sys import sys
import asyncio import asyncio
import json import json
from time import time
from logging import getLogger from logging import getLogger
from configparser import ConfigParser from configparser import ConfigParser
import uvicorn import uvicorn
...@@ -81,8 +82,13 @@ def main(argv=sys.argv[1:]): ...@@ -81,8 +82,13 @@ def main(argv=sys.argv[1:]):
conf = ConfigParser() conf = ConfigParser()
conf.read(conf_file) conf.read(conf_file)
cf = dict(conf.items('main')) cf = dict(conf.items('main'))
login_timeout = int(cf['login_timeout'])
module = get_module_object(cf['module']) module = get_module_object(cf['module'])
module.init(cf) module.init(cf)
# Memory ID didaftar ini akan berakhir
old_clients = []
# Key client_id, Value mem_id
mem_clients = dict()
# Configure a normal WSGI app then wrap it with WSGI -> ASGI class # Configure a normal WSGI app then wrap it with WSGI -> ASGI class
with Configurator(settings=cf) as config: with Configurator(settings=cf) as config:
wsgi_app = config.make_wsgi_app() wsgi_app = config.make_wsgi_app()
...@@ -91,12 +97,21 @@ def main(argv=sys.argv[1:]): ...@@ -91,12 +97,21 @@ def main(argv=sys.argv[1:]):
@app.route('/ws', protocol='websocket') @app.route('/ws', protocol='websocket')
async def main_websocket(scope, receive, send): async def main_websocket(scope, receive, send):
def log_info(msg): def log_info(msg, func=log.info):
if client_id: if client_id:
msg = f'{ip} {mem_id} Client {client_id} {msg}' msg = f'{ip} {mem_id} Client {client_id} {msg}'
else: else:
msg = f'{ip} {mem_id} {msg}' msg = f'{ip} {mem_id} {msg}'
log.info(msg) func(msg)
def log_unknown_error():
log_info(exception_message(), log.error)
def log_message(method: str, d: dict):
try:
module.log_message(ip, 'websocket', method, d, client_id)
except Exception:
log_unknown_error()
async def kirim(d: dict): async def kirim(d: dict):
log_info(f'Send {d}') log_info(f'Send {d}')
...@@ -104,7 +119,9 @@ def main(argv=sys.argv[1:]): ...@@ -104,7 +119,9 @@ def main(argv=sys.argv[1:]):
async def kirim_pesan(d: dict): async def kirim_pesan(d: dict):
text = json.dumps(d) text = json.dumps(d)
await kirim({'type': 'websocket.send', 'text': text}) log_message('send', d)
d = {'type': 'websocket.send', 'text': text}
await kirim(d)
async def run_queue(): async def run_queue():
if client_id and client_id in ws_data: if client_id and client_id in ws_data:
...@@ -113,33 +130,50 @@ def main(argv=sys.argv[1:]): ...@@ -113,33 +130,50 @@ def main(argv=sys.argv[1:]):
del ws_data[client_id][0] del ws_data[client_id][0]
if q['status'] == 'send': if q['status'] == 'send':
await kirim_pesan(q['data']) await kirim_pesan(q['data'])
try:
async def login(d: dict): d = module.get_data()
if d:
await kirim_pesan(d)
except Exception:
log_unknown_error()
async def login(dc: dict):
cid = None
try: try:
d = module.login(d) dc = module.login(dc)
client_id = d['client_id'] cid = dc['client_id']
if client_id in ws_data: if cid in ws_data:
d = dict( old_mem_id = mem_clients[cid]
code=91, old_clients.append(old_mem_id)
message=f'Client {client_id} masih terhubung') log_info(
client_id = None f'Koneksi Client {cid} sebelumnya akan diputus',
log.warning)
else: else:
ws_data[client_id] = [] ws_data[cid] = []
mem_clients[cid] = mem_id
except BaseError as e: except BaseError as e:
d = dict(code=e.code, message=e.message) dc = dict(code=e.code, message=e.message)
except Exception: except Exception:
msg = exception_message() log_unknown_error()
log.error(msg) dc = dict(code=91, message='Login gagal')
d = dict(code=91, message='Login gagal') log_info(f'Encode JSON {dc}')
log_info(f'Encode JSON {d}') await kirim_pesan(dc)
await kirim_pesan(d) return cid
return client_id
first = True first = True
ip = scope['client'][0] ip = scope['client'][0]
mem_id = id(scope) mem_id = id(scope)
client_id = None client_id = None
start_time = time()
while True: while True:
if not client_id and time() - start_time > login_timeout:
log_info('Login timeout', log.error)
break
if mem_id in old_clients:
log_info('Koneksi berakhir karena sudah ada yang baru')
i = old_clients.index(mem_id)
del old_clients[i]
break
try: try:
async with asyncio.timeout(2): async with asyncio.timeout(2):
message = await receive() message = await receive()
...@@ -153,15 +187,28 @@ def main(argv=sys.argv[1:]): ...@@ -153,15 +187,28 @@ def main(argv=sys.argv[1:]):
text = message.get('text') text = message.get('text')
d = json.loads(text) d = json.loads(text)
log_info(f'Decode JSON {d}') log_info(f'Decode JSON {d}')
log_message('receive', d)
if first: if first:
first = False first = False
client_id = await login(d) client_id = await login(d)
if not client_id: if not client_id:
break break
else:
try:
await module.parse(d)
except BaseError as e:
log_info(e.message, log.error)
except Exception as e:
log_unknown_error()
elif message['type'] == 'websocket.disconnect': elif message['type'] == 'websocket.disconnect':
if client_id in ws_data: if client_id in ws_data:
del ws_data[client_id] del ws_data[client_id]
break break
if client_id:
try:
module.logout(client_id)
except Exception:
log_unknown_error()
log.info(f"Listen {cf['ip']} port {cf['port']}") log.info(f"Listen {cf['ip']} port {cf['port']}")
uvicorn.run(app, host=cf['ip'], port=int(cf['port']), log_level='info') uvicorn.run(app, host=cf['ip'], port=int(cf['port']), log_level='info')
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
module = async_web.handlers.default_server module = async_web.handlers.default_server
ip = 0.0.0.0 ip = 0.0.0.0
port = 8000 port = 8000
login_timeout = 30
# Data untuk handlers/default_server.py # Data untuk handlers/default_server.py
keys = keys =
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!