30
30
#include "supervisor/shared/translate/translate.h"
31
31
#include "supervisor/shared/web_workflow/web_workflow.h"
32
32
33
+ #include "shared-bindings/mdns/Server.h"
33
34
#include "shared-bindings/socketpool/__init__.h"
34
35
#include "shared-bindings/socketpool/Socket.h"
35
36
#include "shared-bindings/socketpool/SocketPool.h"
@@ -59,12 +60,18 @@ typedef struct {
59
60
enum request_state state ;
60
61
char method [6 ];
61
62
char path [256 ];
63
+ char header_key [64 ];
64
+ char header_value [64 ];
62
65
uint32_t content_length ;
63
66
size_t offset ;
67
+ bool redirect ;
68
+ bool done ;
64
69
} _request ;
65
70
66
71
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE ;
67
72
73
+ static mdns_server_obj_t mdns ;
74
+
68
75
static socketpool_socketpool_obj_t pool ;
69
76
static socketpool_socket_obj_t listening ;
70
77
static socketpool_socket_obj_t active ;
@@ -133,6 +140,8 @@ void supervisor_start_web_workflow(void) {
133
140
return ;
134
141
}
135
142
143
+ mdns_server_construct (& mdns );
144
+
136
145
pool .base .type = & socketpool_socketpool_type ;
137
146
common_hal_socketpool_socketpool_construct (& pool , & common_hal_wifi_radio_obj );
138
147
@@ -183,6 +192,7 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
183
192
bool more = true;
184
193
bool error = false;
185
194
uint8_t c ;
195
+ // This code assumes header lines are terminated with \r\n
186
196
while (more && !error ) {
187
197
int len = socketpool_socket_recv_into (socket , & c , 1 );
188
198
if (len != 1 ) {
@@ -192,7 +202,7 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
192
202
more = false;
193
203
break ;
194
204
}
195
- ESP_LOGI (TAG , "%c" , c );
205
+ // ESP_LOGI(TAG, "%c", c);
196
206
switch (request -> state ) {
197
207
case STATE_METHOD : {
198
208
if (c == ' ' ) {
@@ -213,7 +223,6 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
213
223
request -> offset = 0 ;
214
224
ESP_LOGW (TAG , "Request %s %s" , request -> method , request -> path );
215
225
request -> state = STATE_VERSION ;
216
- error = true;
217
226
} else if (request -> offset > sizeof (request -> path ) - 1 ) {
218
227
// Skip methods that are too long.
219
228
} else {
@@ -222,25 +231,93 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
222
231
}
223
232
break ;
224
233
}
225
- case STATE_VERSION :
234
+ case STATE_VERSION : {
235
+ const char * supported_version = "HTTP/1.1\r" ;
236
+ error = supported_version [request -> offset ] != c ;
237
+ request -> offset ++ ;
238
+ if (request -> offset == strlen (supported_version )) {
239
+ ESP_LOGW (TAG , "Version ok" );
240
+ request -> state = STATE_HEADER_KEY ;
241
+ request -> offset = 0 ;
242
+ }
226
243
break ;
227
- case STATE_HEADER_KEY :
244
+ }
245
+ case STATE_HEADER_KEY : {
246
+ if (c == '\r' ) {
247
+ request -> state = STATE_BODY ;
248
+ ESP_LOGW (TAG , "Body" );
249
+ } else if (c == '\n' ) {
250
+ // Consume the \n
251
+ } else if (c == ':' ) {
252
+ request -> header_key [request -> offset ] = '\0' ;
253
+ request -> offset = 0 ;
254
+ request -> state = STATE_HEADER_VALUE ;
255
+ } else if (request -> offset > sizeof (request -> header_key ) - 1 ) {
256
+ // Skip methods that are too long.
257
+ } else {
258
+ request -> header_key [request -> offset ] = c ;
259
+ request -> offset ++ ;
260
+ }
228
261
break ;
229
- case STATE_HEADER_VALUE :
262
+ }
263
+ case STATE_HEADER_VALUE : {
264
+ if (request -> offset == 0 ) {
265
+ error = c != ' ' ;
266
+ request -> offset ++ ;
267
+ } else if (c == '\r' ) {
268
+ request -> header_value [request -> offset - 1 ] = '\0' ;
269
+ request -> offset = 0 ;
270
+ request -> state = STATE_HEADER_KEY ;
271
+ if (strcmp (request -> header_key , "Authorization" ) == 0 ) {
272
+ ESP_LOGW (TAG , "Authorization" );
273
+ } else if (strcmp (request -> header_key , "Host" ) == 0 ) {
274
+ ESP_LOGW (TAG , "Host header check '%s'" , request -> header_value );
275
+ request -> redirect = strcmp (request -> header_value , "circuitpython.local" ) == 0 ;
276
+ }
277
+ ESP_LOGW (TAG , "Header %s %s" , request -> header_key , request -> header_value );
278
+ } else if (request -> offset > sizeof (request -> header_value ) - 1 ) {
279
+ // Skip methods that are too long.
280
+ } else {
281
+ request -> header_value [request -> offset - 1 ] = c ;
282
+ request -> offset ++ ;
283
+ }
230
284
break ;
285
+ }
231
286
case STATE_BODY :
287
+ request -> done = true;
288
+ more = false;
232
289
break ;
233
290
}
234
291
}
235
292
if (error ) {
236
- const char * error_response = "HTTP/1.1 501 Not Implemented" ;
293
+ const char * error_response = "HTTP/1.1 501 Not Implemented\r\n\r\n " ;
237
294
int nodelay = 1 ;
238
295
int err = lwip_setsockopt (socket -> num , IPPROTO_TCP , TCP_NODELAY , & nodelay , sizeof (nodelay ));
239
296
int sent = socketpool_socket_send (socket , (const uint8_t * )error_response , strlen (error_response ));
240
297
ESP_LOGW (TAG , "sent %d %d" , sent , err );
241
- vTaskDelay (0 );
242
- socketpool_socket_close (socket );
243
298
}
299
+ if (!request -> done ) {
300
+ return ;
301
+ }
302
+ if (request -> redirect ) {
303
+ const char * redirect_response = "HTTP/1.1 301 Moved Permanently\r\nConnection: close\r\nContent-Length: 0\r\nLocation: http://" ;
304
+ int nodelay = 1 ;
305
+ int err = lwip_setsockopt (socket -> num , IPPROTO_TCP , TCP_NODELAY , & nodelay , sizeof (nodelay ));
306
+ int sent = socketpool_socket_send (socket , (const uint8_t * )redirect_response , strlen (redirect_response ));
307
+ const char * instance_name = common_hal_mdns_server_get_instance_name (& mdns );
308
+ sent += socketpool_socket_send (socket , (const uint8_t * )instance_name , strlen (instance_name ));
309
+ const char * local = ".local" ;
310
+ sent += socketpool_socket_send (socket , (const uint8_t * )local , strlen (local ));
311
+ sent += socketpool_socket_send (socket , (const uint8_t * )request -> path , strlen (request -> path ));
312
+ const char * two_lines = "\r\n\r\n" ;
313
+ sent += socketpool_socket_send (socket , (const uint8_t * )two_lines , strlen (two_lines ));
314
+ ESP_LOGW (TAG , "sent %d %d" , sent , err );
315
+ } else {
316
+ const char * ok_response = "HTTP/1.1 200 OK\r\nContent-Length: 11\r\nContent-Type: text/plain\r\n\r\nHello World" ;
317
+ int sent = socketpool_socket_send (socket , (const uint8_t * )ok_response , strlen (ok_response ));
318
+ ESP_LOGW (TAG , "sent ok %d" , sent );
319
+ }
320
+ request -> done = false;
244
321
}
245
322
246
323
@@ -249,6 +326,9 @@ void supervisor_web_workflow_background(void) {
249
326
if (!common_hal_socketpool_socket_get_connected (& active ) &&
250
327
!common_hal_socketpool_socket_get_closed (& listening ) &&
251
328
listening .num > 0 ) {
329
+ if (!common_hal_socketpool_socket_get_closed (& active )) {
330
+ common_hal_socketpool_socket_close (& active );
331
+ }
252
332
uint32_t ip ;
253
333
uint32_t port ;
254
334
int newsoc = socketpool_socket_accept (& listening , (uint8_t * )& ip , & port );
@@ -268,6 +348,8 @@ void supervisor_web_workflow_background(void) {
268
348
269
349
active_request .state = STATE_METHOD ;
270
350
active_request .offset = 0 ;
351
+ active_request .done = false;
352
+ active_request .redirect = false;
271
353
272
354
lwip_fcntl (newsoc , F_SETFL , O_NONBLOCK );
273
355
}
0 commit comments