kopia lustrzana https://github.com/micropython/micropython-lib
uasyncio.websocket.server: Websocket server implementation for uasyncio.
During development, following questions were posed, and subsequently, answered: Q #1: Should this be in uasyncio package at all? Upstream doesn't have this. Pro: will be easier for people do discover (see e.g. https://github.com/micropython/micropython-lib/issues/148) A: uasyncio diverges more and more from asyncio, so if something is convinient for uasyncio, there's no need to look back at asyncio. Q #2: This provides implements 2 ways to create a WS connections: 1) using start_ws_server(); 2) using wrapping existing StreamReader and StreamWriter. History: initial prototype of course used 2). But the idea was "it should be like the official start_server()!!1". But then I though how to integrate it e.g. with Picoweb, and became clear that 2) is the most flixble way. So, 1) is intended to be removed. A: 1) was removed and is not part of the merged version of the patch. Q #3: Uses native websocket module for read path, but has own write path due to https://github.com/micropython/micropython/issues/3396 A: So far, so good. Q #4: Requires https://github.com/micropython/micropython-lib/pull/227 due to https://github.com/micropython/micropython/issues/3394 . A: The prerequisite was merged.pull/261/head
rodzic
0c45f9f666
commit
4c6e7f7107
|
@ -0,0 +1,63 @@
|
|||
import uasyncio
|
||||
import uhashlib, ubinascii
|
||||
import websocket
|
||||
|
||||
|
||||
def make_respkey(webkey):
|
||||
d = uhashlib.sha1(webkey)
|
||||
d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
||||
respkey = d.digest()
|
||||
respkey = ubinascii.b2a_base64(respkey) #[:-1]
|
||||
# Return with trailing "\n".
|
||||
return respkey
|
||||
|
||||
|
||||
class WSWriter:
|
||||
|
||||
def __init__(self, reader, writer):
|
||||
# Reader is passed for symmetry with WSReader() and ignored.
|
||||
self.s = writer
|
||||
|
||||
async def awrite(self, data):
|
||||
assert len(data) < 126
|
||||
await self.s.awrite(b"\x81")
|
||||
await self.s.awrite(bytes([len(data)]))
|
||||
await self.s.awrite(data)
|
||||
|
||||
|
||||
def WSReader(reader, writer):
|
||||
|
||||
webkey = None
|
||||
while 1:
|
||||
l = yield from reader.readline()
|
||||
print(l)
|
||||
if not l:
|
||||
raise ValueError()
|
||||
if l == b"\r\n":
|
||||
break
|
||||
if l.startswith(b'Sec-WebSocket-Key'):
|
||||
webkey = l.split(b":", 1)[1]
|
||||
webkey = webkey.strip()
|
||||
|
||||
if not webkey:
|
||||
raise ValueError("Not a websocker request")
|
||||
|
||||
respkey = make_respkey(webkey)
|
||||
|
||||
await writer.awrite(b"""\
|
||||
HTTP/1.1 101 Switching Protocols\r
|
||||
Upgrade: websocket\r
|
||||
Connection: Upgrade\r
|
||||
Sec-WebSocket-Accept: """)
|
||||
await writer.awrite(respkey)
|
||||
# This will lead to "<key>\n\r\n" being written. Not exactly
|
||||
# "\r\n\r\n", but browsers seem to eat it.
|
||||
await writer.awrite("\r\n")
|
||||
#await writer.awrite("\r\n\r\n")
|
||||
|
||||
print("Finished webrepl handshake")
|
||||
|
||||
ws = websocket.websocket(reader.ios)
|
||||
rws = uasyncio.StreamReader(reader.ios, ws)
|
||||
|
||||
return rws
|
Ładowanie…
Reference in New Issue