Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share the web workflow MDNS object with the user #7445

Merged
merged 3 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 10 additions & 5 deletions ports/espressif/common-hal/mdns/Server.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ STATIC bool inited = false;

void mdns_server_construct(mdns_server_obj_t *self, bool workflow) {
if (inited) {
self->inited = false;
tannewt marked this conversation as resolved.
Show resolved Hide resolved
return;
}
mdns_init();
Expand All @@ -46,6 +47,8 @@ void mdns_server_construct(mdns_server_obj_t *self, bool workflow) {
snprintf(self->default_hostname, sizeof(self->default_hostname), "cpy-%02x%02x%02x", mac[3], mac[4], mac[5]);
common_hal_mdns_server_set_hostname(self, self->default_hostname);

self->inited = true;

if (workflow) {
// Set a delegated entry to ourselves. This allows us to respond to "circuitpython.local"
// queries as well.
Expand All @@ -67,21 +70,23 @@ void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_
mp_raise_ValueError(translate("mDNS only works with built-in WiFi"));
return;
}
if (inited) {
mdns_server_construct(self, false);
if (common_hal_mdns_server_deinited(self)) {
mp_raise_RuntimeError(translate("mDNS already initialized"));
}
mdns_server_construct(self, false);
}

void common_hal_mdns_server_deinit(mdns_server_obj_t *self) {
if (common_hal_mdns_server_deinited(self)) {
return;
}
self->inited = false;
inited = false;
mdns_free();
}

bool common_hal_mdns_server_deinited(mdns_server_obj_t *self) {
// This returns INVALID_STATE when not initialized and INVALID_PARAM when it
// is.
return mdns_instance_name_set(NULL) == ESP_ERR_INVALID_STATE;
return !self->inited;
}

const char *common_hal_mdns_server_get_hostname(mdns_server_obj_t *self) {
Expand Down
1 change: 1 addition & 0 deletions ports/espressif/common-hal/mdns/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ typedef struct {
const char *instance_name;
// "cpy-" "XXXXXX" "\0"
char default_hostname[4 + 6 + 1];
tannewt marked this conversation as resolved.
Show resolved Hide resolved
bool inited;
} mdns_server_obj_t;
28 changes: 21 additions & 7 deletions ports/raspberrypi/common-hal/mdns/Server.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,29 @@
#include "lwip/apps/mdns.h"
#include "lwip/prot/dns.h"

// Track if we've inited the LWIP MDNS at all. It expects to only init once.
// Subsequent times, we restart it.
STATIC bool inited = false;
// Track if we are globally inited. This essentially forces one inited MDNS
// object at a time. (But ignores MDNS objects that are deinited.)
STATIC bool object_inited = false;

#define NETIF_STA (&cyw43_state.netif[CYW43_ITF_STA])
#define NETIF_AP (&cyw43_state.netif[CYW43_ITF_AP])

void mdns_server_construct(mdns_server_obj_t *self, bool workflow) {
if (inited) {
if (object_inited) {
self->inited = false;
return;
}

mdns_resp_init();
inited = true;
if (!inited) {
mdns_resp_init();
inited = true;
} else {
mdns_resp_restart(NETIF_STA);
}
self->inited = true;

uint8_t mac[6];
wifi_radio_get_mac_address(&common_hal_wifi_radio_obj, mac);
Expand All @@ -68,19 +79,23 @@ void common_hal_mdns_server_construct(mdns_server_obj_t *self, mp_obj_t network_
mp_raise_ValueError(translate("mDNS only works with built-in WiFi"));
return;
}
if (inited) {
if (object_inited) {
mp_raise_RuntimeError(translate("mDNS already initialized"));
}
mdns_server_construct(self, false);
}

void common_hal_mdns_server_deinit(mdns_server_obj_t *self) {
inited = false;
if (common_hal_mdns_server_deinited(self)) {
return;
}
self->inited = false;
object_inited = false;
mdns_resp_remove_netif(NETIF_STA);
}

bool common_hal_mdns_server_deinited(mdns_server_obj_t *self) {
return !mdns_resp_netif_active(NETIF_STA);
return !self->inited;
}

const char *common_hal_mdns_server_get_hostname(mdns_server_obj_t *self) {
Expand Down Expand Up @@ -215,7 +230,6 @@ STATIC void alloc_search_result_cb(struct mdns_answer *answer, const char *varpa
if ((flags & MDNS_SEARCH_RESULT_FIRST) != 0) {
// first
mdns_remoteservice_obj_t *service = gc_alloc(sizeof(mdns_remoteservice_obj_t), 0, false);
mp_printf(&mp_plat_print, "found service %p\n", service);
if (service == NULL) {
// alloc fails
mdns_search_stop(state->request_id);
Expand Down
1 change: 1 addition & 0 deletions ports/raspberrypi/common-hal/mdns/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ typedef struct {
// "cpy-" "XXXXXX" "\0"
char default_hostname[4 + 6 + 1];
const char *service_type[MDNS_MAX_SERVICES];
bool inited;
} mdns_server_obj_t;
14 changes: 13 additions & 1 deletion shared-bindings/mdns/Server.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include "shared-bindings/mdns/Server.h"
#include "shared-bindings/util.h"

#if CIRCUITPY_WEB_WORKFLOW
#include "supervisor/shared/web_workflow/web_workflow.h"
#endif

//| class Server:
//| """The MDNS Server responds to queries for this device's information and allows for querying
//| other devices."""
Expand All @@ -53,7 +57,14 @@ STATIC mp_obj_t mdns_server_make_new(const mp_obj_type_t *type, size_t n_args, s
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);

mdns_server_obj_t *self = m_new_obj(mdns_server_obj_t);
#if CIRCUITPY_WEB_WORKFLOW
mdns_server_obj_t *web_workflow_mdns = supervisor_web_workflow_mdns(args[ARG_network_interface].u_obj);
if (web_workflow_mdns != NULL) {
return web_workflow_mdns;
}
#endif

mdns_server_obj_t *self = m_new_obj_with_finaliser(mdns_server_obj_t);
self->base.type = &mdns_server_type;
common_hal_mdns_server_construct(self, args[ARG_network_interface].u_obj);

Expand Down Expand Up @@ -194,6 +205,7 @@ STATIC const mp_rom_map_elem_t mdns_server_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_find), MP_ROM_PTR(&mdns_server_find_obj) },
{ MP_ROM_QSTR(MP_QSTR_advertise_service), MP_ROM_PTR(&mdns_server_advertise_service_obj) },

{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mdns_server_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mdns_server_deinit_obj) },
};

Expand Down
71 changes: 49 additions & 22 deletions supervisor/shared/web_workflow/web_workflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,16 @@ STATIC void _update_encoded_ip(void) {
}
}

mdns_server_obj_t *supervisor_web_workflow_mdns(mp_obj_t network_interface) {
#if CIRCUITPY_MDNS
if (network_interface == &common_hal_wifi_radio_obj &&
mdns.base.type == &mdns_server_type) {
return &mdns;
}
#endif
return NULL;
}

#if CIRCUITPY_STATUS_BAR
bool supervisor_web_workflow_status_dirty(void) {
return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled ||
Expand Down Expand Up @@ -300,11 +310,6 @@ void supervisor_start_web_workflow(void) {

if (first_start) {
port_changed = false;
#if CIRCUITPY_MDNS
mdns_server_construct(&mdns, true);
mdns.base.type = &mdns_server_type;
common_hal_mdns_server_set_instance_name(&mdns, MICROPY_HW_BOARD_NAME);
#endif
pool.base.type = &socketpool_socketpool_type;
common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj);

Expand All @@ -313,13 +318,26 @@ void supervisor_start_web_workflow(void) {

websocket_init();
}
#if CIRCUITPY_MDNS
// Try to start MDNS if the user deinited it.
if (mdns.base.type != &mdns_server_type ||
common_hal_mdns_server_deinited(&mdns)) {
mdns_server_construct(&mdns, true);
mdns.base.type = &mdns_server_type;
if (!common_hal_mdns_server_deinited(&mdns)) {
common_hal_mdns_server_set_instance_name(&mdns, MICROPY_HW_BOARD_NAME);
}
}
#endif
if (port_changed) {
common_hal_socketpool_socket_close(&listening);
}
if (first_start || port_changed) {
web_api_port = new_port;
#if CIRCUITPY_MDNS
common_hal_mdns_server_advertise_service(&mdns, "_circuitpython", "_tcp", web_api_port);
if (!common_hal_mdns_server_deinited(&mdns)) {
common_hal_mdns_server_advertise_service(&mdns, "_circuitpython", "_tcp", web_api_port);
}
#endif
socketpool_socket(&pool, SOCKETPOOL_AF_INET, SOCKETPOOL_SOCK_STREAM, &listening);
common_hal_socketpool_socket_settimeout(&listening, 0);
Expand Down Expand Up @@ -444,17 +462,18 @@ static bool _origin_ok(const char *origin) {
}
// These are prefix checks up to : so that any port works.
// TODO: Support DHCP hostname in addition to MDNS.
const char *end;
#if CIRCUITPY_MDNS
const char *local = ".local";
const char *hostname = common_hal_mdns_server_get_hostname(&mdns);
const char *end = origin + strlen(http) + strlen(hostname) + strlen(local);
if (strncmp(origin + strlen(http), hostname, strlen(hostname)) == 0 &&
strncmp(origin + strlen(http) + strlen(hostname), local, strlen(local)) == 0 &&
(end[0] == '\0' || end[0] == ':')) {
return true;
if (!common_hal_mdns_server_deinited(&mdns)) {
const char *local = ".local";
const char *hostname = common_hal_mdns_server_get_hostname(&mdns);
end = origin + strlen(http) + strlen(hostname) + strlen(local);
if (strncmp(origin + strlen(http), hostname, strlen(hostname)) == 0 &&
strncmp(origin + strlen(http) + strlen(hostname), local, strlen(local)) == 0 &&
(end[0] == '\0' || end[0] == ':')) {
return true;
}
}
#else
const char *end;
#endif

_update_encoded_ip();
Expand Down Expand Up @@ -733,12 +752,13 @@ static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request,
}

static void _reply_with_devices_json(socketpool_socket_obj_t *socket, _request *request) {
size_t total_results = 0;
#if CIRCUITPY_MDNS
mdns_remoteservice_obj_t found_devices[32];
size_t total_results = mdns_server_find(&mdns, "_circuitpython", "_tcp", 1, found_devices, MP_ARRAY_SIZE(found_devices));
if (!common_hal_mdns_server_deinited(&mdns)) {
total_results = mdns_server_find(&mdns, "_circuitpython", "_tcp", 1, found_devices, MP_ARRAY_SIZE(found_devices));
}
size_t count = MIN(total_results, MP_ARRAY_SIZE(found_devices));
#else
size_t total_results = 0;
#endif
socketpool_socket_send(socket, (const uint8_t *)OK_JSON, strlen(OK_JSON));
_cors_header(socket, request);
Expand Down Expand Up @@ -775,10 +795,11 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request *
_send_str(socket, "\r\n");
mp_print_t _socket_print = {socket, _print_chunk};

#if CIRCUITPY_MDNS
const char *hostname = common_hal_mdns_server_get_hostname(&mdns);
#else
const char *hostname = "";
#if CIRCUITPY_MDNS
if (!common_hal_mdns_server_deinited(&mdns)) {
hostname = common_hal_mdns_server_get_hostname(&mdns);
}
#endif
_update_encoded_ip();
// Note: this leverages the fact that C concats consecutive string literals together.
Expand Down Expand Up @@ -1023,7 +1044,13 @@ static void _decode_percents(char *str) {
static bool _reply(socketpool_socket_obj_t *socket, _request *request) {
if (request->redirect) {
#if CIRCUITPY_MDNS
_reply_redirect(socket, request, request->path);
if (!common_hal_mdns_server_deinited(&mdns)) {
_reply_redirect(socket, request, request->path);
} else {
_reply_missing(socket, request);
}
#else
_reply_missing(socket, request);
#endif
} else if (strlen(request->origin) > 0 && !_origin_ok(request->origin)) {
_reply_forbidden(socket, request);
Expand Down
4 changes: 4 additions & 0 deletions supervisor/shared/web_workflow/web_workflow.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <stdbool.h>

#include "shared-bindings/mdns/Server.h"
#include "shared-bindings/socketpool/Socket.h"

// This background function should be called repeatedly. It cannot be done based
Expand All @@ -38,5 +39,8 @@ void supervisor_web_workflow_status(void);
void supervisor_start_web_workflow(void);
void supervisor_stop_web_workflow(void);

// Share the MDNS object with user code.
mdns_server_obj_t *supervisor_web_workflow_mdns(mp_obj_t network_interface);

// To share with websocket.
void web_workflow_send_raw(socketpool_socket_obj_t *socket, const uint8_t *buf, int len);