blob: 204819065804a8d1587c4aecbe6dc65ed85c47ed [file] [log] [blame] [raw]
#ifndef WEBSOCKET_SHOOTOUT_PUBSUB_H
/**
This test suite emulates the websocket shoot testing requirements, except that
the JSON will not be parsed.
Here are a few possible test commands:
{"type":"broadcast",
websocket-bench broadcast ws://127.0.0.1:3000/ --concurrent 10 \
--sample-size 100 --server-type binary --step-size 1000 --limit-percentile 95 \
--limit-rtt 250ms --initial-clients 1000
websocket-bench broadcast ws://127.0.0.1:3000/ --concurrent 10 \
--sample-size 100 --step-size 1000 --limit-percentile 95 \
--limit-rtt 250ms --initial-clients 1000
ab -n 1000000 -c 2000 -k http://127.0.0.1:3000/
wrk -c400 -d5 -t12 http://localhost:3000/
I also run it for a while using the following Ruby script:
sleep 10 while `websocket-bench broadcast ws://127.0.0.1:3000/ --concurrent 10 \
--sample-size 100 --server-type binary --step-size 1000 --limit-percentile 95 \
--limit-rtt 250ms --initial-clients 1000`.tap {|s| puts s; puts "zzz..."}
*/
#define WEBSOCKET_SHOOTOUT_PUBSUB_H
#include "pubsub.h" // includes the "http.h" header
#include "websockets.h" // includes the "http.h" header
#include <errno.h>
#include <string.h>
static void ws_shootout_pubsub_on_open(ws_s *ws) {
websocket_subscribe(ws, .channel.name = "text", .force_text = 1);
websocket_subscribe(ws, .channel.name = "binary", .force_binary = 1);
}
static void ws_shootout_pubsub(ws_s *ws, char *data, size_t size,
uint8_t is_text) {
(void)(ws);
(void)(is_text);
(void)(size);
if (data[0] == 'b') {
pubsub_publish(.channel.name = "binary", .msg.data = data, .msg.len = size);
// fwrite(".", 1, 1, stderr);
data[0] = 'r';
websocket_write(ws, data, size, 0);
} else if (data[9] == 'b') {
// fwrite(".", 1, 1, stderr);
pubsub_publish(.channel.name = "text", .msg.data = data, .msg.len = size);
/* send result */
size = size + (25 - 19);
void *buff = malloc(size);
memcpy(buff, "{\"type\":\"broadcastResult\"", 25);
memcpy((void *)(((uintptr_t)buff) + 25), data + 19, size - 25);
websocket_write(ws, buff, size, 1);
free(buff);
} else {
/* perform echo */
websocket_write(ws, data, size, is_text);
}
}
/*
A simple Hello World HTTP response emulation. Test with:
ab -n 1000000 -c 200 -k http://127.0.0.1:3000/
*/
static void http_websocket_shotout_pubsub(http_request_s *request) {
// to log we will start a response.
http_response_s *response = http_response_create(request);
http_response_write_header(response, .name = "Server", .name_len = 6,
.value = "facil.io/0.4.0", .value_len = 14);
// http_response_log_start(&response);
// upgrade requests to broadcast will have the following properties:
if (request->upgrade) {
// Websocket upgrade will use our existing response (never leak responses).
websocket_upgrade(.request = request, .response = response,
.on_open = ws_shootout_pubsub_on_open,
.on_message = ws_shootout_pubsub);
return;
}
http_response_write_header(response, .name = "Content-Type", .name_len = 12,
.value = "text/plain", .value_len = 10);
http_response_write_body(response,
"This is a Websocket-Shootout application!", 41);
http_response_finish(response);
}
static void listen2shootout_pubsub(const char *port, char is_logging) {
if (http_listen(port, NULL, .on_request = http_websocket_shotout_pubsub,
.log_static = is_logging))
perror("Couldn't initiate Websocket Shootout service"), exit(1);
}
#endif