WebSocket client example using Nilorea network module.
#include <getopt.h>
#include <string.h>
fprintf(stderr,
" -V 'log level' : set the log level (LOG_NULL, LOG_NOTICE, LOG_INFO, LOG_ERR, LOG_DEBUG)\n"
" -h : help\n");
}
int fails = 0;
unsigned char out[512];
unsigned char mask[4] = {0x12, 0x34, 0x56, 0x78};
size_t consumed = 0;
{
if (w != 7) fails++;
if (consumed != 7 || memcmp(f.
payload,
"hello", 5) != 0) fails++;
}
{
unsigned char plain[8];
if (w != 10) fails++;
if (memcmp(plain, "abcd", 4) != 0) fails++;
}
{
unsigned char big[200];
size_t i, w;
for (i = 0; i < sizeof(big); i++) big[i] = (unsigned char)(i & 0xFF);
if (w != 4 + sizeof(big)) fails++;
}
{
}
{
size_t total = w1 + w2;
if (
n_ws_frame_parse(out, total, &f, &consumed) != 1 || consumed != w1) fails++;
if (memcmp(f.
payload,
"one", 3) != 0) fails++;
if (
n_ws_frame_parse(out + consumed, total - consumed, &f, &consumed) != 1) fails++;
}
if (fails)
else
return fails;
}
int main(
int argc,
char* argv[]) {
while ((
getoptret = getopt(argc, argv,
"hV:")) != EOF) {
case 'V':
if (!strncmp("LOG_NULL", optarg, 8)) {
} else if (!strncmp("LOG_NOTICE", optarg, 10)) {
} else if (!strncmp("LOG_INFO", optarg, 8)) {
} else if (!strncmp("LOG_ERR", optarg, 7)) {
} else if (!strncmp("LOG_DEBUG", optarg, 9)) {
} else {
fprintf(stderr, "%s is not a valid log level.\n", optarg);
exit(1);
}
break;
case 'h':
default:
exit(1);
}
}
exit(1);
#ifdef HAVE_OPENSSL
n_log(
LOG_INFO,
"Connecting to wss://echo.websocket.org:443/ ...");
if (!ws) {
fprintf(stdout, "WebSocket echo server unreachable, skipping\n");
exit(0);
}
memset(&greeting, 0, sizeof(greeting));
}
const char* test_msg = "nilorea ws test";
exit(1);
}
memset(&msg, 0, sizeof(msg));
fprintf(stdout, "WebSocket echo test PASSED\n");
} else {
fprintf(stdout,
"WebSocket echo test: got response (opcode %d)\n", msg.
opcode);
}
} else {
exit(1);
}
#else
fprintf(stdout, "OpenSSL not available, skipping WebSocket test\n");
#endif
exit(0);
}
static int test_frame_codec(void)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
int masked
MASK bit (client-to-server frames are masked)
int opcode
opcode (N_WS_OP_*)
int fin
FIN bit (1 = final fragment)
uint64_t payload_len
payload length in bytes
const unsigned char * payload
pointer into the input buffer (still masked)
N_STR * payload
message payload
unsigned char mask[4]
masking key when masked, else zeroed
void n_ws_unmask(unsigned char *dst, const unsigned char *src, size_t len, const unsigned char mask[4])
XOR-unmask len bytes of src into dst using a 4-byte WebSocket mask key.
int n_ws_frame_parse(const unsigned char *buf, size_t len, N_WS_FRAME *frame, size_t *consumed)
Parse one WebSocket frame from a byte buffer (stateless, no allocation).
N_WS_CONN * n_ws_connect(const char *host, const char *port, const char *path, int use_ssl)
Connect to a WebSocket server (ws:// or wss://).
#define N_WS_OP_TEXT
WebSocket opcodes per RFC 6455.
int n_ws_recv(N_WS_CONN *conn, N_WS_MESSAGE *msg_out)
Receive one WebSocket frame.
size_t n_ws_frame_build(int fin, int opcode, int do_mask, const unsigned char *payload, size_t len, const unsigned char mask_key[4], unsigned char *out, size_t out_cap)
build a WebSocket frame into out (optionally masking the payload).
void n_ws_conn_free(N_WS_CONN **conn)
Free a WebSocket connection structure.
int n_ws_send(N_WS_CONN *conn, const char *payload, size_t len, int opcode)
Send a WebSocket frame (client always masks).
A single parsed WebSocket frame (RFC 6455).
N_STR and string function declaration.