From 1f13855e412bba26064672b02dff78deecb795ab Mon Sep 17 00:00:00 2001 From: OpenGnSys Support Team Date: Tue, 27 Apr 2021 23:45:28 +0200 Subject: #1043 add WOL_SENT state WOL_SENT tells that WakeOnLan was sent to computer, after 60 seconds, if computer does not boot, this state is released. --- src/core.c | 6 ++++++ src/rest.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/wol.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ src/wol.h | 14 +++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/core.c b/src/core.c index fef00ea..a346e7b 100644 --- a/src/core.c +++ b/src/core.c @@ -11,6 +11,7 @@ #include "utils.h" #include "list.h" #include "rest.h" +#include "wol.h" #include "client.h" #include "json.h" #include "schedule.h" @@ -326,6 +327,7 @@ void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io, int events) int on = 1, idle = OG_TCP_KEEPALIVE_IDLE; struct sockaddr_in client_addr; socklen_t addrlen = sizeof(client_addr); + struct og_client_wol *cli_wol; struct og_client *cli; int client_sd; @@ -343,6 +345,10 @@ void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io, int events) setsockopt(client_sd, IPPROTO_TCP, TCP_KEEPINTVL, &intl, sizeof(int)); setsockopt(client_sd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(int)); + cli_wol = og_client_wol_find(&client_addr.sin_addr); + if (cli_wol) + og_client_wol_destroy(cli_wol); + cli = (struct og_client *)calloc(1, sizeof(struct og_client)); if (!cli) { close(client_sd); diff --git a/src/rest.c b/src/rest.c index f78483e..9823b0f 100644 --- a/src/rest.c +++ b/src/rest.c @@ -11,6 +11,7 @@ #include "utils.h" #include "list.h" #include "rest.h" +#include "wol.h" #include "cfg.h" #include "schedule.h" #include @@ -76,6 +77,7 @@ struct ev_loop *og_loop; #define OG_REST_PARAM_CENTER (1UL << 43) static LIST_HEAD(client_list); +static LIST_HEAD(client_wol_list); void og_client_add(struct og_client *cli) { @@ -391,19 +393,53 @@ static int og_json_client_append(json_t *array, struct og_client *client) return 0; } +static int og_json_client_wol_append(json_t *array, + struct og_client_wol *cli_wol) +{ + json_t *addr, *state, *object; + + object = json_object(); + if (!object) + return -1; + + addr = json_string(inet_ntoa(cli_wol->addr)); + if (!addr) { + json_decref(object); + return -1; + } + json_object_set_new(object, "addr", addr); + state = json_string(og_client_wol_status(cli_wol)); + if (!state) { + json_decref(object); + return -1; + } + json_object_set_new(object, "state", state); + json_array_append_new(array, object); + + return 0; +} + static int og_cmd_get_clients(json_t *element, struct og_msg_params *params, char *buffer_reply) { - struct og_client *client; struct og_buffer og_buffer = { .data = buffer_reply, }; + struct og_client_wol *cli_wol; + struct og_client *client; json_t *array, *root; array = json_array(); if (!array) return -1; + list_for_each_entry(cli_wol, &client_wol_list, list) { + if (og_json_client_wol_append(array, cli_wol) < 0) { + json_decref(array); + return -1; + } + } + list_for_each_entry(client, &client_list, list) { if (!client->agent) continue; @@ -450,10 +486,24 @@ static int og_json_parse_type(json_t *element, struct og_msg_params *params) return 0; } +struct og_client_wol *og_client_wol_find(const struct in_addr *addr) +{ + struct og_client_wol *cli_wol; + + list_for_each_entry(cli_wol, &client_wol_list, list) { + if (cli_wol->addr.s_addr == addr->s_addr) + return cli_wol; + } + + return NULL; +} + static int og_cmd_wol(json_t *element, struct og_msg_params *params) { char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {}; + struct og_client_wol *cli_wol; int ips_str_len = 0; + struct in_addr addr; const char *msglog; struct og_dbi *dbi; int err = 0, i = 0; @@ -520,6 +570,23 @@ static int og_cmd_wol(json_t *element, struct og_msg_params *params) if (i == 0) return 0; + for (i = 0; i < params->ips_array_len; i++) { + if (inet_aton(params->ips_array[i], &addr) < 0) + return -1; + + cli_wol = og_client_wol_find(&addr); + if (cli_wol) { + og_client_wol_refresh(cli_wol); + continue; + } + + cli_wol = og_client_wol_create(&addr); + if (!cli_wol) + return -1; + + list_add_tail(&cli_wol->list, &client_wol_list); + } + if (!Levanta((char **)params->ips_array, (char **)params->mac_array, (char **)params->netmask_array, i, (char *)params->wol_type)) diff --git a/src/wol.c b/src/wol.c index 0ebf718..b0c9426 100644 --- a/src/wol.c +++ b/src/wol.c @@ -18,6 +18,7 @@ #include #include #include "wol.h" +#include "rest.h" #include "cfg.h" #include "ogAdmServer.h" @@ -86,3 +87,52 @@ bool wake_up_broadcast(int sd, struct sockaddr_in *client, return wake_up_send(sd, client, msg, &addr.sin_addr); } + +#define OG_WOL_CLIENT_TIMEOUT 60 + +static void og_client_wol_timer_cb(struct ev_loop *loop, ev_timer *timer, + int events) +{ + struct og_client_wol *cli_wol; + + cli_wol = container_of(timer, struct og_client_wol, timer); + + syslog(LOG_ERR, "timeout WakeOnLAN request for client %s\n", + inet_ntoa(cli_wol->addr)); + list_del(&cli_wol->list); + free(cli_wol); +} + +struct og_client_wol *og_client_wol_create(const struct in_addr *addr) +{ + struct og_client_wol *cli_wol; + + cli_wol = calloc(1, sizeof(struct og_client_wol)); + if (!cli_wol) + return NULL; + + cli_wol->addr = *addr; + + ev_timer_init(&cli_wol->timer, og_client_wol_timer_cb, + OG_WOL_CLIENT_TIMEOUT, 0.); + ev_timer_start(og_loop, &cli_wol->timer); + + return cli_wol; +} + +void og_client_wol_refresh(struct og_client_wol *cli_wol) +{ + ev_timer_again(og_loop, &cli_wol->timer); +} + +void og_client_wol_destroy(struct og_client_wol *cli_wol) +{ + ev_timer_stop(og_loop, &cli_wol->timer); + list_del(&cli_wol->list); + free(cli_wol); +} + +const char *og_client_wol_status(const struct og_client_wol *wol) +{ + return "WOL_SENT"; +} diff --git a/src/wol.h b/src/wol.h index 8682520..a245592 100644 --- a/src/wol.h +++ b/src/wol.h @@ -5,6 +5,8 @@ #define OG_WOL_MACADDR_LEN 6 #define OG_WOL_REPEAT 16 +#include "list.h" +#include #include struct wol_msg { @@ -18,4 +20,16 @@ bool wake_up_send(int sd, struct sockaddr_in *client, bool wake_up_broadcast(int sd, struct sockaddr_in *client, const struct wol_msg *msg); +struct og_client_wol { + struct list_head list; + struct in_addr addr; + struct ev_timer timer; +}; + +struct og_client_wol *og_client_wol_create(const struct in_addr *addr); +struct og_client_wol *og_client_wol_find(const struct in_addr *addr); +void og_client_wol_refresh(struct og_client_wol *cli_wol); +void og_client_wol_destroy(struct og_client_wol *cli_wol); +const char *og_client_wol_status(const struct og_client_wol *wol); + #endif -- cgit v1.2.3-18-g5258