aboutsummaryrefslogtreecommitdiffstats
path: root/net/ws.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ws.c')
-rw-r--r--net/ws.c61
1 files changed, 61 insertions, 0 deletions
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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <cJSON.h>
+#include <curl/curl.h>
+
+#include <log.h>
+
+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;
+ }
+}