summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-04-23 12:57:36 +0200
committertroido <troido@protonmail.com>2020-04-23 12:57:36 +0200
commitf7f8f1ee8fd9ed6c4fc6ca040bb86c5e9039ae89 (patch)
treeb5472c1f69653afbec9f1f7a698dd74698da676b
parent4021d17bbc7e9d3ca3f54fdd5e0545c170e9752b (diff)
do introduction before starting the client; ask for the password when the name is registered
-rw-r--r--asciifarmclient/common/messages.py40
-rw-r--r--asciifarmclient/connection.py2
-rw-r--r--asciifarmclient/gameclient.py1
-rw-r--r--asciifarmclient/main.py43
4 files changed, 82 insertions, 4 deletions
diff --git a/asciifarmclient/common/messages.py b/asciifarmclient/common/messages.py
index d3aed9a..df4492b 100644
--- a/asciifarmclient/common/messages.py
+++ b/asciifarmclient/common/messages.py
@@ -63,11 +63,34 @@ class NameMessage(ClientToServerMessage):
if name[0] != "~":
for char in name:
category = unicodedata.category(char)
+ print("'{}'".format(name))
assert category in self.categories, InvalidNameError("all name caracters must be in these unicode categories: " + "|".join(self.categories) + " (except for tildenames)")
self.name = name
def body(self):
return self.name
+
+
+
+class AuthMessage(ClientToServerMessage):
+
+ typename = "auth"
+ categories = {"Lu", "Ll", "Lt", "Lm", "Lo", "Nd", "Nl", "No", "Pc"}
+
+
+ def __init__(self, name, password):
+ assert isinstance(name, str), InvalidNameError("name must be a string")
+ assert (len(name) > 0), InvalidNameError("name needs at least one character")
+ assert (len(bytes(name, "utf-8")) <= 256), InvalidNameError("name may not be longer than 256 utf8 bytes")
+ if name[0] != "~":
+ for char in name:
+ category = unicodedata.category(char)
+ assert category in self.categories, InvalidNameError("all name caracters must be in these unicode categories: " + "|".join(self.categories) + " (except for tildenames)")
+ self.name = name
+ self.password = password
+
+ def body(self):
+ return {"name": self.name, "type": "passtoken", "passtoken": self.password}
class InputMessage(ClientToServerMessage):
@@ -145,6 +168,17 @@ class ErrorMessage(ServerToClientMessage):
return [self.typename, self.errType, self.description]
+class ConnectedMessage(ServerToClientMessage):
+
+ typename = "connected"
+ msglen = 2
+
+ def __init__(self, description=""):
+ self.description = description
+
+ def to_json(self):
+ return [self.typename, self.description]
+
messages = {message.msgType(): message for message in [
NameMessage,
@@ -152,6 +186,10 @@ messages = {message.msgType(): message for message in [
ChatMessage,
WorldMessage,
ErrorMessage,
- MessageMessage
+ MessageMessage,
+ ConnectedMessage
]}
+def message_from_json(msg):
+ return messages[msg[0]].from_json(msg)
+
diff --git a/asciifarmclient/connection.py b/asciifarmclient/connection.py
index bdcc913..707a02e 100644
--- a/asciifarmclient/connection.py
+++ b/asciifarmclient/connection.py
@@ -25,7 +25,7 @@ class Connection:
return None
datastr = databytes.decode('utf-8')
msg = json.loads(datastr)
- message = messages.messages[msg[0]].from_json(msg)
+ message = messages.message_from_json(msg)
return message
def listen(self, callback, onError):
diff --git a/asciifarmclient/gameclient.py b/asciifarmclient/gameclient.py
index d705b59..9d7bca6 100644
--- a/asciifarmclient/gameclient.py
+++ b/asciifarmclient/gameclient.py
@@ -44,7 +44,6 @@ class Client:
self.log(e.description)
def start(self):
- self.sendMessage(messages.NameMessage(self.name))
threading.Thread(target=self.listen, daemon=True).start()
threading.Thread(target=self.getInput, daemon=True).start()
diff --git a/asciifarmclient/main.py b/asciifarmclient/main.py
index 8c79fac..09c9b13 100644
--- a/asciifarmclient/main.py
+++ b/asciifarmclient/main.py
@@ -6,13 +6,16 @@ import sys
import termios
import tty
import signal
-#import os
+import getpass
+import hashlib
+import base64
from .connection import Connection
from .gameclient import Client
from .display import Display
from .parseargs import parse_args
from ratuil.screen import Screen
+from asciifarmclient.common import messages
def main(argv=None):
@@ -26,6 +29,8 @@ def main(argv=None):
print("ERROR: Could not connect to server.\nAre you sure that the server is running and that you're connecting to the right address?", file=sys.stderr)
return
+ if not introduce(connection, name):
+ return
error = None
closeMessage = None
@@ -63,3 +68,39 @@ def main(argv=None):
if closeMessage:
print(closeMessage, file=sys.stderr)
+
+def introduce(connection, name):
+ connection.send(messages.NameMessage(name))
+ print("introducing to server as {}".format(name))
+ response = connection.receive()
+ if response is None:
+ print("connection lost")
+ return False
+ if isinstance(response, messages.ConnectedMessage):
+ print("connection successful")
+ return True
+ if isinstance(response, messages.ErrorMessage):
+ if response.errType == "registered":
+ print("'{}' is a registered name. Enter password to login, or restart the client with the -n <name> option to choose a different name".format(name))
+ password = getpass.getpass()
+ m = hashlib.sha256()
+ m.update(bytes("asciifarm{name}{pw}{name}asciifarm".format(name=name, pw=password), "utf-8"))
+ passbytes = m.digest()
+ passtoken = base64.b64encode(passbytes).decode("ascii")
+ connection.send(messages.AuthMessage(name, passtoken))
+ response = connection.receive()
+ if response is None:
+ print("connection lost")
+ return False
+ if isinstance(response, messages.ConnectedMessage):
+ print("connection successful")
+ return True
+
+ print("Connection unsuccessful: {}".format(response.to_json()))
+ return False
+ else:
+ print("Error: {}".format(response.to_json()), file=sys.stderr)
+ return False
+
+ print("Invalid server response: {}".format(response.to_json()), file=sys.stderr)
+ return False