Skip to content

Commit 0882cbf

Browse files
committed
web server kinda works
1 parent 61d0f79 commit 0882cbf

File tree

4 files changed

+110
-15
lines changed

4 files changed

+110
-15
lines changed

ports/espressif/common-hal/mdns/Server.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,9 @@
3535

3636
STATIC bool inited = false;
3737

38-
void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_interface) {
39-
if (network_interface != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) {
40-
mp_raise_ValueError(translate("mDNS only works with built-in WiFi"));
41-
return;
42-
}
38+
void mdns_server_construct(mdns_server_obj_t *self) {
4339
if (inited) {
44-
mp_raise_RuntimeError(translate("mDNS already initialized"));
40+
return;
4541
}
4642
mdns_init();
4743

@@ -65,6 +61,17 @@ void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_
6561
mdns_delegate_hostname_add("circuitpython", &our_ip);
6662
}
6763

64+
void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_interface) {
65+
if (network_interface != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) {
66+
mp_raise_ValueError(translate("mDNS only works with built-in WiFi"));
67+
return;
68+
}
69+
if (inited) {
70+
mp_raise_RuntimeError(translate("mDNS already initialized"));
71+
}
72+
mdns_server_construct(self);
73+
}
74+
6875
void common_hal_mdns_server_deinit(mdns_server_obj_t *self) {
6976
inited = false;
7077
mdns_free();

ports/espressif/common-hal/socketpool/Socket.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,10 @@ int socketpool_socket_recv_into(socketpool_socket_obj_t *self,
284284

285285
// In non-blocking mode, fail instead of looping
286286
if (received == -1 && self->timeout_ms == 0) {
287-
if (errno != EAGAIN) {
287+
if (errno == ENOTCONN) {
288+
self->connected = false;
289+
return -MP_ENOTCONN;
290+
} else if (errno != EAGAIN) {
288291
ESP_LOGE(TAG, "recv %d", errno);
289292
}
290293
return -MP_EAGAIN;

shared-bindings/mdns/Server.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ const char *common_hal_mdns_server_get_instance_name(mdns_server_obj_t *self);
4141
void common_hal_mdns_server_set_instance_name(mdns_server_obj_t *self, const char *instance_name);
4242
mp_obj_t common_hal_mdns_server_find(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_float_t timeout);
4343
void common_hal_mdns_server_advertise_service(mdns_server_obj_t *self, const char *service_type, const char *protocol, mp_int_t port);
44+
45+
// For internal use.
46+
void mdns_server_construct(mdns_server_obj_t *self);

supervisor/shared/web_workflow/web_workflow.c

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "supervisor/shared/translate/translate.h"
3131
#include "supervisor/shared/web_workflow/web_workflow.h"
3232

33+
#include "shared-bindings/mdns/Server.h"
3334
#include "shared-bindings/socketpool/__init__.h"
3435
#include "shared-bindings/socketpool/Socket.h"
3536
#include "shared-bindings/socketpool/SocketPool.h"
@@ -59,12 +60,18 @@ typedef struct {
5960
enum request_state state;
6061
char method[6];
6162
char path[256];
63+
char header_key[64];
64+
char header_value[64];
6265
uint32_t content_length;
6366
size_t offset;
67+
bool redirect;
68+
bool done;
6469
} _request;
6570

6671
static wifi_radio_error_t wifi_status = WIFI_RADIO_ERROR_NONE;
6772

73+
static mdns_server_obj_t mdns;
74+
6875
static socketpool_socketpool_obj_t pool;
6976
static socketpool_socket_obj_t listening;
7077
static socketpool_socket_obj_t active;
@@ -133,6 +140,8 @@ void supervisor_start_web_workflow(void) {
133140
return;
134141
}
135142

143+
mdns_server_construct(&mdns);
144+
136145
pool.base.type = &socketpool_socketpool_type;
137146
common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj);
138147

@@ -183,6 +192,7 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
183192
bool more = true;
184193
bool error = false;
185194
uint8_t c;
195+
// This code assumes header lines are terminated with \r\n
186196
while (more && !error) {
187197
int len = socketpool_socket_recv_into(socket, &c, 1);
188198
if (len != 1) {
@@ -192,7 +202,7 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
192202
more = false;
193203
break;
194204
}
195-
ESP_LOGI(TAG, "%c", c);
205+
// ESP_LOGI(TAG, "%c", c);
196206
switch (request->state) {
197207
case STATE_METHOD: {
198208
if (c == ' ') {
@@ -213,7 +223,6 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
213223
request->offset = 0;
214224
ESP_LOGW(TAG, "Request %s %s", request->method, request->path);
215225
request->state = STATE_VERSION;
216-
error = true;
217226
} else if (request->offset > sizeof(request->path) - 1) {
218227
// Skip methods that are too long.
219228
} else {
@@ -222,25 +231,93 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
222231
}
223232
break;
224233
}
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+
}
226243
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+
}
228261
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+
}
230284
break;
285+
}
231286
case STATE_BODY:
287+
request->done = true;
288+
more = false;
232289
break;
233290
}
234291
}
235292
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";
237294
int nodelay = 1;
238295
int err = lwip_setsockopt(socket->num, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
239296
int sent = socketpool_socket_send(socket, (const uint8_t *)error_response, strlen(error_response));
240297
ESP_LOGW(TAG, "sent %d %d", sent, err);
241-
vTaskDelay(0);
242-
socketpool_socket_close(socket);
243298
}
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;
244321
}
245322

246323

@@ -249,6 +326,9 @@ void supervisor_web_workflow_background(void) {
249326
if (!common_hal_socketpool_socket_get_connected(&active) &&
250327
!common_hal_socketpool_socket_get_closed(&listening) &&
251328
listening.num > 0) {
329+
if (!common_hal_socketpool_socket_get_closed(&active)) {
330+
common_hal_socketpool_socket_close(&active);
331+
}
252332
uint32_t ip;
253333
uint32_t port;
254334
int newsoc = socketpool_socket_accept(&listening, (uint8_t *)&ip, &port);
@@ -268,6 +348,8 @@ void supervisor_web_workflow_background(void) {
268348

269349
active_request.state = STATE_METHOD;
270350
active_request.offset = 0;
351+
active_request.done = false;
352+
active_request.redirect = false;
271353

272354
lwip_fcntl(newsoc, F_SETFL, O_NONBLOCK);
273355
}

0 commit comments

Comments
 (0)