/* * libwebsockets - small server side websockets and web server implementation * * Copyright (C) 2010 Andy Green * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation: * version 2.1 of the License. * * This library 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. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #ifndef __LIBWEBSOCKET_H__ #define __LIBWEBSOCKET_H__ #ifdef __cplusplus extern "C" { #include #endif #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include #include #include "../win32port/win32helpers/websock-w32.h" #include "../win32port/win32helpers/gettimeofday.h" #define strcasecmp stricmp typedef int ssize_t; #ifdef LWS_DLL #ifdef LWS_INTERNAL #define LWS_EXTERN extern __declspec(dllexport) #else #define LWS_EXTERN extern __declspec(dllimport) #endif #endif #else #include #endif #ifndef LWS_EXTERN #define LWS_EXTERN extern #endif #define CONTEXT_PORT_NO_LISTEN 0 #define MAX_MUX_RECURSION 2 enum libwebsocket_context_options { LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK = 1, LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT = 2, }; enum libwebsocket_callback_reasons { LWS_CALLBACK_ESTABLISHED, LWS_CALLBACK_CLIENT_CONNECTION_ERROR, LWS_CALLBACK_CLIENT_ESTABLISHED, LWS_CALLBACK_CLOSED, LWS_CALLBACK_RECEIVE, LWS_CALLBACK_CLIENT_RECEIVE, LWS_CALLBACK_CLIENT_RECEIVE_PONG, LWS_CALLBACK_CLIENT_WRITEABLE, LWS_CALLBACK_SERVER_WRITEABLE, LWS_CALLBACK_HTTP, LWS_CALLBACK_BROADCAST, LWS_CALLBACK_FILTER_NETWORK_CONNECTION, LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION, LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, LWS_CALLBACK_CONFIRM_EXTENSION_OKAY, LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED, /* external poll() management support */ LWS_CALLBACK_ADD_POLL_FD, LWS_CALLBACK_DEL_POLL_FD, LWS_CALLBACK_SET_MODE_POLL_FD, LWS_CALLBACK_CLEAR_MODE_POLL_FD, }; enum libwebsocket_extension_callback_reasons { LWS_EXT_CALLBACK_SERVER_CONTEXT_CONSTRUCT, LWS_EXT_CALLBACK_CLIENT_CONTEXT_CONSTRUCT, LWS_EXT_CALLBACK_SERVER_CONTEXT_DESTRUCT, LWS_EXT_CALLBACK_CLIENT_CONTEXT_DESTRUCT, LWS_EXT_CALLBACK_CONSTRUCT, LWS_EXT_CALLBACK_CLIENT_CONSTRUCT, LWS_EXT_CALLBACK_CHECK_OK_TO_REALLY_CLOSE, LWS_EXT_CALLBACK_CHECK_OK_TO_PROPOSE_EXTENSION, LWS_EXT_CALLBACK_DESTROY, LWS_EXT_CALLBACK_DESTROY_ANY_WSI_CLOSING, LWS_EXT_CALLBACK_ANY_WSI_ESTABLISHED, LWS_EXT_CALLBACK_PACKET_RX_PREPARSE, LWS_EXT_CALLBACK_PACKET_TX_PRESEND, LWS_EXT_CALLBACK_PACKET_TX_DO_SEND, LWS_EXT_CALLBACK_HANDSHAKE_REPLY_TX, LWS_EXT_CALLBACK_FLUSH_PENDING_TX, LWS_EXT_CALLBACK_EXTENDED_PAYLOAD_RX, LWS_EXT_CALLBACK_CAN_PROXY_CLIENT_CONNECTION, LWS_EXT_CALLBACK_1HZ, LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE, LWS_EXT_CALLBACK_IS_WRITEABLE, }; enum libwebsocket_write_protocol { LWS_WRITE_TEXT, LWS_WRITE_BINARY, LWS_WRITE_CONTINUATION, LWS_WRITE_HTTP, /* special 04+ opcodes */ LWS_WRITE_CLOSE, LWS_WRITE_PING, LWS_WRITE_PONG, /* flags */ LWS_WRITE_NO_FIN = 0x40, /* * client packet payload goes out on wire unmunged * only useful for security tests since normal servers cannot * decode the content if used */ LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80 }; /* * you need these to look at headers that have been parsed if using the * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum * list below is absent, .token = NULL and token_len = 0. Otherwise .token * points to .token_len chars containing that header content. */ struct lws_tokens { char *token; int token_len; }; enum lws_token_indexes { WSI_TOKEN_GET_URI, WSI_TOKEN_HOST, WSI_TOKEN_CONNECTION, WSI_TOKEN_KEY1, WSI_TOKEN_KEY2, WSI_TOKEN_PROTOCOL, WSI_TOKEN_UPGRADE, WSI_TOKEN_ORIGIN, WSI_TOKEN_DRAFT, WSI_TOKEN_CHALLENGE, /* new for 04 */ WSI_TOKEN_KEY, WSI_TOKEN_VERSION, WSI_TOKEN_SWORIGIN, /* new for 05 */ WSI_TOKEN_EXTENSIONS, /* client receives these */ WSI_TOKEN_ACCEPT, WSI_TOKEN_NONCE, WSI_TOKEN_HTTP, WSI_TOKEN_MUXURL, /* always last real token index*/ WSI_TOKEN_COUNT, /* parser state additions */ WSI_TOKEN_NAME_PART, WSI_TOKEN_SKIPPING, WSI_TOKEN_SKIPPING_SAW_CR, WSI_PARSING_COMPLETE, WSI_INIT_TOKEN_MUXURL, }; /* * From 06 spec 1000 1000 indicates a normal closure, meaning whatever purpose the connection was established for has been fulfilled. 1001 1001 indicates that an endpoint is "going away", such as a server going down, or a browser having navigated away from a page. 1002 1002 indicates that an endpoint is terminating the connection due to a protocol error. 1003 1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g. an endpoint that understands only text data may send this if it receives a binary message.) 1004 1004 indicates that an endpoint is terminating the connection because it has received a message that is too large. */ enum lws_close_status { LWS_CLOSE_STATUS_NOSTATUS = 0, LWS_CLOSE_STATUS_NORMAL = 1000, LWS_CLOSE_STATUS_GOINGAWAY = 1001, LWS_CLOSE_STATUS_PROTOCOL_ERR = 1002, LWS_CLOSE_STATUS_UNACCEPTABLE_OPCODE = 1003, LWS_CLOSE_STATUS_PAYLOAD_TOO_LARGE = 1004, }; struct libwebsocket; struct libwebsocket_context; struct libwebsocket_extension; /** * callback_function() - User server actions * @context: Websockets context * @wsi: Opaque websocket instance pointer * @reason: The reason for the call * @user: Pointer to per-session user data allocated by library * @in: Pointer used for some callback reasons * @len: Length set for some callback reasons * * This callback is the way the user controls what is served. All the * protocol detail is hidden and handled by the library. * * For each connection / session there is user data allocated that is * pointed to by "user". You set the size of this user data area when * the library is initialized with libwebsocket_create_server. * * You get an opportunity to initialize user data when called back with * LWS_CALLBACK_ESTABLISHED reason. * * LWS_CALLBACK_ESTABLISHED: after the server completes a handshake with * an incoming client * * LWS_CALLBACK_CLIENT_CONNECTION_ERROR: the request client connection has * been unable to complete a handshake with the remote server * * LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed * a handshake with the remote server * * LWS_CALLBACK_CLOSED: when the websocket session ends * * LWS_CALLBACK_BROADCAST: signal to send to client (you would use * libwebsocket_write() taking care about the * special buffer requirements * * LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a * remote client, it can be found at *in and is * len bytes long * * LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets, * they appear with this callback reason. PONG * packets only exist in 04+ protocol * * LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the * client connection, it can be found at *in and * is len bytes long * * LWS_CALLBACK_HTTP: an http request has come from a client that is not * asking to upgrade the connection to a websocket * one. This is a chance to serve http content, * for example, to send a script to the client * which will then open the websockets connection. * @in points to the URI path requested and * libwebsockets_serve_http_file() makes it very * simple to send back a file to the client. * * LWS_CALLBACK_CLIENT_WRITEABLE: * LWS_CALLBACK_SERVER_WRITEABLE: If you call * libwebsocket_callback_on_writable() on a connection, you will * get one of these callbacks coming when the connection socket * is able to accept another write packet without blocking. * If it already was able to take another packet without blocking, * you'll get this callback at the next call to the service loop * function. Notice that CLIENTs get LWS_CALLBACK_CLIENT_WRITEABLE * and servers get LWS_CALLBACK_SERVER_WRITEABLE. * * LWS_CALLBACK_FILTER_NETWORK_CONNECTION: called when a client connects to * the server at network level; the connection is accepted but then * passed to this callback to decide whether to hang up immediately * or not, based on the client IP. @user contains the connection * socket's descriptor. Return non-zero to terminate * the connection before sending or receiving anything. * Because this happens immediately after the network connection * from the client, there's no websocket protocol selected yet so * this callback is issued only to protocol 0. * * LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: called when the handshake has * been received and parsed from the client, but the response is * not sent yet. Return non-zero to disallow the connection. * @user is a pointer to an array of struct lws_tokens, you can * use the header enums lws_token_indexes from libwebsockets.h * to check for and read the supported header presence and * content before deciding to allow the handshake to proceed or * to kill the connection. * * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: if configured for * including OpenSSL support, this callback allows your user code * to perform extra SSL_CTX_load_verify_locations() or similar * calls to direct OpenSSL where to find certificates the client * can use to confirm the remote server identity. @user is the * OpenSSL SSL_CTX* * * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: if configured for * including OpenSSL support, this callback allows your user code * to load extra certifcates into the server which allow it to * verify the validity of certificates returned by clients. @user * is the server's OpenSSL SSL_CTX* * * LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the * libwebsockets context was created with the option * LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this * callback is generated during OpenSSL verification of the cert * sent from the client. It is sent to protocol[0] callback as * no protocol has been negotiated on the connection yet. * Notice that the libwebsockets context and wsi are both NULL * during this callback. See * http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html * to understand more detail about the OpenSSL callback that * generates this libwebsockets callback and the meanings of the * arguments passed. In this callback, @user is the x509_ctx, * @in is the ssl pointer and @len is preverify_ok * Notice that this callback maintains libwebsocket return * conventions, return 0 to mean the cert is OK or 1 to fail it. * This also means that if you don't handle this callback then * the default callback action of returning 0 allows the client * certificates. * * LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: this callback happens * when a client handshake is being compiled. @user is NULL, * @in is a char **, it's pointing to a char * which holds the * next location in the header buffer where you can add * headers, and @len is the remaining space in the header buffer, * which is typically some hundreds of bytes. So, to add a canned * cookie, your handler code might look similar to: * * char **p = (char **)in; * * if (len < 100) * return 1; * * *p += sprintf(*p, "Cookie: a=b\x0d\x0a"); * * return 0; * * Notice if you add anything, you just have to take care about * the CRLF on the line you added. Obviously this callback is * optional, if you don't handle it everything is fine. * * Notice the callback is coming to protocols[0] all the time, * because there is no specific protocol handshook yet. * * LWS_CALLBACK_CONFIRM_EXTENSION_OKAY: When the server handshake code * sees that it does support a requested extension, before * accepting the extension by additing to the list sent back to * the client it gives this callback just to check that it's okay * to use that extension. It calls back to the requested protocol * and with @in being the extension name, @len is 0 and @user is * valid. Note though at this time the ESTABLISHED callback hasn't * happened yet so if you initialize @user content there, @user * content during this callback might not be useful for anything. * Notice this callback comes to protocols[0]. * * LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED: When a client * connection is being prepared to start a handshake to a server, * each supported extension is checked with protocols[0] callback * with this reason, giving the user code a chance to suppress the * claim to support that extension by returning non-zero. If * unhandled, by default 0 will be returned and the extension * support included in the header to the server. Notice this * callback comes to protocols[0]. * * The next four reasons are optional and only need taking care of if you * will be integrating libwebsockets sockets into an external polling * array. * * LWS_CALLBACK_ADD_POLL_FD: libwebsocket deals with its poll() loop * internally, but in the case you are integrating with another * server you will need to have libwebsocket sockets share a * polling array with the other server. This and the other * POLL_FD related callbacks let you put your specialized * poll array interface code in the callback for protocol 0, the * first protocol you support, usually the HTTP protocol in the * serving case. This callback happens when a socket needs to be * added to the polling loop: @user contains the fd, and * @len is the events bitmap (like, POLLIN). If you are using the * internal polling loop (the "service" callback), you can just * ignore these callbacks. * * LWS_CALLBACK_DEL_POLL_FD: This callback happens when a socket descriptor * needs to be removed from an external polling array. @user is * the socket desricptor. If you are using the internal polling * loop, you can just ignore it. * * LWS_CALLBACK_SET_MODE_POLL_FD: This callback happens when libwebsockets * wants to modify the events for the socket descriptor in @user. * The handler should OR @len on to the events member of the pollfd * struct for this socket descriptor. If you are using the * internal polling loop, you can just ignore it. * * LWS_CALLBACK_CLEAR_MODE_POLL_FD: This callback occurs when libwebsockets * wants to modify the events for the socket descriptor in @user. * The handler should AND ~@len on to the events member of the * pollfd struct for this socket descriptor. If you are using the * internal polling loop, you can just ignore it. */ LWS_EXTERN int callback(struct libwebsocket_context * context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len); typedef int (callback_function)(struct libwebsocket_context * context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len); /** * extension_callback_function() - Hooks to allow extensions to operate * @context: Websockets context * @ext: This extension * @wsi: Opaque websocket instance pointer * @reason: The reason for the call * @user: Pointer to per-session user data allocated by library * @in: Pointer used for some callback reasons * @len: Length set for some callback reasons * * Each extension that is active on a particular connection receives * callbacks during the connection lifetime to allow the extension to * operate on websocket data and manage itself. * * Libwebsockets takes care of allocating and freeing "user" memory for * each active extension on each connection. That is what is pointed to * by the @user parameter. * * LWS_EXT_CALLBACK_CONSTRUCT: called when the server has decided to * select this extension from the list provided by the client, * just before the server will send back the handshake accepting * the connection with this extension active. This gives the * extension a chance to initialize its connection context found * in @user. * * LWS_EXT_CALLBACK_CLIENT_CONSTRUCT: same as LWS_EXT_CALLBACK_CONSTRUCT * but called when client is instantiating this extension. Some * extensions will work the same on client and server side and then * you can just merge handlers for both CONSTRUCTS. * * LWS_EXT_CALLBACK_DESTROY: called when the connection the extension was * being used on is about to be closed and deallocated. It's the * last chance for the extension to deallocate anything it has * allocated in the user data (pointed to by @user) before the * user data is deleted. This same callback is used whether you * are in client or server instantiation context. * * LWS_EXT_CALLBACK_PACKET_RX_PREPARSE: when this extension was active on * a connection, and a packet of data arrived at the connection, * it is passed to this callback to give the extension a chance to * change the data, eg, decompress it. @user is pointing to the * extension's private connection context data, @in is pointing * to an lws_tokens struct, it consists of a char * pointer called * token, and an int called token_len. At entry, these are * set to point to the received buffer and set to the content * length. If the extension will grow the content, it should use * a new buffer allocated in its private user context data and * set the pointed-to lws_tokens members to point to its buffer. * * LWS_EXT_CALLBACK_PACKET_TX_PRESEND: this works the same way as * LWS_EXT_CALLBACK_PACKET_RX_PREPARSE above, except it gives the * extension a chance to change websocket data just before it will * be sent out. Using the same lws_token pointer scheme in @in, * the extension can change the buffer and the length to be * transmitted how it likes. Again if it wants to grow the * buffer safely, it should copy the data into its own buffer and * set the lws_tokens token pointer to it. */ LWS_EXTERN int extension_callback(struct libwebsocket_context * context, struct libwebsocket_extension *ext, struct libwebsocket *wsi, enum libwebsocket_extension_callback_reasons reason, void *user, void *in, size_t len); typedef int (extension_callback_function)(struct libwebsocket_context * context, struct libwebsocket_extension *ext, struct libwebsocket *wsi, enum libwebsocket_extension_callback_reasons reason, void *user, void *in, size_t len); /** * struct libwebsocket_protocols - List of protocols and handlers server * supports. * @name: Protocol name that must match the one given in the client * Javascript new WebSocket(url, 'protocol') name * @callback: The service callback used for this protocol. It allows the * service action for an entire protocol to be encapsulated in * the protocol-specific callback * @per_session_data_size: Each new connection using this protocol gets * this much memory allocated on connection establishment and * freed on connection takedown. A pointer to this per-connection * allocation is passed into the callback in the 'user' parameter * @owning_server: the server init call fills in this opaque pointer when * registering this protocol with the server. * @broadcast_socket_port: the server init call fills this in with the * localhost port number used to forward broadcasts for this * protocol * @broadcast_socket_user_fd: the server init call fills this in ... the main() * process context can write to this socket to perform broadcasts * (use the libwebsockets_broadcast() api to do this instead, * it works from any process context) * @protocol_index: which protocol we are starting from zero * * This structure represents one protocol supported by the server. An * array of these structures is passed to libwebsocket_create_server() * allows as many protocols as you like to be handled by one server. */ struct libwebsocket_protocols { const char *name; callback_function *callback; size_t per_session_data_size; /* * below are filled in on server init and can be left uninitialized, * no need for user to use them directly either */ struct libwebsocket_context *owning_server; int broadcast_socket_port; int broadcast_socket_user_fd; int protocol_index; }; /** * struct libwebsocket_extension - An extension we know how to cope with * * @name: Formal extension name, eg, "deflate-stream" * @callback: Service callback * @per_session_data_size: Libwebsockets will auto-malloc this much * memory for the use of the extension, a pointer * to it comes in the @user callback parameter * @per_context_private_data: Optional storage for this externsion that * is per-context, so it can track stuff across * all sessions, etc, if it wants */ struct libwebsocket_extension { const char *name; extension_callback_function *callback; size_t per_session_data_size; void * per_context_private_data; }; LWS_EXTERN struct libwebsocket_context * libwebsocket_create_context(int port, const char * interf, struct libwebsocket_protocols *protocols, struct libwebsocket_extension *extensions, const char *ssl_cert_filepath, const char *ssl_private_key_filepath, int gid, int uid, unsigned int options); LWS_EXTERN void libwebsocket_context_destroy(struct libwebsocket_context *context); LWS_EXTERN int libwebsockets_fork_service_loop(struct libwebsocket_context *context); LWS_EXTERN int libwebsocket_service(struct libwebsocket_context *context, int timeout_ms); LWS_EXTERN int libwebsocket_service_fd(struct libwebsocket_context *context, struct pollfd *pollfd); /* * IMPORTANT NOTICE! * * When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY) * the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE * buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len). * * This allows us to add protocol info before and after the data, and send as * one packet on the network without payload copying, for maximum efficiency. * * So for example you need this kind of code to use libwebsocket_write with a * 128-byte payload * * char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING]; * * // fill your part of the buffer... for example here it's all zeros * memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128); * * libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128); * * When sending LWS_WRITE_HTTP, there is no protocol addition and you can just * use the whole buffer without taking care of the above. */ /* * this is the frame nonce plus two header plus 8 length * there's an additional two for mux extension per mux nesting level * 2 byte prepend on close will already fit because control frames cannot use * the big length style */ #define LWS_SEND_BUFFER_PRE_PADDING (4 + 10 + (2 * MAX_MUX_RECURSION)) #define LWS_SEND_BUFFER_POST_PADDING 1 LWS_EXTERN int libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len, enum libwebsocket_write_protocol protocol); LWS_EXTERN int libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file, const char *content_type); /* notice - you need the pre- and post- padding allocation for buf below */ LWS_EXTERN int libwebsockets_broadcast(const struct libwebsocket_protocols *protocol, unsigned char *buf, size_t len); LWS_EXTERN const struct libwebsocket_protocols * libwebsockets_get_protocol(struct libwebsocket *wsi); LWS_EXTERN int libwebsocket_callback_on_writable(struct libwebsocket_context *context, struct libwebsocket *wsi); LWS_EXTERN int libwebsocket_callback_on_writable_all_protocol( const struct libwebsocket_protocols *protocol); LWS_EXTERN int libwebsocket_get_socket_fd(struct libwebsocket *wsi); LWS_EXTERN int libwebsocket_is_final_fragment(struct libwebsocket *wsi); LWS_EXTERN void * libwebsocket_ensure_user_space(struct libwebsocket *wsi); LWS_EXTERN int libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable); LWS_EXTERN size_t libwebsockets_remaining_packet_payload(struct libwebsocket *wsi); LWS_EXTERN struct libwebsocket * libwebsocket_client_connect(struct libwebsocket_context *clients, const char *address, int port, int ssl_connection, const char *path, const char *host, const char *origin, const char *protocol, int ietf_version_or_minus_one); LWS_EXTERN struct libwebsocket * libwebsocket_client_connect_extended(struct libwebsocket_context *clients, const char *address, int port, int ssl_connection, const char *path, const char *host, const char *origin, const char *protocol, int ietf_version_or_minus_one, void *userdata); LWS_EXTERN const char * libwebsocket_canonical_hostname(struct libwebsocket_context *context); LWS_EXTERN void libwebsockets_get_peer_addresses(int fd, char *name, int name_len, char *rip, int rip_len); LWS_EXTERN void libwebsockets_hangup_on_client(struct libwebsocket_context *context, int fd); LWS_EXTERN void libwebsocket_close_and_free_session(struct libwebsocket_context *context, struct libwebsocket *wsi, enum lws_close_status); LWS_EXTERN int libwebsockets_get_random(struct libwebsocket_context *context, void *buf, int len); LWS_EXTERN int lws_send_pipe_choked(struct libwebsocket *wsi); LWS_EXTERN unsigned char * libwebsockets_SHA1(const unsigned char *d, size_t n, unsigned char *md); LWS_EXTERN int lws_b64_encode_string(const char *in, int in_len, char *out, int out_size); LWS_EXTERN int lws_b64_decode_string(const char *in, char *out, int out_size); LWS_EXTERN struct libwebsocket_extension libwebsocket_internal_extensions[]; #ifdef __cplusplus } #endif #endif