Andy Green | a0da8a8 | 2010-11-08 17:12:19 +0000 | [diff] [blame] | 1 | /* |
| 2 | * libwebsockets - small server side websockets and web server implementation |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 3 | * |
Andy Green | a0da8a8 | 2010-11-08 17:12:19 +0000 | [diff] [blame] | 4 | * Copyright (C) 2010 Andy Green <andy@warmcat.com> |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation: |
| 9 | * version 2.1 of the License. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
| 19 | * MA 02110-1301 USA |
| 20 | */ |
| 21 | |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 22 | #ifndef __LIBWEBSOCKET_H__ |
| 23 | #define __LIBWEBSOCKET_H__ |
| 24 | |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 25 | #define CONTEXT_PORT_NO_LISTEN 0 |
Andy Green | ff95d7a | 2010-10-28 22:36:01 +0100 | [diff] [blame] | 26 | |
Andy Green | 775c0dd | 2010-10-29 14:15:22 +0100 | [diff] [blame] | 27 | enum libwebsocket_callback_reasons { |
| 28 | LWS_CALLBACK_ESTABLISHED, |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 29 | LWS_CALLBACK_CLIENT_ESTABLISHED, |
Andy Green | 775c0dd | 2010-10-29 14:15:22 +0100 | [diff] [blame] | 30 | LWS_CALLBACK_CLOSED, |
Andy Green | 775c0dd | 2010-10-29 14:15:22 +0100 | [diff] [blame] | 31 | LWS_CALLBACK_RECEIVE, |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 32 | LWS_CALLBACK_CLIENT_RECEIVE, |
Andy Green | a6cbece | 2011-01-27 20:06:03 +0000 | [diff] [blame] | 33 | LWS_CALLBACK_CLIENT_RECEIVE_PONG, |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 34 | LWS_CALLBACK_CLIENT_WRITEABLE, |
Andy Green | a2b0ab0 | 2010-11-11 12:28:29 +0000 | [diff] [blame] | 35 | LWS_CALLBACK_HTTP, |
Andy Green | 0ca6a17 | 2010-12-19 20:50:01 +0000 | [diff] [blame] | 36 | LWS_CALLBACK_BROADCAST |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 37 | }; |
| 38 | |
| 39 | enum libwebsocket_write_protocol { |
| 40 | LWS_WRITE_TEXT, |
| 41 | LWS_WRITE_BINARY, |
Andy Green | 38e57bb | 2011-01-19 12:20:27 +0000 | [diff] [blame] | 42 | LWS_WRITE_HTTP, |
| 43 | |
| 44 | /* special 04 opcodes */ |
| 45 | |
| 46 | LWS_WRITE_CLOSE, |
| 47 | LWS_WRITE_PING, |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 48 | LWS_WRITE_PONG, |
| 49 | |
Andy Green | bd96d80 | 2011-01-30 08:24:31 +0000 | [diff] [blame] | 50 | /* flags */ |
| 51 | |
| 52 | LWS_WRITE_NO_FIN = 0x40, |
| 53 | /* |
| 54 | * client packet payload goes out on wire unmunged |
| 55 | * only useful for security tests since normal servers cannot |
| 56 | * decode the content if used |
| 57 | */ |
| 58 | LWS_WRITE_CLIENT_IGNORE_XOR_MASK = 0x80 |
Andy Green | ff95d7a | 2010-10-28 22:36:01 +0100 | [diff] [blame] | 59 | }; |
| 60 | |
Andy Green | 775c0dd | 2010-10-29 14:15:22 +0100 | [diff] [blame] | 61 | struct libwebsocket; |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 62 | struct libwebsocket_context; |
Andy Green | ff95d7a | 2010-10-28 22:36:01 +0100 | [diff] [blame] | 63 | |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 64 | /* document the generic callback (it's a fake prototype under this) */ |
| 65 | /** |
| 66 | * callback() - User server actions |
| 67 | * @wsi: Opaque websocket instance pointer |
| 68 | * @reason: The reason for the call |
| 69 | * @user: Pointer to per-session user data allocated by library |
| 70 | * @in: Pointer used for some callback reasons |
| 71 | * @len: Length set for some callback reasons |
| 72 | * |
| 73 | * This callback is the way the user controls what is served. All the |
| 74 | * protocol detail is hidden and handled by the library. |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 75 | * |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 76 | * For each connection / session there is user data allocated that is |
| 77 | * pointed to by "user". You set the size of this user data area when |
| 78 | * the library is initialized with libwebsocket_create_server. |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 79 | * |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 80 | * You get an opportunity to initialize user data when called back with |
| 81 | * LWS_CALLBACK_ESTABLISHED reason. |
| 82 | * |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 83 | * LWS_CALLBACK_ESTABLISHED: after the server completes a handshake with |
| 84 | * an incoming client |
| 85 | * |
| 86 | * LWS_CALLBACK_CLIENT_ESTABLISHED: after your client connection completed |
| 87 | * a handshake with the remote server |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 88 | * |
| 89 | * LWS_CALLBACK_CLOSED: when the websocket session ends |
| 90 | * |
| 91 | * LWS_CALLBACK_BROADCAST: signal to send to client (you would use |
| 92 | * libwebsocket_write() taking care about the |
| 93 | * special buffer requirements |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 94 | * |
| 95 | * LWS_CALLBACK_RECEIVE: data has appeared for this server endpoint from a |
| 96 | * remote client, it can be found at *in and is |
| 97 | * len bytes long |
| 98 | * |
Andy Green | a6cbece | 2011-01-27 20:06:03 +0000 | [diff] [blame] | 99 | * LWS_CALLBACK_CLIENT_RECEIVE_PONG: if you elected to see PONG packets, |
| 100 | * they appear with this callback reason. PONG |
| 101 | * packets only exist in 04+ protocol |
| 102 | * |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 103 | * LWS_CALLBACK_CLIENT_RECEIVE: data has appeared from the server for the |
| 104 | * client connection, it can be found at *in and |
| 105 | * is len bytes long |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 106 | * |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 107 | * LWS_CALLBACK_HTTP: an http request has come from a client that is not |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 108 | * asking to upgrade the connection to a websocket |
| 109 | * one. This is a chance to serve http content, |
| 110 | * for example, to send a script to the client |
| 111 | * which will then open the websockets connection. |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 112 | * @in points to the URI path requested and |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 113 | * libwebsockets_serve_http_file() makes it very |
| 114 | * simple to send back a file to the client. |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 115 | * |
| 116 | * LWS_CALLBACK_CLIENT_WRITEABLE: if you call |
| 117 | * libwebsocket_callback_on_writable() on a connection, you will |
| 118 | * get this callback coming when the connection socket is able to |
| 119 | * accept another write packet without blocking. If it already |
| 120 | * was able to take another packet without blocking, you'll get |
| 121 | * this callback at the next call to the service loop function. |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 122 | */ |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 123 | extern int callback(struct libwebsocket *wsi, |
| 124 | enum libwebsocket_callback_reasons reason, void *user, |
Andy Green | 8f037e4 | 2010-12-19 22:13:26 +0000 | [diff] [blame] | 125 | void *in, size_t len); |
| 126 | |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 127 | /** |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 128 | * struct libwebsocket_protocols - List of protocols and handlers server |
| 129 | * supports. |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 130 | * @name: Protocol name that must match the one given in the client |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 131 | * Javascript new WebSocket(url, 'protocol') name |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 132 | * @callback: The service callback used for this protocol. It allows the |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 133 | * service action for an entire protocol to be encapsulated in |
| 134 | * the protocol-specific callback |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 135 | * @per_session_data_size: Each new connection using this protocol gets |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 136 | * this much memory allocated on connection establishment and |
| 137 | * freed on connection takedown. A pointer to this per-connection |
| 138 | * allocation is passed into the callback in the 'user' parameter |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 139 | * @owning_server: the server init call fills in this opaque pointer when |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 140 | * registering this protocol with the server. |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 141 | * @broadcast_socket_port: the server init call fills this in with the |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 142 | * localhost port number used to forward broadcasts for this |
| 143 | * protocol |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 144 | * @broadcast_socket_user_fd: the server init call fills this in ... the main() |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 145 | * process context can write to this socket to perform broadcasts |
| 146 | * (use the libwebsockets_broadcast() api to do this instead, |
| 147 | * it works from any process context) |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 148 | * @protocol_index: which protocol we are starting from zero |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 149 | * |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 150 | * This structure represents one protocol supported by the server. An |
| 151 | * array of these structures is passed to libwebsocket_create_server() |
| 152 | * allows as many protocols as you like to be handled by one server. |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 153 | */ |
| 154 | |
| 155 | struct libwebsocket_protocols { |
| 156 | const char *name; |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 157 | int (*callback)(struct libwebsocket *wsi, |
| 158 | enum libwebsocket_callback_reasons reason, void *user, |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 159 | void *in, size_t len); |
| 160 | size_t per_session_data_size; |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 161 | |
| 162 | /* |
| 163 | * below are filled in on server init and can be left uninitialized, |
| 164 | * no need for user to use them directly either |
| 165 | */ |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 166 | |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 167 | struct libwebsocket_context *owning_server; |
| 168 | int broadcast_socket_port; |
| 169 | int broadcast_socket_user_fd; |
| 170 | int protocol_index; |
Andy Green | 4f3943a | 2010-11-12 10:44:16 +0000 | [diff] [blame] | 171 | }; |
| 172 | |
Andy Green | e92cd17 | 2011-01-19 13:11:55 +0000 | [diff] [blame] | 173 | extern struct libwebsocket_context * |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 174 | libwebsocket_create_context(int port, |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 175 | struct libwebsocket_protocols *protocols, |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 176 | const char *ssl_cert_filepath, |
| 177 | const char *ssl_private_key_filepath, int gid, int uid); |
Andy Green | ff95d7a | 2010-10-28 22:36:01 +0100 | [diff] [blame] | 178 | |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 179 | extern void |
| 180 | libwebsocket_context_destroy(struct libwebsocket_context *this); |
| 181 | |
Andy Green | e92cd17 | 2011-01-19 13:11:55 +0000 | [diff] [blame] | 182 | extern int |
| 183 | libwebsockets_fork_service_loop(struct libwebsocket_context *this); |
| 184 | |
| 185 | extern int |
| 186 | libwebsocket_service(struct libwebsocket_context *this, int timeout_ms); |
| 187 | |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 188 | /* |
| 189 | * IMPORTANT NOTICE! |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 190 | * |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 191 | * When sending with websocket protocol (LWS_WRITE_TEXT or LWS_WRITE_BINARY) |
| 192 | * the send buffer has to have LWS_SEND_BUFFER_PRE_PADDING bytes valid BEFORE |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 193 | * buf, and LWS_SEND_BUFFER_POST_PADDING bytes valid AFTER (buf + len). |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 194 | * |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 195 | * This allows us to add protocol info before and after the data, and send as |
| 196 | * one packet on the network without payload copying, for maximum efficiency. |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 197 | * |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 198 | * So for example you need this kind of code to use libwebsocket_write with a |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 199 | * 128-byte payload |
| 200 | * |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 201 | * char buf[LWS_SEND_BUFFER_PRE_PADDING + 128 + LWS_SEND_BUFFER_POST_PADDING]; |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 202 | * |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 203 | * // fill your part of the buffer... for example here it's all zeros |
| 204 | * memset(&buf[LWS_SEND_BUFFER_PRE_PADDING], 0, 128); |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 205 | * |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 206 | * libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], 128); |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 207 | * |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 208 | * When sending LWS_WRITE_HTTP, there is no protocol addition and you can just |
| 209 | * use the whole buffer without taking care of the above. |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 210 | */ |
| 211 | |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 212 | /* this is the frame nonce plus two header plus 8 length */ |
| 213 | |
| 214 | #define LWS_SEND_BUFFER_PRE_PADDING (4 + 10) |
Andy Green | 4ea6006 | 2010-10-30 12:15:07 +0100 | [diff] [blame] | 215 | #define LWS_SEND_BUFFER_POST_PADDING 1 |
| 216 | |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 217 | extern int |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 218 | libwebsocket_write(struct libwebsocket *wsi, unsigned char *buf, size_t len, |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 219 | enum libwebsocket_write_protocol protocol); |
Andy Green | a2b0ab0 | 2010-11-11 12:28:29 +0000 | [diff] [blame] | 220 | |
Andy Green | 5fd8a5e | 2010-10-31 11:57:17 +0000 | [diff] [blame] | 221 | extern int |
Andy Green | e77ddd8 | 2010-11-13 10:03:47 +0000 | [diff] [blame] | 222 | libwebsockets_serve_http_file(struct libwebsocket *wsi, const char *file, |
| 223 | const char *content_type); |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 224 | |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 225 | /* notice - you need the pre- and post- padding allocation for buf below */ |
| 226 | |
| 227 | extern int |
Andy Green | 6964bb5 | 2011-01-23 16:50:33 +0000 | [diff] [blame] | 228 | libwebsockets_broadcast(const struct libwebsocket_protocols *protocol, |
Andy Green | b45993c | 2010-12-18 15:13:50 +0000 | [diff] [blame] | 229 | unsigned char *buf, size_t len); |
| 230 | |
| 231 | extern const struct libwebsocket_protocols * |
| 232 | libwebsockets_get_protocol(struct libwebsocket *wsi); |
| 233 | |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 234 | extern int |
| 235 | libwebsocket_callback_on_writable(struct libwebsocket *wsi); |
| 236 | |
| 237 | extern int |
| 238 | libwebsocket_callback_on_writable_all_protocol( |
| 239 | const struct libwebsocket_protocols *protocol); |
| 240 | |
Andy Green | a6cbece | 2011-01-27 20:06:03 +0000 | [diff] [blame] | 241 | extern int |
| 242 | libwebsocket_get_socket_fd(struct libwebsocket *wsi); |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 243 | |
| 244 | extern int |
| 245 | libwebsocket_rx_flow_control(struct libwebsocket *wsi, int enable); |
| 246 | |
Andy Green | 38e57bb | 2011-01-19 12:20:27 +0000 | [diff] [blame] | 247 | extern size_t |
| 248 | libwebsockets_remaining_packet_payload(struct libwebsocket *wsi); |
| 249 | |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 250 | extern struct libwebsocket * |
| 251 | libwebsocket_client_connect(struct libwebsocket_context *clients, |
| 252 | const char *address, |
| 253 | int port, |
Andy Green | 90c7cbc | 2011-01-27 06:26:52 +0000 | [diff] [blame] | 254 | int ssl_connection, |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 255 | const char *path, |
| 256 | const char *host, |
| 257 | const char *origin, |
| 258 | const char *protocol); |
| 259 | |
Andy Green | 2ac5a6f | 2011-01-28 10:00:18 +0000 | [diff] [blame] | 260 | extern const char * |
| 261 | libwebsocket_canonical_hostname(struct libwebsocket_context *this); |
| 262 | |
| 263 | extern void |
Andy Green | 4739e5c | 2011-01-22 12:51:57 +0000 | [diff] [blame] | 264 | libwebsocket_client_close(struct libwebsocket *wsi); |
| 265 | |
Andy Green | ab990e4 | 2010-10-31 12:42:52 +0000 | [diff] [blame] | 266 | #endif |