13
13
14
14
DEBUG = 0
15
15
16
- _DEFAULT_STATIC_HOST = const ("https://felix.dogcraft.de /webrepl/" )
16
+ _DEFAULT_STATIC_HOST = const ("https://micropython.org /webrepl/" )
17
17
_WELCOME_PROMPT = const ("\r \n WebREPL connected\r \n >>> " )
18
18
static_host = _DEFAULT_STATIC_HOST
19
19
webrepl_pass = None
20
20
21
+ legacy = LegacyFileTransfer ()
22
+
23
+
21
24
class WebreplWrapper (io .IOBase ):
22
25
def __init__ (self , sock ):
23
26
self .sock = sock
24
- self .sock .ioctl (9 , 2 )
27
+ self .sock .ioctl (9 , 1 if legacy else 2 )
25
28
if webrepl_pass is not None :
26
29
self .pw = bytearray (16 )
27
30
self .pwPos = 0
@@ -32,14 +35,14 @@ def __init__(self, sock):
32
35
33
36
def readinto (self , buf ):
34
37
if self .pw is not None :
35
- buf = bytearray (1 )
38
+ buf1 = bytearray (1 )
36
39
while True :
37
- l = self .sock .readinto (buf )
40
+ l = self .sock .readinto (buf1 )
38
41
if l is None :
39
42
continue
40
43
if l <= 0 :
41
44
return l
42
- if buf [0 ] == 10 or buf [0 ] == 13 :
45
+ if buf1 [0 ] == 10 or buf1 [0 ] == 13 :
43
46
print ("Authenticating with:" )
44
47
print (self .pw [0 :self .pwPos ])
45
48
if bytes (self .pw [0 :self .pwPos ]) == webrepl_pass :
@@ -54,9 +57,21 @@ def readinto(self, buf):
54
57
return 0
55
58
else :
56
59
if self .pwPos < len (self .pw ):
57
- self .pw [self .pwPos ] = buf [0 ]
60
+ self .pw [self .pwPos ] = buf1 [0 ]
58
61
self .pwPos = self .pwPos + 1
59
- return self .sock .readinto (buf )
62
+ ret = None
63
+ while True :
64
+ ret = self .sock .readinto (buf )
65
+ if ret is None or ret <= 0 :
66
+ break
67
+ # ignore any non-data frames
68
+ if self .sock .ioctl (8 ) >= 8 :
69
+ continue
70
+ if self .sock .ioctl (8 ) == 2 and legacy :
71
+ legacy .handle (buf , self .sock )
72
+ continue
73
+ break
74
+ return ret
60
75
61
76
def write (self , buf ):
62
77
if self .pw is not None :
@@ -72,8 +87,7 @@ def ioctl(self, kind, arg):
72
87
def close (self ):
73
88
self .sock .close ()
74
89
75
- def server_handshake (cl ):
76
- req = cl .makefile ("rwb" , 0 )
90
+ def server_handshake (req ):
77
91
# Skip HTTP GET line.
78
92
l = req .readline ()
79
93
if DEBUG :
@@ -115,30 +129,33 @@ def server_handshake(cl):
115
129
if DEBUG :
116
130
print ("respkey:" , respkey )
117
131
118
- cl . send (
132
+ req . write (
119
133
b"""\
120
134
HTTP/1.1 101 Switching Protocols\r
121
135
Upgrade: websocket\r
122
136
Connection: Upgrade\r
123
137
Sec-WebSocket-Accept: """
124
138
)
125
- cl . send (respkey )
126
- cl . send ("\r \n \r \n " )
139
+ req . write (respkey )
140
+ req . write ("\r \n \r \n " )
127
141
128
142
return True
129
143
130
144
131
145
def send_html (cl ):
132
- cl .send (
146
+ cl .write (
133
147
b"""\
134
148
HTTP/1.0 200 OK\r
135
149
\r
136
150
<base href=\" """
137
151
)
138
- cl .send (static_host )
139
- cl .send (
152
+ cl .write (static_host )
153
+ cl .write (
140
154
b"""\" ></base>\r
141
- <script src="webreplv2_content.js"></script>\r
155
+ <script src="webrepl""" )
156
+ if not legacy :
157
+ cl .write ("v2" )
158
+ cl .write (b"""_content.js"></script>\r
142
159
"""
143
160
)
144
161
cl .close ()
@@ -149,10 +166,7 @@ def setup_conn(port, accept_handler):
149
166
listen_s = socket .socket ()
150
167
listen_s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
151
168
152
- ai = socket .getaddrinfo ("0.0.0.0" , port )
153
- addr = ai [0 ][4 ]
154
-
155
- listen_s .bind (addr )
169
+ listen_s .bind (("" , port ))
156
170
listen_s .listen (1 )
157
171
if accept_handler :
158
172
listen_s .setsockopt (socket .SOL_SOCKET , 20 , accept_handler )
@@ -164,11 +178,14 @@ def setup_conn(port, accept_handler):
164
178
165
179
166
180
def accept_conn (listen_sock ):
167
- global client_s
181
+ global client_s , webrepl_ssl_context
168
182
cl , remote_addr = listen_sock .accept ()
183
+ sock = cl
184
+ if webrepl_ssl_context is not None :
185
+ sock = webrepl_ssl_context .wrap_socket (sock )
169
186
170
187
if not server_handshake (cl ):
171
- send_html (cl )
188
+ send_html (sock )
172
189
return False
173
190
174
191
prev = os .dupterm (None )
@@ -180,13 +197,13 @@ def accept_conn(listen_sock):
180
197
print ("\n WebREPL connection from:" , remote_addr )
181
198
client_s = cl
182
199
183
- ws = websocket .websocket (cl , True )
184
- ws = WebreplWrapper (ws )
200
+ sock = websocket .websocket (sock )
201
+ sock = WebreplWrapper (sock )
185
202
cl .setblocking (False )
186
203
# notify REPL on socket incoming data (ESP32/ESP8266-only)
187
204
if hasattr (os , "dupterm_notify" ):
188
205
cl .setsockopt (socket .SOL_SOCKET , 20 , os .dupterm_notify )
189
- os .dupterm (ws )
206
+ os .dupterm (sock )
190
207
191
208
return True
192
209
@@ -200,9 +217,10 @@ def stop():
200
217
listen_s .close ()
201
218
202
219
203
- def start (port = 8266 , password = None , accept_handler = accept_conn ):
204
- global static_host , webrepl_pass
220
+ def start (port = 8266 , password = None , ssl_context = None , accept_handler = accept_conn ):
221
+ global static_host , webrepl_pass , webrepl_ssl_context
205
222
stop ()
223
+ webrepl_ssl_context = ssl_context
206
224
webrepl_pass = password
207
225
if password is None :
208
226
try :
@@ -230,5 +248,5 @@ def start(port=8266, password=None, accept_handler=accept_conn):
230
248
print ("Started webrepl in manual override mode" )
231
249
232
250
233
- def start_foreground (port = 8266 , password = None ):
234
- start (port , password , None )
251
+ def start_foreground (port = 8266 , password = None , ssl_context = None ):
252
+ start (port , password , ssl_context = ssl_context , accept_handler = None )
0 commit comments