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
Author[]Andy Green <andy@warmcat.com> 2025-05-14 10:12 UTC
Committer[]Andy Green <andy@warmcat.com> 2025-05-14 12:07 UTC
Tree159c52396fd6043b9e7d4914a6994f68cc60c9e2   Raw Patch
 
wol-use-root-privs
wol-use-root-privs
diff --git a/src/builder/b-private.h b/src/builder/b-private.h index f2fee9e..784e676 100644 --- a/src/builder/b-private.h +++ b/src/builder/b-private.h @@ -74,67 +74,7 @@ enum { NSSTATE_FAILED, }; -struct saib_logproxy { - char sockpath[128]; - struct sai_nspawn *ns; - int log_channel_idx; -}; - -struct saib_resproxy { - char sockpath[128]; - struct sai_nspawn *ns; -}; - -struct sai_nspawn; - -struct sai_nspawn { - lws_dll2_owner_t chunk_cache; - - char inp[512]; - char path[384]; - char pending_mirror_log[128]; - - /* convenient place to store it */ - struct saib_logproxy slp_control; - struct saib_logproxy slp[2]; - - lws_dll2_t list; /* sai_plat owner lists sai_nspawns */ - struct sai_builder *builder; - struct lws_fsmount fsm; - struct lws_spawn_piped *lsp; - sai_task_t *task; - lws_dll2_owner_t artifact_owner; /* struct artifact_path */ - - struct lws_threadpool *tp; - struct lws_threadpool_task *tp_task; - lws_sorted_usec_list_t sul_cleaner; - lws_sorted_usec_list_t sul_task_cancel; - - sai_plat_t *sp; /* the sai_plat */ - struct sai_plat_server *spm; /* the sai plat / server with the ss / wsi */ - - size_t chunk_cache_size; - - const char *server_name; /* sai-server name who triggered this, eg, 'warmcat' */ - const char *project_name; /* name of the git project, eg, 'libwebsockets' */ - const char *ref; /* remote refname, eg 'server' */ - const char *hash; /* remote hash */ - const char *git_repo_url; - - int retcode; - int instance_idx; - int mirror_wait_budget; - - uint8_t spins; - uint8_t state; /* NSSTATE_ */ - uint8_t stdcount; - uint8_t term_budget; - - uint8_t finished_when_logs_drained:1; - uint8_t state_changed:1; - uint8_t user_cancel:1; -}; typedef struct sai_mirror_instance { pthread_mutex_t mut; diff --git a/src/common/include/private.h b/src/common/include/private.h index 4a024e7..f020053 100644 --- a/src/common/include/private.h +++ b/src/common/include/private.h @@ -54,31 +54,8 @@ enum { SAISPRF_SIGNALLED = 0x4000, }; -/* - * Builder is indicating he can't take the task and server should free it up - * and try another builder. - */ - -typedef struct sai_rejection { - struct lws_dll2 list; - char host_platform[65]; - char task_uuid[65]; - int ongoing; - int limit; -} sai_rejection_t; - -/* - * Master is broadcasting that builders should stop work on the given task, - * because, eg, the task was reset - */ - -typedef struct sai_cancel { - struct lws_dll2 list; - char task_uuid[65]; -} sai_cancel_t; - -struct sai_event; +struct sai_nspawn; typedef struct { lws_dll2_t list; @@ -115,6 +92,94 @@ typedef struct { char told_ongoing; } sai_task_t; +typedef struct sai_plat sai_plat_t; + +struct saib_logproxy { + char sockpath[128]; + struct sai_nspawn *ns; + int log_channel_idx; +}; + +struct saib_resproxy { + char sockpath[128]; + struct sai_nspawn *ns; +}; + +struct sai_nspawn { + lws_dll2_owner_t chunk_cache; + + char inp[512]; + char path[384]; + char pending_mirror_log[128]; + + /* convenient place to store it */ + struct saib_logproxy slp_control; + struct saib_logproxy slp[2]; + + lws_dll2_t list; /* sai_plat owner lists sai_nspawns */ + struct sai_builder *builder; + struct lws_fsmount fsm; + struct lws_spawn_piped *lsp; + sai_task_t *task; + + lws_dll2_owner_t artifact_owner; /* struct artifact_path */ + + struct lws_threadpool *tp; + struct lws_threadpool_task *tp_task; + lws_sorted_usec_list_t sul_cleaner; + lws_sorted_usec_list_t sul_task_cancel; + + sai_plat_t *sp; /* the sai_plat */ + struct sai_plat_server *spm; /* the sai plat / server with the ss / wsi */ + + size_t chunk_cache_size; + + const char *server_name; /* sai-server name who triggered this, eg, 'warmcat' */ + const char *project_name; /* name of the git project, eg, 'libwebsockets' */ + const char *ref; /* remote refname, eg 'server' */ + const char *hash; /* remote hash */ + const char *git_repo_url; + + int retcode; + int instance_idx; + int mirror_wait_budget; + + uint8_t spins; + uint8_t state; /* NSSTATE_ */ + uint8_t stdcount; + uint8_t term_budget; + + uint8_t finished_when_logs_drained:1; + uint8_t state_changed:1; + uint8_t user_cancel:1; +}; + +/* + * Builder is indicating he can't take the task and server should free it up + * and try another builder. + */ + +typedef struct sai_rejection { + struct lws_dll2 list; + char host_platform[65]; + char task_uuid[65]; + int ongoing; + int limit; +} sai_rejection_t; + +/* + * Master is broadcasting that builders should stop work on the given task, + * because, eg, the task was reset + */ + +typedef struct sai_cancel { + struct lws_dll2 list; + char task_uuid[65]; +} sai_cancel_t; + + +struct sai_event; + typedef struct sai_event { struct lws_dll2 list; lws_dll2_owner_t task_owner; diff --git a/src/power/p-comms.c b/src/power/p-comms.c index 8b64718..d551000 100644 --- a/src/power/p-comms.c +++ b/src/power/p-comms.c @@ -70,17 +70,9 @@ saip_m_rx(void *userobj, const uint8_t *buf, size_t len, int flags) * is powered on. */ if (!strcmp(sp->power_on_type, "wol")) { - uint8_t mac[LWS_ETHER_ADDR_LEN]; - - if (lws_parse_mac(sp->power_on_mac, mac)) { - lwsl_user("Failed to parse mac '%s'\n", sp->power_on_mac); - } else - - if (!lws_wol(lws_ss_cx_from_user(pss), - NULL, mac)) { - lwsl_user("Failed to WOL '%s'\n", sp->power_on_mac); - } else - lwsl_user("Sent WOL to '%s'\n", sp->power_on_mac); + lwsl_notice("%s: triggering WOL\n", __func__); + write(lws_spawn_get_fd_stdxxx(lsp_wol, 0), + sp->power_on_mac, strlen(sp->power_on_mac)); } if (!strcmp(sp->power_on_type, "tasmota")) { diff --git a/src/power/p-private.h b/src/power/p-private.h index dae86da..fc3eb62 100644 --- a/src/power/p-private.h +++ b/src/power/p-private.h @@ -91,6 +91,8 @@ struct sai_power { struct lws_context *context; struct lws_vhost *vhost; + struct sai_nspawn wol_nspawn; + lws_sorted_usec_list_t sul_idle; const char *power_off; @@ -116,6 +118,7 @@ struct jpargs { extern struct sai_power power; extern const lws_ss_info_t ssi_saip_server_link_t, ssi_saip_smartplug_t; extern const struct lws_protocols protocol_com_warmcat_sai, protocol_ws_power; +extern struct lws_spawn_piped *lsp_wol; int saip_config_global(struct sai_power *power, const char *d); extern int saip_config(struct sai_power *power, const char *d); diff --git a/src/power/p-sai.c b/src/power/p-sai.c index 8bf3775..1949a67 100644 --- a/src/power/p-sai.c +++ b/src/power/p-sai.c @@ -50,6 +50,9 @@ #include <libwebsockets.h> #include <string.h> #include <signal.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> #if defined(__linux__) #include <unistd.h> @@ -74,6 +77,7 @@ int getpid(void) { return 0; } static const char *config_dir = "/etc/sai/power"; static int interrupted; static lws_state_notify_link_t nl; +struct lws_spawn_piped *lsp_wol; struct sai_power power; @@ -320,6 +324,52 @@ int main(int argc, const char **argv) lws_context_info_defaults(&info, NULL); + if ((p = lws_cmdline_option(argc, argv, "-s"))) { + struct lws_context *cx; + ssize_t n = 0; + + printf("%s: WOL subprocess generation...\n", __func__); + + cx = lws_create_context(&info); + if (!cx) { + lwsl_err("%s: failed to create wol cx\n", __func__); + return 1; + } + + /* + * A new process gets started with this option before we drop + * privs. This allows us to do WOL with root privs later. + * + * We just wait until we get an ascii mac on stdin from the main + * process indicating the WOL needed. + */ + + while (n >= 0) { + char min[20]; + uint8_t mac[LWS_ETHER_ADDR_LEN]; + + n = read(0, min, sizeof(min) - 1); + lwsl_notice("%s: wol process read returned %d\n", __func__, (int)n); + + if (n <= 0) + continue; + + min[n] = '\0'; + + { int fd = open("/tmp/q", O_CREAT | O_TRUNC | O_RDWR, 0644); write(fd, min, (size_t)(n + 1)); close(fd); } + + if (lws_parse_mac(min, mac)) { + lwsl_user("Failed to parse mac '%s'\n", min); + } else + if (lws_wol(cx, NULL, mac)) { + lwsl_user("Failed to WOL '%s'\n", min); + } else + lwsl_user("Sent WOL to '%s'\n", min); + } + + return 0; + } + if ((p = lws_cmdline_option(argc, argv, "-d"))) logs = atoi(p); @@ -336,6 +386,10 @@ int main(int argc, const char **argv) lws_set_log_level(logs, NULL); + lwsl_user("Sai Power - " + "Copyright (C) 2019-2025 Andy Green <andy@warmcat.com>\n"); + lwsl_user(" sai-power [-c <config-file>]\n"); + #if defined(WIN32) { PWSTR wdi = NULL; @@ -364,14 +418,11 @@ int main(int argc, const char **argv) * Let's parse the global bits out of the config */ - lwsl_user("Sai Power - " - "Copyright (C) 2019-2025 Andy Green <andy@warmcat.com>\n"); - lwsl_user(" sai-power [-c <config-file>]\n"); - info.pprotocols = pprotocols; info.uid = 883; info.pt_serv_buf_size = 32 * 1024; info.rlimit_nofile = 20000; + info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS; signal(SIGINT, sigint_handler); @@ -392,7 +443,6 @@ int main(int argc, const char **argv) return 1; } - lwsl_notice("%s: config dir %s\n", __func__, config_dir); if (saip_config_global(&power, config_dir)) { lwsl_err("%s: global config failed\n", __func__); @@ -406,6 +456,29 @@ int main(int argc, const char **argv) goto bail; } + { + struct lws_spawn_piped_info info; + char rpath[PATH_MAX]; + const char * const ea[] = { rpath, "-s", NULL }; + + realpath(argv[0], rpath); + + memset(&info, 0, sizeof(info)); + memset(&power.wol_nspawn, 0, sizeof(power.wol_nspawn)); + + info.vh = power.vhost; + info.exec_array = ea; + info.max_log_lines = 100; + info.opaque = (void *)&power.wol_nspawn; + + lsp_wol = lws_spawn_piped(&info); + if (!lsp_wol) + lwsl_err("%s: wol spawn failed\n", __func__); + } + + lws_finalize_startup(power.context); + + while (!lws_service(power.context, 0) && !interrupted) ;
Page fetched 0s ago, creation time: 4ms (vhost etag hits: 0%, cache hits: 0%)