Skip to content

Commit

Permalink
webrepl: Changes for more webrepl features while making it smaller.
Browse files Browse the repository at this point in the history
This change:
- Moves the password checking to python
- Removes the special file transfer protocol
- Moves the REPL data to websocket binary packages

Signed-off-by: Felix Dörre <[email protected]>
  • Loading branch information
felixdoerre committed Mar 14, 2024
1 parent ffb07db commit cd2a054
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 12 deletions.
2 changes: 1 addition & 1 deletion micropython/net/webrepl/manifest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
metadata(description="WebREPL server.", version="0.1.0")
metadata(description="WebREPL server.", version="1.0.0")

module("webrepl.py", opt=3)
module("webrepl_setup.py", opt=3)
74 changes: 63 additions & 11 deletions micropython/net/webrepl/webrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,68 @@
import socket
import sys
import websocket
import _webrepl
import io

listen_s = None
client_s = None

DEBUG = 0

_DEFAULT_STATIC_HOST = const("https://micropython.org/webrepl/")
_DEFAULT_STATIC_HOST = const("https://felix.dogcraft.de/webrepl/")
_WELCOME_PROMPT = const("\r\nWebREPL connected\r\n>>> ")
static_host = _DEFAULT_STATIC_HOST
webrepl_pass = None


class WebreplWrapper(io.IOBase):
def __init__(self, sock):
self.sock = sock
self.sock.ioctl(9, 2)
if webrepl_pass is not None:
self.pw = bytearray(16)
self.pwPos = 0
self.sock.write("Password: ")
else:
self.pw = None
self.sock.write(_WELCOME_PROMPT)

def readinto(self, buf):
if self.pw is not None:
buf = bytearray(1)
while True:
l = self.sock.readinto(buf)
if l is None:
continue
if l <= 0:
return l
if buf[0] == 10 or buf[0] == 13:
if bytes(self.pw[0 : self.pwPos]) == webrepl_pass:
self.pw = None
del self.pwPos
self.sock.write(_WELCOME_PROMPT)
break
else:
self.sock.write("\r\nAccess denied\r\n")
return 0
else:
if self.pwPos < len(self.pw):
self.pw[self.pwPos] = buf[0]
self.pwPos = self.pwPos + 1
return self.sock.readinto(buf)

def write(self, buf):
if self.pw is not None:
return len(buf)
return self.sock.write(buf)

def ioctl(self, kind, arg):
if kind == 4:
self.sock.close()
return 0
return -1

def close(self):
self.sock.close()


def server_handshake(cl):
Expand Down Expand Up @@ -84,7 +137,7 @@ def send_html(cl):
cl.send(static_host)
cl.send(
b"""\"></base>\r
<script src="webrepl_content.js"></script>\r
<script src="webreplv2_content.js"></script>\r
"""
)
cl.close()
Expand All @@ -95,10 +148,7 @@ def setup_conn(port, accept_handler):
listen_s = socket.socket()
listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

ai = socket.getaddrinfo("0.0.0.0", port)
addr = ai[0][4]

listen_s.bind(addr)
listen_s.bind(("", port))
listen_s.listen(1)
if accept_handler:
listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
Expand Down Expand Up @@ -127,7 +177,7 @@ def accept_conn(listen_sock):
client_s = cl

ws = websocket.websocket(cl, True)
ws = _webrepl._webrepl(ws)
ws = WebreplWrapper(ws)
cl.setblocking(False)
# notify REPL on socket incoming data (ESP32/ESP8266-only)
if hasattr(os, "dupterm_notify"):
Expand All @@ -147,10 +197,10 @@ def stop():


def start(port=8266, password=None, accept_handler=accept_conn):
global static_host
global static_host, webrepl_pass
stop()
webrepl_pass = password
if webrepl_pass is None:
if password is None:
try:
import webrepl_cfg

Expand All @@ -160,7 +210,9 @@ def start(port=8266, password=None, accept_handler=accept_conn):
except:
print("WebREPL is not configured, run 'import webrepl_setup'")

_webrepl.password(webrepl_pass)
if webrepl_pass is not None:
webrepl_pass = webrepl_pass.encode()

s = setup_conn(port, accept_handler)

if accept_handler is None:
Expand Down

0 comments on commit cd2a054

Please sign in to comment.