/* * Wslay - The WebSocket Library * * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef WSLAY_H #define WSLAY_H #if defined(_MSC_VER) #include <BaseTsd.h> typedef SSIZE_T ssize_t; #endif #include <stdint.h> #include <stdlib.h> #include <sys/types.h> #include <functional> enum wslay_error { WSLAY_ERR_WANT_READ = -100, WSLAY_ERR_WANT_WRITE = -101, WSLAY_ERR_PROTO = -200, WSLAY_ERR_INVALID_ARGUMENT = -300, WSLAY_ERR_INVALID_CALLBACK = -301, WSLAY_ERR_NO_MORE_MSG = -302, WSLAY_ERR_CALLBACK_FAILURE = -400, WSLAY_ERR_WOULDBLOCK = -401, WSLAY_ERR_NOMEM = -500 }; enum wslay_io_flags { /*T_R * There is more data to send. */ WSLAY_MSG_MORE = 1 }; /* * Callback function used by wslay_frame_send() function when it needs * to send data. The implementation of this function must send at most * len bytes of data in data. flags is the bitwise OR of zero or more * of the following flag: * * WSLAY_MSG_MORE * There is more data to send * * It provides some hints to tune performance and behaviour. user_data * is one given in wslay_frame_context_init() function. The * implementation of this function must return the number of bytes * sent. If there is an error, return -1. The return value 0 is also * treated an error by the library. */ /*typedef ssize_t (*wslay_frame_send_callback)(const uint8_t *data, size_t len, int flags, void *user_data);*/ typedef std::function<int(const uint8_t *data, size_t len, int flags, void *user_data)> wslay_frame_send_callback; /* * Callback function used by wslay_frame_recv() function when it needs * more data. The implementation of this function must fill at most * len bytes of data into buf. The memory area of buf is allocated by * library and not be freed by the application code. flags is always 0 * in this version. user_data is one given in * wslay_frame_context_init() function. The implementation of this * function must return the number of bytes filled. If there is an * error, return -1. The return value 0 is also treated an error by * the library. */ /*typedef ssize_t (*wslay_frame_recv_callback)(uint8_t *buf, size_t len, int flags, void *user_data);*/ typedef std::function<int(uint8_t *buf, size_t len, int flags, void *user_data)> wslay_frame_recv_callback; /* * Callback function used by wslay_frame_send() function when it needs * new mask key. The implementation of this function must write * exactly len bytes of mask key to buf. user_data is one given in * wslay_frame_context_init() function. The implementation of this * function return 0 on success. If there is an error, return -1. */ /*typedef int (*wslay_frame_genmask_callback)(uint8_t *buf, size_t len, void *user_data);*/ typedef std::function<int(uint8_t *buf, size_t len, void *user_data)> wslay_frame_genmask_callback; struct wslay_frame_callbacks { wslay_frame_send_callback send_callback; wslay_frame_recv_callback recv_callback; wslay_frame_genmask_callback genmask_callback; }; /* * The opcode defined in RFC6455. */ enum wslay_opcode { WSLAY_CONTINUATION_FRAME = 0x0u, WSLAY_TEXT_FRAME = 0x1u, WSLAY_BINARY_FRAME = 0x2u, WSLAY_CONNECTION_CLOSE = 0x8u, WSLAY_PING = 0x9u, WSLAY_PONG = 0xau }; /* * Macro that returns 1 if opcode is control frame opcode, otherwise * returns 0. */ #define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1) struct wslay_frame_iocb { /* 1 for fragmented final frame, 0 for otherwise */ uint8_t fin; /* * reserved 3 bits. rsv = ((RSV1 << 2) | (RSV << 1) | RSV3). * RFC6455 requires 0 unless extensions are negotiated. */ uint8_t rsv; /* 4 bit opcode */ uint8_t opcode; /* payload length [0, 2**63-1] */ uint64_t payload_length; /* 1 for masked frame, 0 for unmasked */ uint8_t mask; /* part of payload data */ const uint8_t *data; /* bytes of data defined above */ size_t data_length; }; struct wslay_frame_context; typedef struct wslay_frame_context *wslay_frame_context_ptr; /* * Initializes ctx using given callbacks and user_data. This function * allocates memory for struct wslay_frame_context and stores the * result to *ctx. The callback functions specified in callbacks are * copied to ctx. user_data is stored in ctx and it will be passed to * callback functions. When the user code finished using ctx, it must * call wslay_frame_context_free to deallocate memory. */ int wslay_frame_context_init(wslay_frame_context_ptr *ctx, const struct wslay_frame_callbacks *callbacks, void *user_data); /* * Deallocates memory pointed by ctx. */ void wslay_frame_context_free(wslay_frame_context_ptr ctx); /* * Send WebSocket frame specified in iocb. ctx must be initialized * using wslay_frame_context_init() function. iocb->fin must be 1 if * this is a fin frame, otherwise 0. iocb->rsv is reserved bits. * iocb->opcode must be the opcode of this frame. iocb->mask must be * 1 if this is masked frame, otherwise 0. iocb->payload_length is * the payload_length of this frame. iocb->data must point to the * payload data to be sent. iocb->data_length must be the length of * the data. This function calls send_callback function if it needs * to send bytes. This function calls gen_mask_callback function if * it needs new mask key. This function returns the number of payload * bytes sent. Please note that it does not include any number of * header bytes. If it cannot send any single bytes of payload, it * returns WSLAY_ERR_WANT_WRITE. If the library detects error in iocb, * this function returns WSLAY_ERR_INVALID_ARGUMENT. If callback * functions report a failure, this function returns * WSLAY_ERR_INVALID_CALLBACK. This function does not always send all * given data in iocb. If there are remaining data to be sent, adjust * data and data_length in iocb accordingly and call this function * again. */ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, struct wslay_frame_iocb *iocb); /* * Receives WebSocket frame and stores it in iocb. This function * returns the number of payload bytes received. This does not * include header bytes. In this case, iocb will be populated as * follows: iocb->fin is 1 if received frame is fin frame, otherwise * 0. iocb->rsv is reserved bits of received frame. iocb->opcode is * opcode of received frame. iocb->mask is 1 if received frame is * masked, otherwise 0. iocb->payload_length is the payload length of * received frame. iocb->data is pointed to the buffer containing * received payload data. This buffer is allocated by the library and * must be read-only. iocb->data_length is the number of payload * bytes recieved. This function calls recv_callback if it needs to * receive additional bytes. If it cannot receive any single bytes of * payload, it returns WSLAY_ERR_WANT_READ. If the library detects * protocol violation in a received frame, this function returns * WSLAY_ERR_PROTO. If callback functions report a failure, this * function returns WSLAY_ERR_INVALID_CALLBACK. This function does * not always receive whole frame in a single call. If there are * remaining data to be received, call this function again. This * function ensures frame alignment. */ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, struct wslay_frame_iocb *iocb); struct wslay_event_context; #endif /* WSLAY_H */