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