diff options
Diffstat (limited to 'contrib/src/foo/evws.h')
-rw-r--r-- | contrib/src/foo/evws.h | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/contrib/src/foo/evws.h b/contrib/src/foo/evws.h new file mode 100644 index 0000000..7967a64 --- /dev/null +++ b/contrib/src/foo/evws.h @@ -0,0 +1,197 @@ +/** + * @file + * @author Pawel Zubrycki <paw.zubr@gmail.com> + * @author 2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de) + * @copyright Simplified BSD + * + * @cond + * This program is free software: you can redistribute it and/or modify + * it under the terms of the FreeBSD license as published by the FreeBSD + * project. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the FreeBSD license along with this + * program. If not, see <http://www.opensource.org/licenses/bsd-license>. + * @endcond + */ + +#ifndef EVWS_H +#define EVWS_H + +#include <event2/event.h> +#include <event2/bufferevent.h> +#include <event2/listener.h> +#include <sys/queue.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +enum evws_opcode { + EVWS_CONTINUATION_FRAME = 0x0, + EVWS_TEXT_FRAME = 0x1, + EVWS_BINARY_FRAME = 0x2, + EVWS_CONNECTION_CLOSE = 0x8, + EVWS_PING = 0x9, + EVWS_PONG = 0xa +}; + +enum evws_conn_state { + EVWS_NULL = 0x0, + EVWS_FIRSTLINE_READ = 0x1, + EVWS_HEADER_READ = 0x2, + EVWS_CONNECTED = 0x3, + EVWS_CLOSED = 0x4, + EVWS_READING_FRAME = 0x5, +}; + +enum evws_frame_state { + EVWS_OPCODE_READ = 0x0, + EVWS_PAYLOAD_LENGTH_LENGTH_READ = 0x1, + EVWS_PAYLOAD_LENGTH_READ = 0x2, + EVWS_MASKING_KEY_READ = 0x3, + EVWS_EXTENSION_READ = 0x4, +}; + +struct evws_header { + TAILQ_ENTRY(evws_header) next; + char *key; + char *value; +}; + +struct evws_frame { + /** + * Indicates that this is the final fragment in a message. The first + * fragment MAY also be the final fragment. + */ + uint8_t fin; + + /** + * MUST be 0 unless an extension is negotiated that defines meanings + * for non-zero values. If a nonzero value is received and none of + * the negotiated extensions defines the meaning of such a nonzero + * value, the receiving endpoint MUST _Fail the WebSocket + * Connection_. + */ + uint8_t rsv; + + /** + * %x0 denotes a continuation frame + * %x1 denotes a text frame + * %x2 denotes a binary frame + * %x3-7 are reserved for further non-control frames + * %x8 denotes a connection close + * %x9 denotes a ping + * %xA denotes a pong + * %xB-F are reserved for further control frames + */ + enum evws_opcode opcode; + + /** + * Defines whether the "Payload data" is masked. + */ + uint8_t has_mask; + + /** + * The length of the "Payload data", in bytes: if 0-125, that is the + * payload length. If 126, the following 2 bytes interpreted as a + * 16-bit unsigned integer are the payload length. If 127, the + * following 8 bytes interpreted as a 64-bit unsigned integer (the + * most significant bit MUST be 0) are the payload length. + */ + uint64_t size; + uint64_t payload_read; + uint8_t payload_bytes; + + /** + * The content or payload of the frame + */ + char* data; + + /** + * All frames sent from the client to the server are masked by a + * 32-bit value that is contained within the frame. This field is + * present if the mask bit is set to 1 and is absent if the mask bit + * is set to 0. + */ + uint8_t mask[4]; + uint8_t mask_bytes; + uint8_t mask_index; + + uint8_t state; +}; + +struct evws_connection +{ + TAILQ_ENTRY(evws_connection) next; + struct evws *ws; + struct evws_frame *frame; + char *uri; + struct bufferevent *bufev; + int state; + int fd; + + // headers + TAILQ_HEAD(wsheadersq, evws_header) headers; +}; + +typedef void (*cb_type)(struct evws_connection *, const char *, size_t, void *); +typedef void (*cb_frame_type)(struct evws_connection *, struct evws_frame *, void *); + +struct evws_cb +{ + TAILQ_ENTRY(evws_cb) next; + char * uri; + cb_frame_type msg_cb; + cb_type conn_cb; + void * cb_arg; +}; + +struct evws_read_buf +{ + TAILQ_ENTRY(evws_read_buf) next; + char* data; +}; + +TAILQ_HEAD(evwsconq, evws_connection); + +struct evws +{ + struct evconnlistener *listener; + TAILQ_HEAD(wscbq, evws_cb) callbacks; + struct evwsconq connections; + + // generic callback + cb_frame_type gencb; + void * gencb_arg; + struct event_base *base; +}; + +struct evws_connection *evws_connection_new(struct evws *ws, evutil_socket_t fd); +void evws_connection_free(struct evws_connection *conn); + +struct evws_frame *evws_frame_new(); +void evws_frame_free(struct evws_frame *frame); + +struct evws *evws_new(struct event_base *base); +void evws_free(struct evws *ptr); + +struct evws_header *evws_header_new(char *key, char *value); +void evws_header_free(struct evws_header *header); + +char *evws_find_header(const struct wsheadersq *q, const char *key); +evutil_socket_t evws_bind_socket(struct evws * ws, unsigned short port); +int evws_set_cb(struct evws * ws, const char * pattern, cb_frame_type message_cb, cb_type connect_cb, void * arg); +cb_frame_type evws_set_gencb(struct evws *ws, cb_frame_type cb, void * arg); +void evws_broadcast(struct evws *ws, const char *uri, enum evws_opcode opcode, const char *data, uint64_t length); +void evws_send_data(struct evws_connection *conn, enum evws_opcode opcode, const char *data, uint64_t length); + +#ifdef __cplusplus +} +#endif + +#endif |