From c1d1c562f3a1e4922711f0584e99ef074c5ce0f1 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 30 Apr 2016 20:41:09 +0300 Subject: [PATCH] esp8266/scripts/webrepl: Add "first connection" mode to setup password. If there's no port_config.py file, or it lacks WEBREPL_PASS variable, "initial setup mode" will be entered on first WebREPLconnection. User will be asked for password, which will be written to port_config.WEBREPL_PASS, and system restarted to work in normal mode with password active. --- esp8266/scripts/webrepl.py | 14 ++++-- esp8266/scripts/webrepl_setup.py | 77 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 esp8266/scripts/webrepl_setup.py diff --git a/esp8266/scripts/webrepl.py b/esp8266/scripts/webrepl.py index 18c991287d..1a2c82277e 100644 --- a/esp8266/scripts/webrepl.py +++ b/esp8266/scripts/webrepl.py @@ -9,7 +9,7 @@ import _webrepl listen_s = None client_s = None -def setup_conn(port): +def setup_conn(port, accept_handler): global listen_s, client_s listen_s = socket.socket() listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) @@ -19,7 +19,7 @@ def setup_conn(port): listen_s.bind(addr) listen_s.listen(1) - listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_conn) + listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler) for i in (network.AP_IF, network.STA_IF): iface = network.WLAN(i) if iface.active(): @@ -51,4 +51,12 @@ def stop(): def start(port=8266): stop() - setup_conn(port) + try: + import port_config + _webrepl.password(port_config.WEBREPL_PASS) + setup_conn(port, accept_conn) + print("Started webrepl in normal mode") + except: + import webrepl_setup + setup_conn(port, webrepl_setup.handle_conn) + print("Started webrepl in setup mode") diff --git a/esp8266/scripts/webrepl_setup.py b/esp8266/scripts/webrepl_setup.py new file mode 100644 index 0000000000..b912a4aa61 --- /dev/null +++ b/esp8266/scripts/webrepl_setup.py @@ -0,0 +1,77 @@ +import sys +import socket +import time + +from websocket import * +import websocket_helper + + +def setup_server(): + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + ai = socket.getaddrinfo("0.0.0.0", 8266) + addr = ai[0][4] + + s.bind(addr) + s.listen(1) + return s + +def getpass(stream, prompt): + stream.write(prompt) + passwd = b"" + while 1: + c = stream.read(1) + if c in (b"\r", b"\n"): + stream.write("\r\n") + return passwd + passwd += c +# stream.write("*") + +def handle_conn(listen_sock): + cl, remote_addr = listen_sock.accept() + + print(""" + +First-time WebREPL connection has been received. WebREPL initial setup +will now start over this connection. During setup, UART REPL will be +non-responsive. After setup finishes, the board will be rebooted. In +case of error during setup, current session will continue. + +If you receive this message unexpectedly, it may mean that your WebREPL +connection is being hacked (power off board if unsure). +""") + + websocket_helper.server_handshake(cl) + ws = websocket(cl) + + ws.write("""\ +Welcome to MicroPython WebREPL!\r +\r +This is the first time you connect to WebREPL, so please set a password\r +to use for the following WebREPL sessions. Once you enter the password\r +twice, your board will reboot with WebREPL running in active mode. On\r +some boards, you may need to press reset button or reconnect power.\r +\r +""") + + while 1: + passwd1 = getpass(ws, "New password: ") + passwd2 = getpass(ws, "Confirm password: ") + if passwd1 == passwd2: + break + ws.write("Passwords do not match\r\n") + + with open("port_config.py", "w") as f: + f.write("WEBREPL_PASS = %r\n" % passwd1.decode("ascii")) + + ws.write("Password successfully set, restarting...\r\n") + cl.close() + time.sleep(2) + import machine + machine.reset() + + +def test(): + s = setup_server() + handle_conn(s)