1# This module should be imported from REPL, not run from command line.
2import socket
3import uos
4import network
5import uwebsocket
6import websocket_helper
7import _webrepl
8
9listen_s = None
10client_s = None
11
12
13def setup_conn(port, accept_handler):
14    global listen_s
15    listen_s = socket.socket()
16    listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
17
18    ai = socket.getaddrinfo("0.0.0.0", port)
19    addr = ai[0][4]
20
21    listen_s.bind(addr)
22    listen_s.listen(1)
23    if accept_handler:
24        listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
25    for i in (network.AP_IF, network.STA_IF):
26        iface = network.WLAN(i)
27        if iface.active():
28            print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
29    return listen_s
30
31
32def accept_conn(listen_sock):
33    global client_s
34    cl, remote_addr = listen_sock.accept()
35    prev = uos.dupterm(None)
36    uos.dupterm(prev)
37    if prev:
38        print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
39        cl.close()
40        return
41    print("\nWebREPL connection from:", remote_addr)
42    client_s = cl
43    websocket_helper.server_handshake(cl)
44    ws = uwebsocket.websocket(cl, True)
45    ws = _webrepl._webrepl(ws)
46    cl.setblocking(False)
47    # notify REPL on socket incoming data (ESP32/ESP8266-only)
48    if hasattr(uos, "dupterm_notify"):
49        cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
50    uos.dupterm(ws)
51
52
53def stop():
54    global listen_s, client_s
55    uos.dupterm(None)
56    if client_s:
57        client_s.close()
58    if listen_s:
59        listen_s.close()
60
61
62def start(port=8266, password=None):
63    stop()
64    if password is None:
65        try:
66            import webrepl_cfg
67
68            _webrepl.password(webrepl_cfg.PASS)
69            setup_conn(port, accept_conn)
70            print("Started webrepl in normal mode")
71        except:
72            print("WebREPL is not configured, run 'import webrepl_setup'")
73    else:
74        _webrepl.password(password)
75        setup_conn(port, accept_conn)
76        print("Started webrepl in manual override mode")
77
78
79def start_foreground(port=8266):
80    stop()
81    s = setup_conn(port, None)
82    accept_conn(s)
83