aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/net.c44
-rw-r--r--net/ws.c10
2 files changed, 31 insertions, 23 deletions
diff --git a/net/net.c b/net/net.c
index bad34c6..72536f9 100644
--- a/net/net.c
+++ b/net/net.c
@@ -25,19 +25,10 @@ int net_subsystem(void)
{
print(LOG_INFO "net: starting net subsystem");
- /* Set handler for heartbeats */
- /*
- struct sigaction *alrmhandler = malloc(sizeof(struct sigaction));
- memset(alrmhandler, 0, sizeof(struct sigaction));
- alrmhandler->sa_handler = &ws_send_heartbeat;
- alrmhandler->sa_flags |= SA_RESTART;
- sigaction(SIGALRM, alrmhandler, NULL);
- free(alrmhandler);
- */
-
if(!gateway_url)
panic("net: gateway url invalid");
+ /* Initialise CURL */
ws_handle = curl_easy_init();
curl_easy_setopt(ws_handle, CURLOPT_URL, gateway_url);
@@ -54,13 +45,6 @@ int net_subsystem(void)
CURLINFO_ACTIVESOCKET, &ws_sockfd)) != CURLE_OK)
panic("net: curl cannot get active socket (errno %d)", ret);
-/* struct pollfd ws_sockpoll = {
- .fd = ws_sockfd,
- .events = POLLIN
- }; */
- char *inbuf = malloc(1<<16 * sizeof(char));
- size_t rlen;
- const struct curl_ws_frame *meta;
/* Block ALRM */
sigset_t *set = malloc(sizeof(sigset_t));
@@ -69,6 +53,7 @@ int net_subsystem(void)
int alrmfd = signalfd(-1, set, 0);
free(set);
+ /* Prepare poll */
struct pollfd pollarray[2] = {
{
.fd = ws_sockfd,
@@ -85,14 +70,23 @@ int net_subsystem(void)
struct pollfd *sockpoll = &(pollarray[0]);
struct pollfd *alrmpoll = &(pollarray[1]);
+ /* Misc. variables */
+ char *inbuf = malloc(1<<16 * sizeof(char));
+ size_t rlen;
+ const struct curl_ws_frame *meta;
+
errno = 0;
do {
if((sockpoll->revents & POLLIN) == POLLIN) {
ret = curl_ws_recv(ws_handle, inbuf, 1<<16, &rlen, &meta);
+ /* sometimes only SSL information gets sent through, so no actual
+ data is received. curl uses NONBLOCK internally so it lets us
+ know if there is no more data remaining */
if(ret == CURLE_AGAIN)
continue;
if(ret != CURLE_OK) {
- print(LOG_ERR "net: encountered curl error while reading socket (curl errno %d)", ret);
+ print(LOG_ERR "net: encountered curl error while reading "
+ "socket (curl errno %d)", ret);
break;
}
@@ -109,8 +103,10 @@ int net_subsystem(void)
}
ws_handle_event(event);
cJSON_Delete(event);
- } else if((sockpoll->revents & (POLLRDHUP | POLLERR | POLLHUP | POLLNVAL)) > 0) {
- print(LOG_ERR "net: encountered error on socket (revents %d)", sockpoll->revents);
+ } else if((sockpoll->revents &
+ (POLLRDHUP | POLLERR | POLLHUP | POLLNVAL)) > 0) {
+ print(LOG_ERR "net: encountered error on socket (revents %d)",
+ sockpoll->revents);
break;
}
@@ -120,8 +116,10 @@ int net_subsystem(void)
ws_send_heartbeat();
}
} while(poll(pollarray, 2, -1) >= 0);
+
if(errno > 0) {
- print(LOG_ERR "net: error encountered while polling (errno %d)", errno);
+ print(LOG_ERR "net: error encountered while polling"
+ " (errno %d)", errno);
}
free(inbuf);
@@ -135,6 +133,7 @@ int net_subsystem(void)
void net_get_gateway_url()
{
+ /* determine if websockets are supported */
curl_version_info_data *curl_version =
curl_version_info(CURLVERSION_NOW);
const char * const* curl_protocols = curl_version->protocols;
@@ -149,6 +148,7 @@ void net_get_gateway_url()
if(!wss_supported)
panic("net: wss not supported by libcurl");
+ /* fetch preferred url from discord */
int fd = http_get("https://discord.com/api/gateway/bot");
if(fd < 0) {
print(LOG_ERR "net: failed to get gateway url (error %d)", -fd);
@@ -170,6 +170,8 @@ void net_get_gateway_url()
goto assume;
}
+ /* curl requires websocket secure URLs to begin with WSS instead
+ of wss, so we fix up the received url for curl */
gateway_url = calloc(strlen(gateway_url_json->valuestring) + 1,
sizeof(char));
strcpy(gateway_url, gateway_url_json->valuestring);
diff --git a/net/ws.c b/net/ws.c
index 9ad857d..8f3a588 100644
--- a/net/ws.c
+++ b/net/ws.c
@@ -21,6 +21,10 @@ void ws_send_heartbeat()
size_t sent;
curl_ws_send(ws_handle, buf, strnlen(buf, 128), &sent, 0, CURLWS_TEXT);
+ /* if we receive a heartbeat request from discord, we need to fix
+ the itimer so we don't send another one before the desired
+ heartbeat interval. if our itimer is off more than 2 seconds
+ then we fix it up and reset it */
struct itimerval itimer;
getitimer(ITIMER_REAL, &itimer);
if(itimer.it_value.tv_sec < heartbeat_time.tv_sec - 2) {
@@ -32,12 +36,14 @@ void ws_send_heartbeat()
void ws_handle_event(cJSON *event)
{
int op = cJSON_GetObjectItem(event, "op")->valueint;
+ cJSON *data = cJSON_GetObjectItem(event, "d")
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;
+ int heartbeat_wait = cJSON_GetObjectItem(data,
+ "heartbeat_interval")->valueint;
float jitter = (float)rand() / (RAND_MAX * 1.0f);
heartbeat_time.tv_sec = heartbeat_wait / 1000;
@@ -52,7 +58,7 @@ void ws_handle_event(cJSON *event)
};
setitimer(ITIMER_REAL, &new_itimer, NULL);
break;
- case 11:
+ case 11: /* Heartbeat ACK */
break;
default:
print(LOG_ERR "ws: received unknown WS opcode %d", op);