Skip to content

Commit

Permalink
new: Add a different websocket server, which allows localhost server …
Browse files Browse the repository at this point in the history
…without triggering windows firewall
  • Loading branch information
alex-ong committed Aug 11, 2020
1 parent f748793 commit 6d4bfae
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 2 deletions.
2 changes: 1 addition & 1 deletion nestris_ocr/network/cached_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def prePackMessage(dictionary, protocol):
def packMessage(dictionary, protocol):
if protocol in ["LEGACY", "AUTOBAHN", "FILE"]:
return json.dumps(dictionary), False
elif protocol in ["AUTOBAHN_V2", "AUTOBAHN_SERVER"]:
elif protocol in ["AUTOBAHN_V2", "AUTOBAHN_SERVER", "WEBSOCKET_SERVER"]:
return bytes(stuffDictionary(dictionary)), True


Expand Down
3 changes: 3 additions & 0 deletions nestris_ocr/network/network_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import nestris_ocr.network.autobahn_client as AutoBahnClient
import nestris_ocr.network.autobahn_server as AutoBahnServer
import nestris_ocr.network.file_client as FileClient
import nestris_ocr.network.websocket_server as WebSocketServer

NetClient = TCPClient
if (
Expand All @@ -14,3 +15,5 @@
NetClient = AutoBahnServer
elif config["network.protocol"] == "FILE":
NetClient = FileClient
elif config["network.protocol"] == "WEBSOCKET_SERVER":
NetClient = WebSocketServer
87 changes: 87 additions & 0 deletions nestris_ocr/network/websocket_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import asyncio
import websockets
import queue
import threading

# We should use auto-bahn server instead, however it uses IF_ANY instead of IF_LOOPBACK
# when hosting. This means firewall error shows up. The app still works, but this
# is user unfriendly. As a result, we are using a different library for now.
# When Autobahn allows hosting on 127.0.0.1 without raising firewall, this dependency
# will be removed.

# This implementation is strictly 1:1 client server. If you add more clients, behavior is
# undefined until we fix it :)


def CreateClient(target, port):
client = Connection(target, port)
client.start()
return client


class Connection(threading.Thread):
def __init__(self, target, port):
super().__init__()
self.host = target
self.port = port
self.running = False
self.queue = queue.Queue()
self.websockets = set() # client websockets
self.server_task = None
self.loop = None

def sendMessage(self, data, isBinary=False):
if not isBinary:
data = data.encode("utf8")
self.queue.put(data)

def checkNetworkClose(self):
return False

def close(self):
self.loop.call_soon_threadsafe(self.loop.stop)

def stop(self):
self.close()

def run(self):
if self.running:
return
self.running = True

# note this doesnt work in linux; it should run in main thread.
# we need self.loop.run_forever() but nonblocking in main thread.

self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.loop.create_task(self.broadcast())
# next, we need to startup our server
self.server_task = websockets.serve(
self.on_client_connect, self.host, self.port
)

self.loop.run_until_complete(self.server_task)
self.loop.run_forever()

async def on_client_connect(self, websocket, path):
print("client connected")
self.websockets.add(websocket)
try:
# receive messages from clients and ignore them
async for msg in websocket:
pass
except websockets.ConnectionClosed:
print("Client disconnected")
finally:
self.websockets.remove(websocket)

async def broadcast(self):
while True:
try:
item = self.queue.get_nowait()
except queue.Empty:
await asyncio.sleep(0.016)
continue
await asyncio.gather(
*[ws.send(item) for ws in self.websockets], return_exceptions=False,
)
6 changes: 5 additions & 1 deletion nestris_ocr/ocr_state/field_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ def line_clear_animation(self, other):

def serialize(self):
result = self.data
if config["network.protocol"] in ["AUTOBAHN_V2", "AUTOBAHN_SERVER"]:
if config["network.protocol"] in [
"AUTOBAHN_V2",
"AUTOBAHN_SERVER",
"WEBSOCKET_SERVER",
]:
result = prePackField(result)
result = result.tobytes()
else:
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ numpy
opencv-python
pillow
pre-commit
websockets
pyobjc; sys_platform == "darwin"
pypiwin32; sys_platform == "win32"
tkmacosx; sys_platform == "darwin"
1 change: 1 addition & 0 deletions scripts/build-windows/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ https://download.lfd.uci.edu/pythonlibs/w3jqiv8s/numpy-1.18.5+vanilla-cp37-cp37m
opencv-python-headless
pillow
pre-commit
websockets
pyobjc; sys_platform == "darwin"
pypiwin32; sys_platform == "win32"
tkmacosx; sys_platform == "darwin"
Expand Down

0 comments on commit 6d4bfae

Please sign in to comment.