/*
- * wsockd.c: charybdis websockets helper
+ * wsockd.c: solanum websockets helper
* Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
* Copyright (C) 2007 ircd-ratbox development team
- * Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
+ * Copyright (C) 2016 Ariadne Conill <ariadne@dereferenced.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
char client_key[37]; /* maximum 36 bytes + nul */
} conn_t;
-#define WEBSOCKET_OPCODE_CONTINUATION_FRAME 0
#define WEBSOCKET_OPCODE_TEXT_FRAME 1
-#define WEBSOCKET_OPCODE_BINARY_FRAME 2
-#define WEBSOCKET_OPCODE_CLOSE_FRAME 8
-#define WEBSOCKET_OPCODE_PING_FRAME 9
-#define WEBSOCKET_OPCODE_PONG_FRAME 10
#define WEBSOCKET_MASK_LENGTH 4
uint8_t payload_length_mask; // payload_length: 7, mask: 1
} ws_frame_hdr_t;
+#define WEBSOCKET_FRAME_HDR_INIT ((ws_frame_hdr_t) { 0, 0 })
+
typedef struct {
ws_frame_hdr_t header;
uint8_t payload_data[WEBSOCKET_MAX_UNEXTENDED_PAYLOAD_DATA_LENGTH];
uint16_t payload_length_extended;
} ws_frame_ext_t;
+#define WEBSOCKET_FRAME_EXT_INIT ((ws_frame_ext_t) { WEBSOCKET_FRAME_HDR_INIT, 0 })
+
typedef struct {
ws_frame_hdr_t header;
uint64_t payload_length_extended;
} ws_frame_ext2_t;
-static inline int
-ws_frame_get_opcode(ws_frame_hdr_t *header)
-{
- return header->opcode_rsv_fin & 0xF;
-}
-
static inline void
ws_frame_set_opcode(ws_frame_hdr_t *header, int opcode)
{
header->opcode_rsv_fin |= opcode & 0xF;
}
-static inline int
-ws_frame_get_fin(ws_frame_hdr_t *header)
-{
- return (header->opcode_rsv_fin >> 7) & 0x1;
-}
-
static inline void
ws_frame_set_fin(ws_frame_hdr_t *header, int fin)
{
header->opcode_rsv_fin |= (fin << 7) & (0x1 << 7);
}
-#ifdef _WIN32
-char *
-strcasestr(const char *s, const char *find)
-{
- char c, sc;
- size_t len;
-
- if ((c = *find++) != 0) {
- c = tolower((unsigned char)c);
- len = strlen(find);
- do {
- do {
- if ((sc = *s++) == 0)
- return (NULL);
- } while ((char)tolower((unsigned char)sc) != c);
- } while (strnicmp(s, find, len) != 0);
- s--;
- }
- return ((char *)s);
-}
-#endif
-
static void close_conn(conn_t * conn, int wait_plain, const char *fmt, ...);
static void conn_mod_read_cb(rb_fde_t *fd, void *data);
static void conn_plain_read_cb(rb_fde_t *fd, void *data);
#define IsCork(x) ((x)->flags & FLAG_CORK)
#define IsDead(x) ((x)->flags & FLAG_DEAD)
-#define IsWS(x) ((x)->flags & FLAG_WSOCK)
#define IsKeyed(x) ((x)->flags & FLAG_KEYED)
#define SetCork(x) ((x)->flags |= FLAG_CORK)
#define SetKeyed(x) ((x)->flags |= FLAG_KEYED)
#define ClearCork(x) ((x)->flags &= ~FLAG_CORK)
-#define ClearDead(x) ((x)->flags &= ~FLAG_DEAD)
-#define ClearWS(x) ((x)->flags &= ~FLAG_WSOCK)
-#define ClearKeyed(x) ((x)->flags &= ~FLAG_KEYED)
#define NO_WAIT 0x0
#define WAIT_PLAIN 0x1
-#define HASH_WALK_SAFE(i, max, ptr, next, table) for(i = 0; i < max; i++) { RB_DLINK_FOREACH_SAFE(ptr, next, table[i].head)
-#define HASH_WALK_END }
#define CONN_HASH_SIZE 2000
#define connid_hash(x) (&connid_hash_table[(x % CONN_HASH_SIZE)])
static void conn_plain_read_shutdown_cb(rb_fde_t *fd, void *data);
-#ifndef _WIN32
static void
dummy_handler(int sig)
{
return;
}
-#endif
static void
setup_signals()
{
-#ifndef _WIN32
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = dummy_handler;
sigaction(SIGALRM, &act, 0);
-#endif
}
static int
return MAXCONNECTIONS;
}
-static conn_t *
-conn_find_by_id(uint32_t id)
-{
- rb_dlink_node *ptr;
- conn_t *conn;
-
- RB_DLINK_FOREACH(ptr, (connid_hash(id))->head)
- {
- conn = ptr->data;
- if(conn->id == id && !IsDead(conn))
- return conn;
- }
- return NULL;
-}
-
static void
conn_add_id_hash(conn_t * conn, uint32_t id)
{
static void
conn_mod_write_short_frame(conn_t * conn, void *data, int len)
{
- ws_frame_hdr_t hdr;
+ ws_frame_hdr_t hdr = WEBSOCKET_FRAME_HDR_INIT;
- ws_frame_set_opcode(&hdr, WEBSOCKET_OPCODE_BINARY_FRAME);
+ ws_frame_set_opcode(&hdr, WEBSOCKET_OPCODE_TEXT_FRAME);
+ ws_frame_set_fin(&hdr, 1);
hdr.payload_length_mask = (len + 2) & 0x7f;
conn_mod_write(conn, &hdr, sizeof(hdr));
static void
conn_mod_write_long_frame(conn_t * conn, void *data, int len)
{
- ws_frame_ext_t hdr;
+ ws_frame_ext_t hdr = WEBSOCKET_FRAME_EXT_INIT;
- ws_frame_set_opcode(&hdr.header, WEBSOCKET_OPCODE_BINARY_FRAME);
+ ws_frame_set_opcode(&hdr.header, WEBSOCKET_OPCODE_TEXT_FRAME);
+ ws_frame_set_fin(&hdr.header, 1);
hdr.header.payload_length_mask = 126;
hdr.payload_length_extended = htons(len + 2);
return;
if (len < 123)
- return conn_mod_write_short_frame(conn, data, len);
-
- return conn_mod_write_long_frame(conn, data, len);
-}
-
-static void
-conn_plain_write(conn_t * conn, void *data, size_t len)
-{
- if(IsDead(conn)) /* again no point in queueing to dead men */
+ {
+ conn_mod_write_short_frame(conn, data, len);
return;
- rb_linebuf_put(&conn->plainbuf_out, data, len);
+ }
+
+ conn_mod_write_long_frame(conn, data, len);
}
static void
if (!dolen)
break;
- if ((p = strcasestr(inbuf, "Sec-WebSocket-Key:")) != NULL)
+ if ((p = rb_strcasestr(inbuf, "Sec-WebSocket-Key:")) != NULL)
{
char *start, *end;
length = rb_read(fd, inbuf, sizeof(inbuf));
- if (length < 0)
+ if (length < 0)
{
if (rb_ignore_errno(errno))
{
else
conn_mod_process(conn);
- if (length < sizeof(inbuf))
+ if ((size_t) length < sizeof(inbuf))
{
rb_setselect(fd, RB_SELECT_READ, conn_mod_read_cb, conn);
return;
main(int argc, char **argv)
{
const char *s_ctlfd, *s_pipe, *s_pid;
- int ctlfd, pipefd, x, maxfd;
+ int ctlfd, pipefd, maxfd, x;
maxfd = maxconn();
s_ctlfd = getenv("CTL_FD");
if(s_ctlfd == NULL || s_pipe == NULL || s_pid == NULL)
{
fprintf(stderr,
- "This is the charybdis wsockd for internal ircd use.\n");
+ "This is the solanum wsockd for internal ircd use.\n");
fprintf(stderr,
"You aren't supposed to run me directly. Exiting.\n");
exit(1);
ctlfd = atoi(s_ctlfd);
pipefd = atoi(s_pipe);
ppid = atoi(s_pid);
- x = 0;
-#ifndef _WIN32
+
for(x = 0; x < maxfd; x++)
{
if(x != ctlfd && x != pipefd && x > 2)
if(x > 2)
close(x);
}
-#endif
+
setup_signals();
rb_lib_init(NULL, NULL, NULL, 0, maxfd, 1024, 4096);
rb_linebuf_init(4096);