2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010 - 2018 Andy Green <andy@warmcat.com>
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.
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.
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,
21 * This is included from core/private.h
24 typedef uint32_t lws_wsi_state_t;
27 * The wsi->role_ops pointer decides almost everything about what role the wsi
28 * will play, h2, raw, ws, etc.
30 * However there are a few additional flags needed that vary, such as if the
31 * role is a client or server side, if it has that concept. And the connection
32 * fulfilling the role, has a separate dynamic state.
35 * [ role flags ] [ state ]
37 * The role flags part is generally invariant for the lifetime of the wsi,
38 * although it can change if the connection role itself does, eg, if the
39 * connection upgrades from H1 -> WS1 the role flags may be changed at that
42 * The state part reflects the dynamic connection state, and the states are
43 * reused between roles.
45 * None of the internal role or state representations are made available outside
46 * of lws internals. Even for lws internals, if you add stuff here, please keep
47 * the constants inside this header only by adding necessary helpers here and
48 * use the helpers in the actual code. This is to ease any future refactors.
50 * Notice LWSIFR_ENCAP means we have a parent wsi that actually carries our
51 * data as a stream inside a different protocol.
56 #define LWSIFR_CLIENT (0x1000 << _RS) /* client side */
57 #define LWSIFR_SERVER (0x2000 << _RS) /* server side */
59 #define LWSIFR_P_ENCAP_H2 (0x0100 << _RS) /* we are encapsulated by h2 */
62 LWSI_ROLE_MASK = (0xffff << _RS),
63 LWSI_ROLE_ENCAP_MASK = (0x0f00 << _RS),
66 #define lwsi_role(wsi) (wsi->wsistate & LWSI_ROLE_MASK)
68 #define lwsi_set_role(wsi, role) wsi->wsistate = \
69 (wsi->wsistate & (~LWSI_ROLE_MASK)) | role
71 void lwsi_set_role(struct lws *wsi, lws_wsi_state_t role);
74 #define lwsi_role_client(wsi) (!!(wsi->wsistate & LWSIFR_CLIENT))
75 #define lwsi_role_server(wsi) (!!(wsi->wsistate & LWSIFR_SERVER))
76 #define lwsi_role_h2_ENCAPSULATION(wsi) \
77 ((wsi->wsistate & LWSI_ROLE_ENCAP_MASK) == LWSIFR_P_ENCAP_H2)
79 /* Pollout wants a callback in this state */
80 #define LWSIFS_POCB (0x100)
81 /* Before any protocol connection was established */
82 #define LWSIFS_NOT_EST (0x200)
86 /* Phase 1: pre-transport */
88 LRS_UNCONNECTED = LWSIFS_NOT_EST | 0,
89 LRS_WAITING_CONNECT = LWSIFS_NOT_EST | 1,
91 /* Phase 2: establishing intermediaries on top of transport */
93 LRS_WAITING_PROXY_REPLY = LWSIFS_NOT_EST | 2,
94 LRS_WAITING_SSL = LWSIFS_NOT_EST | 3,
95 LRS_WAITING_SOCKS_GREETING_REPLY = LWSIFS_NOT_EST | 4,
96 LRS_WAITING_SOCKS_CONNECT_REPLY = LWSIFS_NOT_EST | 5,
97 LRS_WAITING_SOCKS_AUTH_REPLY = LWSIFS_NOT_EST | 6,
99 /* Phase 3: establishing tls tunnel */
101 LRS_SSL_INIT = LWSIFS_NOT_EST | 7,
102 LRS_SSL_ACK_PENDING = LWSIFS_NOT_EST | 8,
103 LRS_PRE_WS_SERVING_ACCEPT = LWSIFS_NOT_EST | 9,
105 /* Phase 4: connected */
107 LRS_WAITING_SERVER_REPLY = LWSIFS_NOT_EST | 10,
108 LRS_H2_AWAIT_PREFACE = LWSIFS_NOT_EST | 11,
109 LRS_H2_AWAIT_SETTINGS = LWSIFS_NOT_EST |
112 /* Phase 5: protocol logically established */
114 LRS_H2_CLIENT_SEND_SETTINGS = LWSIFS_POCB | 13,
115 LRS_H2_WAITING_TO_SEND_HEADERS = LWSIFS_POCB | 14,
116 LRS_DEFERRING_ACTION = LWSIFS_POCB | 15,
118 LRS_H1C_ISSUE_HANDSHAKE = 17,
119 LRS_H1C_ISSUE_HANDSHAKE2 = 18,
120 LRS_ISSUE_HTTP_BODY = 19,
121 LRS_ISSUING_FILE = 20,
124 LRS_DISCARD_BODY = 31,
125 LRS_ESTABLISHED = LWSIFS_POCB | 23,
126 /* we are established, but we have embarked on serving a single
127 * transaction. Other transaction input may be pending, but we will
128 * not service it while we are busy dealing with the current
131 * When we complete the current transaction, we would reset our state
132 * back to ESTABLISHED and start to process the next transaction.
134 LRS_DOING_TRANSACTION = LWSIFS_POCB | 24,
136 /* Phase 6: finishing */
138 LRS_WAITING_TO_SEND_CLOSE = LWSIFS_POCB | 25,
139 LRS_RETURNED_CLOSE = LWSIFS_POCB | 26,
140 LRS_AWAITING_CLOSE_ACK = LWSIFS_POCB | 27,
141 LRS_FLUSHING_BEFORE_CLOSE = LWSIFS_POCB | 28,
146 LRS_DEAD_SOCKET = 30,
151 #define lwsi_state(wsi) ((enum lwsi_state)(wsi->wsistate & LRS_MASK))
152 #define lwsi_state_PRE_CLOSE(wsi) \
153 ((enum lwsi_state)(wsi->wsistate_pre_close & LRS_MASK))
154 #define lwsi_state_est(wsi) (!(wsi->wsistate & LWSIFS_NOT_EST))
155 #define lwsi_state_est_PRE_CLOSE(wsi) \
156 (!(wsi->wsistate_pre_close & LWSIFS_NOT_EST))
157 #define lwsi_state_can_handle_POLLOUT(wsi) (wsi->wsistate & LWSIFS_POCB)
158 #if !defined (_DEBUG)
159 #define lwsi_set_state(wsi, lrs) wsi->wsistate = \
160 (wsi->wsistate & (~LRS_MASK)) | lrs
162 void lwsi_set_state(struct lws *wsi, lws_wsi_state_t lrs);
165 #define _LWS_ADOPT_FINISH (1 << 24)
168 * internal role-specific ops
170 struct lws_context_per_thread;
171 struct lws_role_ops {
175 * After http headers have parsed, this is the last chance for a role
176 * to upgrade the connection to something else using the headers.
177 * ws-over-h2 is upgraded from h2 like this.
179 int (*check_upgrades)(struct lws *wsi);
180 /* role-specific context init during context creation */
181 int (*init_context)(struct lws_context *context,
182 const struct lws_context_creation_info *info);
183 /* role-specific per-vhost init during vhost creation */
184 int (*init_vhost)(struct lws_vhost *vh,
185 const struct lws_context_creation_info *info);
186 /* role-specific per-vhost destructor during vhost destroy */
187 int (*destroy_vhost)(struct lws_vhost *vh);
188 /* generic 1Hz callback for the role itself */
189 int (*periodic_checks)(struct lws_context *context, int tsi,
191 /* chance for the role to force POLLIN without network activity */
192 int (*service_flag_pending)(struct lws_context *context, int tsi);
193 /* an fd using this role has POLLIN signalled */
194 int (*handle_POLLIN)(struct lws_context_per_thread *pt, struct lws *wsi,
195 struct lws_pollfd *pollfd);
196 /* an fd using the role wanted a POLLOUT callback and now has it */
197 int (*handle_POLLOUT)(struct lws *wsi);
198 /* perform user pollout */
199 int (*perform_user_POLLOUT)(struct lws *wsi);
200 /* do effective callback on writeable */
201 int (*callback_on_writable)(struct lws *wsi);
202 /* connection-specific tx credit in bytes */
203 lws_fileofs_t (*tx_credit)(struct lws *wsi);
204 /* role-specific write formatting */
205 int (*write_role_protocol)(struct lws *wsi, unsigned char *buf,
206 size_t len, enum lws_write_protocol *wp);
208 /* get encapsulation parent */
209 struct lws * (*encapsulation_parent)(struct lws *wsi);
211 /* role-specific destructor */
212 int (*alpn_negotiated)(struct lws *wsi, const char *alpn);
214 /* chance for the role to handle close in the protocol */
215 int (*close_via_role_protocol)(struct lws *wsi,
216 enum lws_close_status reason);
217 /* role-specific close processing */
218 int (*close_role)(struct lws_context_per_thread *pt, struct lws *wsi);
219 /* role-specific connection close processing */
220 int (*close_kill_connection)(struct lws *wsi,
221 enum lws_close_status reason);
222 /* role-specific destructor */
223 int (*destroy_role)(struct lws *wsi);
225 /* role-specific socket-adopt */
226 int (*adoption_bind)(struct lws *wsi, int type, const char *prot);
227 /* role-specific client-bind:
228 * ret 1 = bound, 0 = not bound, -1 = fail out
229 * i may be NULL, indicating client_bind is being called after
230 * a successful bind earlier, to finalize the binding. In that
231 * case ret 0 = OK, 1 = fail, wsi needs freeing, -1 = fail, wsi freed */
232 int (*client_bind)(struct lws *wsi,
233 const struct lws_client_connect_info *i);
236 * the callback reasons for adoption for client, server
237 * (just client applies if no concept of client or server)
239 uint16_t adoption_cb[2];
241 * the callback reasons for adoption for client, server
242 * (just client applies if no concept of client or server)
246 * the callback reasons for WRITEABLE for client, server
247 * (just client applies if no concept of client or server)
249 uint16_t writeable_cb[2];
251 * the callback reasons for CLOSE for client, server
252 * (just client applies if no concept of client or server)
254 uint16_t close_cb[2];
256 * the callback reasons for protocol bind for client, server
257 * (just client applies if no concept of client or server)
259 uint16_t protocol_bind_cb[2];
261 * the callback reasons for protocol unbind for client, server
262 * (just client applies if no concept of client or server)
264 uint16_t protocol_unbind_cb[2];
266 unsigned int file_handle:1; /* role operates on files not sockets */
270 extern struct lws_role_ops role_ops_raw_skt, role_ops_raw_file, role_ops_listen,
273 /* bring in role private declarations */
275 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
276 #include "private-lib-roles-http.h"
278 #define lwsi_role_http(wsi) (0)
281 #if defined(LWS_ROLE_H1)
282 #include "private-lib-roles-h1.h"
284 #define lwsi_role_h1(wsi) (0)
287 #if defined(LWS_ROLE_H2)
288 #include "private-lib-roles-h2.h"
290 #define lwsi_role_h2(wsi) (0)
293 #if defined(LWS_ROLE_WS)
294 #include "private-lib-roles-ws.h"
296 #define lwsi_role_ws(wsi) (0)
299 #if defined(LWS_ROLE_CGI)
300 #include "private-lib-roles-cgi.h"
302 #define lwsi_role_cgi(wsi) (0)
305 #if defined(LWS_ROLE_DBUS)
306 #include "private-lib-roles-dbus.h"
308 #define lwsi_role_dbus(wsi) (0)
311 #if defined(LWS_ROLE_RAW_PROXY)
312 #include "private-lib-roles-raw-proxy.h"
314 #define lwsi_role_raw_proxy(wsi) (0)
320 LWS_HP_RET_USER_SERVICE,
322 LWS_HPI_RET_WSI_ALREADY_DIED, /* we closed it */
323 LWS_HPI_RET_HANDLED, /* no probs */
324 LWS_HPI_RET_PLEASE_CLOSE_ME, /* close it for us */
327 LWS_UPG_RET_CONTINUE,
332 lws_role_call_adoption_bind(struct lws *wsi, int type, const char *prot);
335 lws_client_connect_3(struct lws *wsi, struct lws *wsi_piggyback, ssize_t plen);