Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
 
root / assets / gs / admin-login.html
Author[]google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.c...> 2025-11-30 16:31 UTC
Committer[]Andy Green <andy@warmcat.com> 2025-11-30 16:33 UTC
Tree87ab7db74554f9620c748fd5dd2ce673b4a4acea   Raw Patch
 
Implement correct builder registration flow in sai-power
Implement correct builder registration flow in sai-power

- Added `local_srv_rx` in `p-http-api.c` to handle builder registration JSON via WebSocket.
- Updated `p-private.h` to store platform information in `saip_builder_t`.
- Cleaned up unused `callback_builder` in `p-sai.c`.
- This ensures builder PCON bindings and platforms are correctly propagated to sai-power and subsequently to sai-server.
diff --git a/src/power/p-http-api.c b/src/power/p-http-api.c index ce294df..fc58279 100644 --- a/src/power/p-http-api.c +++ b/src/power/p-http-api.c @@ -183,6 +183,9 @@ LWS_SS_USER_TYPEDEF char payload[200]; size_t size; size_t pos; + struct lws_struct_args a; + struct lejp_ctx ctx; + saip_builder_t *b; } local_srv_t; static lws_ss_state_return_t @@ -216,6 +219,100 @@ local_srv_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len, } static lws_ss_state_return_t +local_srv_rx(void *userobj, const uint8_t *buf, size_t len, int flags) +{ + local_srv_t *g = (local_srv_t *)userobj; + struct lws_ss_handle *h = lws_ss_from_user(g); + saip_pcon_t *pc; + saip_builder_t *b; + + if (!g->ctx.user) { /* first time */ + memset(&g->a, 0, sizeof(g->a)); + g->a.map_st[0] = lsm_schema_builder_registration; + g->a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema_builder_registration); + g->a.ac_block_size = 2048; + lws_struct_json_init_parse(&g->ctx, NULL, &g->a); + } + + if (lejp_parse(&g->ctx, buf, (int)len) < 0 || !g->a.dest) { + lwsl_ss_warn(h, "JSON decode failed"); + lwsac_free(&g->a.ac); + return LWSSSSRET_DISCONNECT_ME; + } + + if (g->a.top_schema_index == 0) { + sai_builder_registration_t *r = (sai_builder_registration_t *)g->a.dest; + + lwsl_ss_notice(h, "Registered builder '%s' on pcon '%s'", + r->builder_name, r->power_controller_name); + + /* Find the PCON */ + pc = saip_pcon_by_name(&power, r->power_controller_name); + if (!pc) { + lwsl_ss_warn(h, "Unknown PCON '%s', creating it", r->power_controller_name); + /* Dynamically create PCON if missing */ + pc = saip_pcon_create(&power, r->power_controller_name); + } + + if (pc) { + /* Check if builder already exists */ + int found = 0; + lws_start_foreach_dll(struct lws_dll2 *, b_node, pc->registered_builders_owner.head) { + saip_builder_t *sb = lws_container_of(b_node, saip_builder_t, list); + if (!strcmp(sb->name, r->builder_name)) { + lwsl_ss_notice(h, "Builder '%s' re-connected to PCON '%s'", r->builder_name, pc->name); + /* sb->wsi = ...; */ /* We don't have wsi here easily, but we have SS handle? Not needed for logic. */ + g->b = sb; /* Link user object to builder */ + found = 1; + break; + } + } lws_end_foreach_dll(b_node); + + if (!found) { + lwsl_ss_notice(h, "Adding builder '%s' to PCON '%s'", r->builder_name, pc->name); + b = malloc(sizeof(*b)); + if (b) { + memset(b, 0, sizeof(*b)); + lws_strncpy(b->name, r->builder_name, sizeof(b->name)); + /* b->wsi = ...; */ + g->b = b; + lws_dll2_add_tail(&b->list, &pc->registered_builders_owner); + } else { + lwsl_ss_err(h, "OOM allocating builder"); + } + } + + /* Store platforms */ + if (g->b) { + /* Clear existing platforms first? Or just append? */ + lws_dll2_owner_clear(&g->b->platforms_owner); /* Assuming we have a way to free items, but lwsac managed? No, these are manual. */ + /* Actually we used lwsac for deserialization, but we need to PERSIST this data. */ + /* We need to copy from 'r->platforms_owner' to 'g->b->platforms_owner' */ + + lws_start_foreach_dll(struct lws_dll2 *, p, r->platforms_owner.head) { + sai_builder_platform_t *bp = lws_container_of(p, sai_builder_platform_t, list); + saip_builder_platform_t *sbp = malloc(sizeof(*sbp)); + if (sbp) { + memset(sbp, 0, sizeof(*sbp)); + lws_strncpy(sbp->name, bp->name, sizeof(sbp->name)); + lws_dll2_add_tail(&sbp->list, &g->b->platforms_owner); + } + } lws_end_foreach_dll(p); + } + + /* Trigger a check since we have a new builder (it's alive!) */ + saip_pcon_start_check(); + + /* Send update to sai-server */ + saip_queue_stay_info(lws_container_of(power.sai_server_owner.head, saip_server_t, list)); + } + } + + lwsac_free(&g->a.ac); + return LWSSSSRET_OK; +} + +static lws_ss_state_return_t local_srv_state(void *userobj, void *sh, lws_ss_constate_t state, lws_ss_tx_ordinal_t ack) { @@ -232,6 +329,16 @@ local_srv_state(void *userobj, void *sh, lws_ss_constate_t state, case LWSSSCS_CREATING: return lws_ss_request_tx(lws_ss_from_user(g)); + case LWSSSCS_DISCONNECTED: + if (g->b) { + /* Mark as offline but don't delete */ + /* g->b->wsi = NULL; */ + g->b = NULL; + } + /* Clean up lejp if pending? */ + lws_struct_json_init_parse(&g->ctx, NULL, NULL); /* Reset */ + break; + case LWSSSCS_SERVER_TXN: lws_ss_get_metadata(lws_ss_from_user(g), "path", (const void **)&path, &len); @@ -410,7 +517,7 @@ power_off: /* * OK this is it, schedule it to happen */ - lws_sul_schedule(lws_ss_cx_from_user(g), 0, + lws_sul_schedule(lws_ss_from_user(g), 0, &pc->sul_delay_off, saip_sul_action_power_off, SAI_POWERDOWN_HOLDOFF_US); @@ -438,5 +545,6 @@ bail: LWS_SS_INFO("local", local_srv_t) .tx = local_srv_tx, + .rx = local_srv_rx, .state = local_srv_state, }; diff --git a/src/power/p-private.h b/src/power/p-private.h index fc94cc5..63013bc 100644 --- a/src/power/p-private.h +++ b/src/power/p-private.h @@ -93,6 +93,7 @@ typedef struct saip_pcon { /* Represents a builder connected to us */ typedef struct saip_builder { struct lws_dll2 list; /* in saip_pcon.registered_builders_owner */ + lws_dll2_owner_t platforms_owner; /* saip_builder_platform_t */ char name[64]; @@ -100,6 +101,11 @@ typedef struct saip_builder { struct lws *wsi; } saip_builder_t; +typedef struct saip_builder_platform { + lws_dll2_t list; + char name[64]; +} saip_builder_platform_t; + struct saip_ws_pss; diff --git a/src/power/p-sai.c b/src/power/p-sai.c index 451a2ac..2ee1855 100644 --- a/src/power/p-sai.c +++ b/src/power/p-sai.c @@ -180,120 +180,8 @@ callback_std(struct lws *wsi, enum lws_callback_reasons reason, void *user, static const struct lws_protocols protocol_std = { "protocol_std", callback_std, 0, 0 }; -/* - * Builder connection handling - */ - -int -callback_builder(struct lws *wsi, enum lws_callback_reasons reason, - void *user, void *in, size_t len) -{ - struct lejp_ctx ctx; - lws_struct_args_t a; - saip_builder_t *b, **pb = (saip_builder_t **)user; - saip_pcon_t *pc; - - switch (reason) { - case LWS_CALLBACK_ESTABLISHED: - lwsl_user("%s: builder connected\n", __func__); - *pb = NULL; /* Ensure user data is clean */ - break; - - case LWS_CALLBACK_RECEIVE: - // lwsl_hexdump_notice(in, len); - memset(&a, 0, sizeof(a)); - a.map_st[0] = lsm_schema_builder_registration; - a.map_entries_st[0] = LWS_ARRAY_SIZE(lsm_schema_builder_registration); - a.ac_block_size = 2048; - - lws_struct_json_init_parse(&ctx, NULL, &a); - if (lejp_parse(&ctx, (uint8_t *)in, (int)len) < 0 || !a.dest) { - lwsl_warn("%s: JSON decode failed\n", __func__); - lwsac_free(&a.ac); - return -1; - } - - if (a.top_schema_index == 0) { - sai_builder_registration_t *r = (sai_builder_registration_t *)a.dest; - - lwsl_notice("%s: Registered builder '%s' on pcon '%s'\n", - __func__, r->builder_name, r->power_controller_name); - - /* Find the PCON */ - pc = saip_pcon_by_name(&power, r->power_controller_name); - if (pc) { - /* Check if builder already exists */ - int found = 0; - lws_start_foreach_dll(struct lws_dll2 *, b_node, pc->registered_builders_owner.head) { - saip_builder_t *sb = lws_container_of(b_node, saip_builder_t, list); - if (!strcmp(sb->name, r->builder_name)) { - lwsl_notice("%s: Builder '%s' re-connected to PCON '%s'\n", __func__, r->builder_name, pc->name); - sb->wsi = wsi; - *pb = sb; - found = 1; - break; - } - } lws_end_foreach_dll(b_node); - - if (!found) { - lwsl_notice("%s: Adding builder '%s' to PCON '%s'\n", __func__, r->builder_name, pc->name); - /* Create/Update builder entry using malloc */ - b = malloc(sizeof(*b)); - if (b) { - memset(b, 0, sizeof(*b)); - lws_strncpy(b->name, r->builder_name, sizeof(b->name)); - b->wsi = wsi; - - /* Store pointer in user data for cleanup */ - *pb = b; - - /* Add to list */ - lws_dll2_add_tail(&b->list, &pc->registered_builders_owner); - } else - lwsl_err("%s: OOM allocating builder\n", __func__); - } - - /* Trigger a check since we have a new builder (it's alive!) */ - saip_pcon_start_check(); - - /* Send update to sai-server? */ - saip_queue_stay_info(lws_container_of(power.sai_server_owner.head, saip_server_t, list)); - - } else { - lwsl_err("%s: Unknown PCON '%s' for builder '%s'\n", - __func__, r->power_controller_name, r->builder_name); - } - - } - lwsac_free(&a.ac); - break; - - case LWS_CALLBACK_CLOSED: - lwsl_user("%s: builder disconnected\n", __func__); - b = *pb; - if (b) { - /* Just mark it as offline, don't remove or free */ - b->wsi = NULL; - /* Don't free *pb, we want to keep the struct */ - /* *pb = NULL; */ - - /* Update state */ - saip_pcon_start_check(); - } - break; - - default: - break; - } - return 0; -} - -static const struct lws_protocols protocol_builder = - { "com-warmcat-sai-builder", callback_builder, sizeof(saip_builder_t *), 0 }; - static const struct lws_protocols *pprotocols[] = { &protocol_std, - &protocol_builder, NULL };
Page fetched 0s ago, creation time: 10ms (vhost etag hits: 0%, cache hits: 0%)