1313
1414DEBUG = 0
1515
16- _DEFAULT_STATIC_HOST = const ("https://felix.dogcraft.de /webrepl/" )
16+ _DEFAULT_STATIC_HOST = const ("https://micropython.org /webrepl/" )
1717_WELCOME_PROMPT = const ("\r \n WebREPL connected\r \n >>> " )
1818static_host = _DEFAULT_STATIC_HOST
1919webrepl_pass = None
2020
21+ legacy = LegacyFileTransfer ()
22+
23+
2124class WebreplWrapper (io .IOBase ):
2225 def __init__ (self , sock ):
2326 self .sock = sock
24- self .sock .ioctl (9 , 2 )
27+ self .sock .ioctl (9 , 1 if legacy else 2 )
2528 if webrepl_pass is not None :
2629 self .pw = bytearray (16 )
2730 self .pwPos = 0
@@ -32,14 +35,14 @@ def __init__(self, sock):
3235
3336 def readinto (self , buf ):
3437 if self .pw is not None :
35- buf = bytearray (1 )
38+ buf1 = bytearray (1 )
3639 while True :
37- l = self .sock .readinto (buf )
40+ l = self .sock .readinto (buf1 )
3841 if l is None :
3942 continue
4043 if l <= 0 :
4144 return l
42- if buf [0 ] == 10 or buf [0 ] == 13 :
45+ if buf1 [0 ] == 10 or buf1 [0 ] == 13 :
4346 print ("Authenticating with:" )
4447 print (self .pw [0 :self .pwPos ])
4548 if bytes (self .pw [0 :self .pwPos ]) == webrepl_pass :
@@ -54,9 +57,21 @@ def readinto(self, buf):
5457 return 0
5558 else :
5659 if self .pwPos < len (self .pw ):
57- self .pw [self .pwPos ] = buf [0 ]
60+ self .pw [self .pwPos ] = buf1 [0 ]
5861 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
6075
6176 def write (self , buf ):
6277 if self .pw is not None :
@@ -72,8 +87,7 @@ def ioctl(self, kind, arg):
7287 def close (self ):
7388 self .sock .close ()
7489
75- def server_handshake (cl ):
76- req = cl .makefile ("rwb" , 0 )
90+ def server_handshake (req ):
7791 # Skip HTTP GET line.
7892 l = req .readline ()
7993 if DEBUG :
@@ -115,30 +129,33 @@ def server_handshake(cl):
115129 if DEBUG :
116130 print ("respkey:" , respkey )
117131
118- cl . send (
132+ req . write (
119133 b"""\
120134 HTTP/1.1 101 Switching Protocols\r
121135Upgrade: websocket\r
122136Connection: Upgrade\r
123137Sec-WebSocket-Accept: """
124138 )
125- cl . send (respkey )
126- cl . send ("\r \n \r \n " )
139+ req . write (respkey )
140+ req . write ("\r \n \r \n " )
127141
128142 return True
129143
130144
131145def send_html (cl ):
132- cl .send (
146+ cl .write (
133147 b"""\
134148 HTTP/1.0 200 OK\r
135149\r
136150<base href=\" """
137151 )
138- cl .send (static_host )
139- cl .send (
152+ cl .write (static_host )
153+ cl .write (
140154 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
142159"""
143160 )
144161 cl .close ()
@@ -149,10 +166,7 @@ def setup_conn(port, accept_handler):
149166 listen_s = socket .socket ()
150167 listen_s .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
151168
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 ))
156170 listen_s .listen (1 )
157171 if accept_handler :
158172 listen_s .setsockopt (socket .SOL_SOCKET , 20 , accept_handler )
@@ -164,11 +178,14 @@ def setup_conn(port, accept_handler):
164178
165179
166180def accept_conn (listen_sock ):
167- global client_s
181+ global client_s , webrepl_ssl_context
168182 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 )
169186
170187 if not server_handshake (cl ):
171- send_html (cl )
188+ send_html (sock )
172189 return False
173190
174191 prev = os .dupterm (None )
@@ -180,13 +197,13 @@ def accept_conn(listen_sock):
180197 print ("\n WebREPL connection from:" , remote_addr )
181198 client_s = cl
182199
183- ws = websocket .websocket (cl , True )
184- ws = WebreplWrapper (ws )
200+ sock = websocket .websocket (sock )
201+ sock = WebreplWrapper (sock )
185202 cl .setblocking (False )
186203 # notify REPL on socket incoming data (ESP32/ESP8266-only)
187204 if hasattr (os , "dupterm_notify" ):
188205 cl .setsockopt (socket .SOL_SOCKET , 20 , os .dupterm_notify )
189- os .dupterm (ws )
206+ os .dupterm (sock )
190207
191208 return True
192209
@@ -200,9 +217,10 @@ def stop():
200217 listen_s .close ()
201218
202219
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
205222 stop ()
223+ webrepl_ssl_context = ssl_context
206224 webrepl_pass = password
207225 if password is None :
208226 try :
@@ -230,5 +248,5 @@ def start(port=8266, password=None, accept_handler=accept_conn):
230248 print ("Started webrepl in manual override mode" )
231249
232250
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