From d5c873a780357928fcccb27f4378b456f0e45dd2 Mon Sep 17 00:00:00 2001 From: turret Date: Wed, 17 Jan 2024 19:13:16 +0000 Subject: net: basic ws handler includes heartbeat mechanism --- net/ws.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 net/ws.c (limited to 'net/ws.c') diff --git a/net/ws.c b/net/ws.c new file mode 100644 index 0000000..9ad857d --- /dev/null +++ b/net/ws.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +extern CURL *ws_handle; +long last_sequence = -1; +struct timeval heartbeat_time; + +void ws_send_heartbeat() +{ + char buf[128] = "{\"op\":1,\"d\":null}"; + if(last_sequence > 0) + snprintf(buf, 128, "{\"op\":1,\"d\":%ld}", last_sequence); + size_t sent; + curl_ws_send(ws_handle, buf, strnlen(buf, 128), &sent, 0, CURLWS_TEXT); + + struct itimerval itimer; + getitimer(ITIMER_REAL, &itimer); + if(itimer.it_value.tv_sec < heartbeat_time.tv_sec - 2) { + itimer.it_value = heartbeat_time; + setitimer(ITIMER_REAL, &itimer, NULL); + } +} + +void ws_handle_event(cJSON *event) +{ + int op = cJSON_GetObjectItem(event, "op")->valueint; + switch(op) { + case 1: /* Heartbeat request */ + ws_send_heartbeat(); + break; + case 10: ; /* Hello */ + int heartbeat_wait = cJSON_GetObjectItem(cJSON_GetObjectItem(event, "d"), "heartbeat_interval")->valueint; + float jitter = (float)rand() / (RAND_MAX * 1.0f); + + heartbeat_time.tv_sec = heartbeat_wait / 1000; + heartbeat_time.tv_usec = (heartbeat_wait % 1000) * 1000; + struct timeval jitter_time = { + .tv_sec = heartbeat_time.tv_sec * jitter, + .tv_usec = heartbeat_time.tv_usec * jitter, + }; + struct itimerval new_itimer = { + .it_interval = heartbeat_time, + .it_value = jitter_time + }; + setitimer(ITIMER_REAL, &new_itimer, NULL); + break; + case 11: + break; + default: + print(LOG_ERR "ws: received unknown WS opcode %d", op); + break; + } +} -- cgit v1.2.3