Compare commits

..

2 Commits

Author SHA1 Message Date
Lexi / Zoe d5f1e76383 Docu: add initial protocol docu 2018-11-24 01:23:24 +01:00
Lexi / Zoe 48c467349d Server: parse client messages, handle 'init' 2018-11-24 01:16:38 +01:00
2 changed files with 84 additions and 9 deletions

49
doc/protocol.md Normal file
View File

@ -0,0 +1,49 @@
InstantChat WebSocket Protocol
==============================
Messages from client to server (commands)
-----------------------------------------
JSON objects. Key `action` determines type of message.
### init
Initialize the connection, set nickname and join/create a chat.
**Parameters:**
* `action` = `"init"`
* `chat_id`: either an existing ID of a chat instance or *[TODO: ?]* empty string to
create a new chat
* `nickname`: user's chosen nickname *[TODO: valid characters?]*
**Example:**
{
"action": "init",
"chat_id": "42",
"nickname": "Alice"
}
### send (?)
Send a message...
*[TODO]*
Messages from server to client (responses/events)
-------------------------------------------------
JSON objects. Key `type` determines type of message.
### init
Response to `init` command. Confirms initialization and chat join.
**Parameters:**
* `type` = `"init"`
* ***[TODO]***
**Example:**
{
"type": "init",
TODO ???
}

View File

@ -1,33 +1,59 @@
#!/usr/bin/env python #!/usr/bin/env python
# Example code from:
# https://websockets.readthedocs.io/en/stable/intro.html
import asyncio import asyncio
import json
import websockets import websockets
def log_message_error(error, message_text):
print(f"[E] {error}")
print(f" Message: {message_text}")
async def parse_client_message(websocket, message_text): async def parse_client_message(websocket, message_text):
"""Parse a message (JSON object) from a client.""" """Parse a message (JSON object) from a client."""
# TODO parse JSON try:
response = f"Hello {message_text}!" # Parse JSON
message = json.loads(message_text)
await websocket.send(response) # Handle message types
if message['action'] == 'init':
await handle_client_init(websocket, message)
else:
log_message_error(f"Unknown action '{message['action']}'", message_text)
except json.decoder.JSONDecodeError as e:
log_message_error(f"JSON decode error: {e}", message_text)
except KeyError as e:
log_message_error(f"Missing key {e} in JSON message", message_text)
async def handle_client_init(websocket, message):
"""Handle client 'init' message."""
print(f"< init: chat_id='{message['chat_id']}', nickname='{message['nickname']}'")
# Send response to client
response = json.dumps({
'type': 'init'
})
print(f"> {response}") print(f"> {response}")
await websocket.send(response)
async def client_handler(websocket, path): async def client_handler(websocket, path):
"""Handle client connection.""" """Handle client connection."""
print(f"++ New client") print(f"++ New client {websocket.remote_address}")
try: try:
# Read and parse messages until connection is closed # Read and parse messages until connection is closed
async for message_text in websocket: async for message_text in websocket:
print(f"< {message_text}")
await parse_client_message(websocket, message_text) await parse_client_message(websocket, message_text)
except websockets.exceptions.ConnectionClosed:
# Ignore ConnectionClosed exceptions because we handle this in finally
pass
finally: finally:
print(f"-- Client connection closed") print(f"-- Client connection closed {websocket.remote_address}")
# Create WebSocket listener # Create WebSocket listener
start_server = websockets.serve(client_handler, '0.0.0.0', 32715) start_server = websockets.serve(client_handler, '0.0.0.0', 32715)