Skip to content

Commit

Permalink
Add ability to set setup ID in HAP.Setup
Browse files Browse the repository at this point in the history
Restart server if already running.

Setup ID is required for QR code based flow.

mongoose-os-apps/shelly-homekit#127
  • Loading branch information
rojer committed Jun 2, 2021
1 parent 33080f7 commit 3b3a9a5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
18 changes: 16 additions & 2 deletions src/mgos_homekit_adk.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ bool mgos_hap_setup_info_from_string(HAPSetupInfo* setupInfo, const char* salt,
}

#ifdef MGOS_HAP_SIMPLE_CONFIG
static void setup_info_cb(int ev, void* ev_data, void* userdata) {
static void mgos_hap_load_setup_info_cb(int ev, void* ev_data, void* userdata) {
struct mgos_hap_load_setup_info_arg* arg = (struct mgos_hap_load_setup_info_arg*) ev_data;
if (!mgos_hap_setup_info_from_string(
arg->setupInfo, mgos_sys_config_get_hap_salt(), mgos_sys_config_get_hap_verifier())) {
Expand All @@ -123,6 +123,19 @@ static void setup_info_cb(int ev, void* ev_data, void* userdata) {
(void) userdata;
}

extern char* g_hap_setup_id;

static void mgos_hap_load_setup_id_cb(int ev, void* ev_data, void* userdata) {
struct mgos_hap_load_setup_id_arg* arg = (struct mgos_hap_load_setup_id_arg*) ev_data;
if (g_hap_setup_id == NULL)
return;
*arg->valid = true;
memset(arg->setupID->stringValue, 0, sizeof(arg->setupID->stringValue));
strncpy(arg->setupID->stringValue, g_hap_setup_id, sizeof(arg->setupID->stringValue) - 1);
(void) ev;
(void) userdata;
}

bool mgos_hap_config_valid(void) {
HAPSetupInfo setupInfo;
return mgos_hap_setup_info_from_string(
Expand All @@ -132,7 +145,8 @@ bool mgos_hap_config_valid(void) {

bool mgos_homekit_adk_init(void) {
#ifdef MGOS_HAP_SIMPLE_CONFIG
mgos_event_add_handler(MGOS_HAP_EV_LOAD_SETUP_INFO, setup_info_cb, NULL);
mgos_event_add_handler(MGOS_HAP_EV_LOAD_SETUP_INFO, mgos_hap_load_setup_info_cb, NULL);
mgos_event_add_handler(MGOS_HAP_EV_LOAD_SETUP_ID, mgos_hap_load_setup_id_cb, NULL);
#endif
mgos_event_register_base(MGOS_HAP_EV_BASE, "HAP");
return true;
Expand Down
54 changes: 41 additions & 13 deletions src/mgos_homekit_adk_rpc_service.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
static const HAPAccessory* s_acc = NULL;
static HAPAccessoryServerRef* s_server = NULL;
static void (*s_start_cb)(HAPAccessoryServerRef* _Nonnull server) = NULL;
char* g_hap_setup_id = NULL;

static void mgos_hap_stop_and_reset_server(struct mg_rpc_request_info* ri, bool reset_code, bool reset_server);

static bool set_salt_and_verfier(const char* salt, const char* verifier, int config_level) {

Expand Down Expand Up @@ -65,17 +68,17 @@ static void mgos_hap_setup_handler(
void* cb_arg,
struct mg_rpc_frame_info* fi,
struct mg_str args) {
char* code = NULL;
char *code = NULL, *id = NULL;
char *salt = NULL, *verifier = NULL;
int config_level = 2;
bool start_server = true;
HAPSetupInfo setupInfo;

json_scanf(args.p, args.len, ri->args_fmt, &code, &salt, &verifier, &config_level, &start_server);
json_scanf(args.p, args.len, ri->args_fmt, &code, &id, &salt, &verifier, &config_level, &start_server);

if (code != NULL && (salt == NULL && verifier == NULL)) {
if (!HAPAccessorySetupIsValidSetupCode(code)) {
mg_rpc_send_errorf(ri, 400, "invalid code");
mg_rpc_send_errorf(ri, 400, "invalid %s", "code");
ri = NULL;
goto out;
}
Expand All @@ -94,7 +97,7 @@ static void mgos_hap_setup_handler(
cs_base64_encode(setupInfo.verifier, 384, verifier, NULL);
} else if (code == NULL && (salt != NULL && verifier != NULL)) {
if (!mgos_hap_setup_info_from_string(&setupInfo, salt, verifier)) {
mg_rpc_send_errorf(ri, 400, "invalid salt + verifier");
mg_rpc_send_errorf(ri, 400, "invalid", "salt + verifier");
ri = NULL;
goto out;
}
Expand All @@ -104,19 +107,40 @@ static void mgos_hap_setup_handler(
goto out;
}

if (id != NULL && !HAPAccessorySetupIsValidSetupID(id)) {
mg_rpc_send_errorf(ri, 400, "invalid %s '%s'", "id", id);
ri = NULL;
goto out;
}

if (!set_salt_and_verfier(salt, verifier, config_level)) {
mg_rpc_send_errorf(ri, 500, "failed to set code");
ri = NULL;
goto out;
}

mg_rpc_send_responsef(ri, NULL);
free(g_hap_setup_id);
g_hap_setup_id = id;
id = NULL;

if (start_server && HAPAccessoryServerGetState(s_server) == kHAPAccessoryServerState_Idle) {
s_start_cb(s_server);
if (start_server) {
switch (HAPAccessoryServerGetState(s_server)) {
case kHAPAccessoryServerState_Idle:
s_start_cb(s_server);
mg_rpc_send_responsef(ri, NULL);
break;
case kHAPAccessoryServerState_Running:
// Restart server without resetting code (which we've just set).
mgos_hap_stop_and_reset_server(ri, false /* reset_code */, true /* reset_server */);
break;
default:
mg_rpc_send_responsef(ri, NULL);
break;
}
}

out:
free(id);
free(code);
free(salt);
free(verifier);
Expand Down Expand Up @@ -175,6 +199,14 @@ static void stop_and_reset(void* arg) {
}
}

static void mgos_hap_stop_and_reset_server(struct mg_rpc_request_info* ri, bool reset_code, bool reset_server) {
struct reset_ctx* ctx = calloc(1, sizeof(*ctx));
ctx->ri = ri;
ctx->reset_server = reset_server;
ctx->reset_code = reset_code;
stop_and_reset(ctx);
}

static void mgos_hap_reset_handler(
struct mg_rpc_request_info* ri,
void* cb_arg,
Expand All @@ -188,11 +220,7 @@ static void mgos_hap_reset_handler(
return;
}

struct reset_ctx* ctx = calloc(1, sizeof(*ctx));
ctx->ri = ri;
ctx->reset_server = reset_server;
ctx->reset_code = reset_code;
stop_and_reset(ctx);
mgos_hap_stop_and_reset_server(ri, true /* reset_code */, true /* reset_server */);

(void) cb_arg;
(void) fi;
Expand All @@ -215,7 +243,7 @@ void mgos_hap_add_rpc_service_cb(
mg_rpc_add_handler(
mgos_rpc_get_global(),
"HAP.Setup",
"{code: %Q, salt: %Q, verifier: %Q, config_level: %d, start_server: %B}",
"{code: %Q, id: %Q, salt: %Q, verifier: %Q, config_level: %d, start_server: %B}",
mgos_hap_setup_handler,
NULL);
mg_rpc_add_handler(
Expand Down

0 comments on commit 3b3a9a5

Please sign in to comment.