mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
ws: replace evws_send with evws_send_text/evws_send_binary (ABI breakage) (#1500)
Replace evws_send with evws_send_text, and introduce new API - evws_send_binary, that can be used to send binary frames. But note, that this commit breaks the ABI compatibility, but it should be OK, since there was only alpha release with evws_send, and nobody should rely on this, and I hope nobody does (we decided to go this way to avoid supporting deprecated API).
This commit is contained in:
parent
21d2f5a415
commit
f39ad1c494
@ -34,10 +34,14 @@ EVENT2_EXPORT_SYMBOL
|
||||
struct evws_connection *evws_new_session(
|
||||
struct evhttp_request *req, ws_on_msg_cb, void *arg, int options);
|
||||
|
||||
/** Sends data over WebSocket connection */
|
||||
/** Sends text data over WebSocket connection */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evws_send(
|
||||
struct evws_connection *evws, const char *packet_str, size_t str_len);
|
||||
void evws_send_text(struct evws_connection *evws, const char *packet_str);
|
||||
|
||||
/** Sends binary data over WebSocket connection */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
void evws_send_binary(
|
||||
struct evws_connection *evws, const char *packet_data, size_t packet_len);
|
||||
|
||||
/** Closes a WebSocket connection with reason code */
|
||||
EVENT2_EXPORT_SYMBOL
|
||||
|
@ -66,7 +66,7 @@ broadcast_msg(char *msg)
|
||||
struct client *client;
|
||||
|
||||
TAILQ_FOREACH (client, &clients, next) {
|
||||
evws_send(client->evws, msg, strlen(msg));
|
||||
evws_send_text(client->evws, msg);
|
||||
}
|
||||
log_d("%s\n", msg);
|
||||
}
|
||||
|
@ -89,10 +89,13 @@ on_ws_msg_cb(struct evws_connection *evws, int type, const unsigned char *data,
|
||||
if (!strcmp(msg, "Send echo")) {
|
||||
const char *reply = "Reply echo";
|
||||
|
||||
evws_send(evws, reply, strlen(reply));
|
||||
evws_send_text(evws, reply);
|
||||
test_ok++;
|
||||
} else if (!strcmp(msg, "Client: hello")) {
|
||||
test_ok++;
|
||||
} else if (!strcmp(msg, "Bye")) {
|
||||
evws_send_binary(evws, "\xde\xad\xbe\xef\x55", 5);
|
||||
test_ok++;
|
||||
} else if (!strcmp(msg, "Close")) {
|
||||
evws_close(evws, 0);
|
||||
test_ok++;
|
||||
@ -126,7 +129,7 @@ http_on_ws_cb(struct evhttp_request *req, void *arg)
|
||||
test_ok++;
|
||||
|
||||
evws_connection_set_closecb(evws, on_ws_close_cb, (void *)0xDEADBEEF);
|
||||
evws_send(evws, hello, strlen(hello));
|
||||
evws_send_text(evws, hello);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -140,10 +143,10 @@ http_ws_errorcb(struct bufferevent *bev, short what, void *arg)
|
||||
}
|
||||
|
||||
static char *
|
||||
receive_ws_msg(struct evbuffer *buf, size_t *out_len, unsigned *options)
|
||||
receive_ws_msg(struct evbuffer *buf, size_t *out_len, bool *is_text_type)
|
||||
{
|
||||
unsigned char *data;
|
||||
int fin, opcode, mask;
|
||||
int opcode, mask;
|
||||
uint64_t payload_len;
|
||||
size_t header_len;
|
||||
const unsigned char *mask_key;
|
||||
@ -153,7 +156,6 @@ receive_ws_msg(struct evbuffer *buf, size_t *out_len, unsigned *options)
|
||||
|
||||
data = evbuffer_pullup(buf, data_len);
|
||||
|
||||
fin = !!(*data & 0x80);
|
||||
opcode = *data & 0x0F;
|
||||
mask = !!(*(data + 1) & 0x80);
|
||||
payload_len = *(data + 1) & 0x7F;
|
||||
@ -191,32 +193,32 @@ receive_ws_msg(struct evbuffer *buf, size_t *out_len, unsigned *options)
|
||||
/* text */
|
||||
if (opcode == 0x01) {
|
||||
out_buf = calloc(payload_len + 1, 1);
|
||||
*is_text_type = true;
|
||||
} else { /* binary */
|
||||
out_buf = malloc(payload_len);
|
||||
}
|
||||
memcpy(out_buf, (const char *)data + header_len, payload_len);
|
||||
|
||||
if (!fin) {
|
||||
*options = 1;
|
||||
}
|
||||
|
||||
evbuffer_drain(buf, header_len + payload_len);
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
enum WSOptions {
|
||||
WS_FIN = 1 << 7,
|
||||
WS_TEXT = 1 << 1,
|
||||
WS_BINARY = 0 << 1,
|
||||
};
|
||||
|
||||
static void
|
||||
send_ws_msg(struct evbuffer *buf, const char *msg, bool final)
|
||||
send_ws_msg(
|
||||
struct evbuffer *buf, const char *msg, size_t len, enum WSOptions options)
|
||||
{
|
||||
size_t len = strlen(msg);
|
||||
uint8_t a = 0, b = 0, c = 0, d = 0;
|
||||
uint8_t mask_key[4] = {1, 2, 3, 4}; /* should be random */
|
||||
uint8_t m;
|
||||
size_t i;
|
||||
|
||||
if (final)
|
||||
a |= 1 << 7; /* fin */
|
||||
a |= 1; /* text frame */
|
||||
|
||||
a = options;
|
||||
b |= 1 << 7; /* mask */
|
||||
|
||||
/* payload len */
|
||||
@ -254,20 +256,31 @@ http_ws_readcb_phase2(struct bufferevent *bev, void *arg)
|
||||
|
||||
while (evbuffer_get_length(input) >= 2) {
|
||||
size_t len = 0;
|
||||
unsigned options = 0;
|
||||
bool is_text_type = false;
|
||||
char *msg;
|
||||
|
||||
msg = receive_ws_msg(input, &len, &options);
|
||||
msg = receive_ws_msg(input, &len, &is_text_type);
|
||||
if (msg) {
|
||||
if (!strcmp(msg, "Server: hello")) {
|
||||
send_ws_msg(output, "Send ", false);
|
||||
send_ws_msg(output, "echo", true);
|
||||
test_ok++;
|
||||
} else if (!strcmp(msg, "Reply echo")) {
|
||||
send_ws_msg(output, "Close", true);
|
||||
test_ok++;
|
||||
if (is_text_type) {
|
||||
if (!strcmp(msg, "Server: hello")) {
|
||||
send_ws_msg(output, "Send ", strlen("Send "), WS_TEXT);
|
||||
send_ws_msg(
|
||||
output, "echo", strlen("echo"), WS_TEXT | WS_FIN);
|
||||
test_ok++;
|
||||
} else if (!strcmp(msg, "Reply echo")) {
|
||||
send_ws_msg(output, "Bye", strlen("Bye"), WS_TEXT | WS_FIN);
|
||||
test_ok++;
|
||||
} else {
|
||||
test_ok--;
|
||||
}
|
||||
} else {
|
||||
test_ok--;
|
||||
if (len == 5 && !memcmp(msg, "\xde\xad\xbe\xef\x55", 5)) {
|
||||
send_ws_msg(
|
||||
output, "Close", strlen("Close"), WS_TEXT | WS_FIN);
|
||||
test_ok++;
|
||||
} else {
|
||||
test_ok--;
|
||||
}
|
||||
}
|
||||
free(msg);
|
||||
}
|
||||
@ -293,9 +306,9 @@ http_ws_readcb_hdr(struct bufferevent *bev, void *arg)
|
||||
free(line);
|
||||
bufferevent_setcb(
|
||||
bev, http_ws_readcb_phase2, http_writecb, http_ws_errorcb, arg);
|
||||
send_ws_msg(output, "Client:", false);
|
||||
send_ws_msg(output, " ", false);
|
||||
send_ws_msg(output, "hello", true);
|
||||
send_ws_msg(output, "Client:", strlen("Client:"), WS_TEXT);
|
||||
send_ws_msg(output, " ", strlen(" "), WS_TEXT);
|
||||
send_ws_msg(output, "hello", strlen("hello"), WS_TEXT | WS_FIN);
|
||||
test_ok++;
|
||||
if (evbuffer_get_length(input) > 0) {
|
||||
http_ws_readcb_phase2(bev, arg);
|
||||
@ -369,7 +382,7 @@ http_ws_test(void *arg)
|
||||
|
||||
test_ok = 0;
|
||||
event_base_dispatch(data->base);
|
||||
tt_int_op(test_ok, ==, 13);
|
||||
tt_int_op(test_ok, ==, 16);
|
||||
|
||||
evhttp_free(http);
|
||||
end:
|
||||
|
24
ws.c
24
ws.c
@ -71,6 +71,10 @@ enum WebSocketFrameType {
|
||||
PONG_FRAME = 0xA
|
||||
};
|
||||
|
||||
|
||||
static void evws_send(struct evws_connection *evws,
|
||||
enum WebSocketFrameType frame_type, const char *packet_str, size_t str_len);
|
||||
|
||||
/*
|
||||
* Clean up a WebSockets connection object
|
||||
*/
|
||||
@ -432,17 +436,31 @@ make_ws_frame(struct evbuffer *output, enum WebSocketFrameType frame_type,
|
||||
evbuffer_add(output, msg, len);
|
||||
}
|
||||
|
||||
void
|
||||
evws_send(struct evws_connection *evws, const char *packet_str, size_t str_len)
|
||||
static void
|
||||
evws_send(struct evws_connection *evws, enum WebSocketFrameType frame_type,
|
||||
const char *packet_str, size_t str_len)
|
||||
{
|
||||
struct evbuffer *output;
|
||||
|
||||
bufferevent_lock(evws->bufev);
|
||||
output = bufferevent_get_output(evws->bufev);
|
||||
make_ws_frame(output, TEXT_FRAME, (unsigned char *)packet_str, str_len);
|
||||
make_ws_frame(output, frame_type, (unsigned char *)packet_str, str_len);
|
||||
bufferevent_unlock(evws->bufev);
|
||||
}
|
||||
|
||||
void
|
||||
evws_send_text(struct evws_connection *evws, const char *packet_str)
|
||||
{
|
||||
evws_send(evws, TEXT_FRAME, packet_str, strlen(packet_str));
|
||||
}
|
||||
|
||||
void
|
||||
evws_send_binary(
|
||||
struct evws_connection *evws, const char *packet_data, size_t packet_len)
|
||||
{
|
||||
evws_send(evws, BINARY_FRAME, packet_data, packet_len);
|
||||
}
|
||||
|
||||
void
|
||||
evws_connection_set_closecb(
|
||||
struct evws_connection *evws, ws_on_close_cb cb, void *cbarg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user