1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker static int
rops_handle_POLLIN_mqtt(struct lws_context_per_thread * pt,struct lws * wsi,struct lws_pollfd * pollfd)28*1c60b9acSAndroid Build Coastguard Worker rops_handle_POLLIN_mqtt(struct lws_context_per_thread *pt, struct lws *wsi,
29*1c60b9acSAndroid Build Coastguard Worker struct lws_pollfd *pollfd)
30*1c60b9acSAndroid Build Coastguard Worker {
31*1c60b9acSAndroid Build Coastguard Worker unsigned int pending = 0;
32*1c60b9acSAndroid Build Coastguard Worker struct lws_tokens ebuf;
33*1c60b9acSAndroid Build Coastguard Worker int n = 0;
34*1c60b9acSAndroid Build Coastguard Worker char buffered = 0;
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: wsistate 0x%x, %s pollout %d\n", __func__,
37*1c60b9acSAndroid Build Coastguard Worker (unsigned int)wsi->wsistate, wsi->a.protocol->name,
38*1c60b9acSAndroid Build Coastguard Worker pollfd->revents);
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker /*
41*1c60b9acSAndroid Build Coastguard Worker * After the CONNACK and nwsi establishment, the first logical
42*1c60b9acSAndroid Build Coastguard Worker * stream is migrated out of the nwsi to be child sid 1, and the
43*1c60b9acSAndroid Build Coastguard Worker * nwsi no longer has a wsi->mqtt of its own.
44*1c60b9acSAndroid Build Coastguard Worker *
45*1c60b9acSAndroid Build Coastguard Worker * RX events on the nwsi must be converted to events seen or not
46*1c60b9acSAndroid Build Coastguard Worker * seen by one or more child streams.
47*1c60b9acSAndroid Build Coastguard Worker *
48*1c60b9acSAndroid Build Coastguard Worker * SUBACK - reflected to child stream that asked for it
49*1c60b9acSAndroid Build Coastguard Worker * PUBACK - routed to child that did the related publish
50*1c60b9acSAndroid Build Coastguard Worker */
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard Worker ebuf.token = NULL;
53*1c60b9acSAndroid Build Coastguard Worker ebuf.len = 0;
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) != LRS_ESTABLISHED) {
56*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
57*1c60b9acSAndroid Build Coastguard Worker
58*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_WAITING_SSL &&
59*1c60b9acSAndroid Build Coastguard Worker ((pollfd->revents & LWS_POLLOUT)) &&
60*1c60b9acSAndroid Build Coastguard Worker lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
61*1c60b9acSAndroid Build Coastguard Worker lwsl_info("failed at set pollfd\n");
62*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
63*1c60b9acSAndroid Build Coastguard Worker }
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker if ((pollfd->revents & LWS_POLLOUT) &&
66*1c60b9acSAndroid Build Coastguard Worker lws_handle_POLLOUT_event(wsi, pollfd)) {
67*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("POLLOUT event closed it\n");
68*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
69*1c60b9acSAndroid Build Coastguard Worker }
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker n = lws_mqtt_client_socket_service(wsi, pollfd, NULL);
72*1c60b9acSAndroid Build Coastguard Worker if (n)
73*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_WSI_ALREADY_DIED;
74*1c60b9acSAndroid Build Coastguard Worker #endif
75*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_HANDLED;
76*1c60b9acSAndroid Build Coastguard Worker }
77*1c60b9acSAndroid Build Coastguard Worker
78*1c60b9acSAndroid Build Coastguard Worker /* 1: something requested a callback when it was OK to write */
79*1c60b9acSAndroid Build Coastguard Worker
80*1c60b9acSAndroid Build Coastguard Worker if ((pollfd->revents & LWS_POLLOUT) &&
81*1c60b9acSAndroid Build Coastguard Worker lwsi_state_can_handle_POLLOUT(wsi) &&
82*1c60b9acSAndroid Build Coastguard Worker lws_handle_POLLOUT_event(wsi, pollfd)) {
83*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_RETURNED_CLOSE)
84*1c60b9acSAndroid Build Coastguard Worker lwsi_set_state(wsi, LRS_FLUSHING_BEFORE_CLOSE);
85*1c60b9acSAndroid Build Coastguard Worker
86*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
87*1c60b9acSAndroid Build Coastguard Worker }
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker /* 3: buflist needs to be drained
90*1c60b9acSAndroid Build Coastguard Worker */
91*1c60b9acSAndroid Build Coastguard Worker read:
92*1c60b9acSAndroid Build Coastguard Worker // lws_buflist_describe(&wsi->buflist, wsi, __func__);
93*1c60b9acSAndroid Build Coastguard Worker ebuf.len = (int)lws_buflist_next_segment_len(&wsi->buflist, &ebuf.token);
94*1c60b9acSAndroid Build Coastguard Worker if (ebuf.len) {
95*1c60b9acSAndroid Build Coastguard Worker lwsl_info("draining buflist (len %d)\n", ebuf.len);
96*1c60b9acSAndroid Build Coastguard Worker buffered = 1;
97*1c60b9acSAndroid Build Coastguard Worker goto drain;
98*1c60b9acSAndroid Build Coastguard Worker }
99*1c60b9acSAndroid Build Coastguard Worker
100*1c60b9acSAndroid Build Coastguard Worker if (!(pollfd->revents & pollfd->events & LWS_POLLIN))
101*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_HANDLED;
102*1c60b9acSAndroid Build Coastguard Worker
103*1c60b9acSAndroid Build Coastguard Worker /* if (lws_is_flowcontrolled(wsi)) { */
104*1c60b9acSAndroid Build Coastguard Worker /* lwsl_info("%s: %p should be rxflow (bm 0x%x)..\n", */
105*1c60b9acSAndroid Build Coastguard Worker /* __func__, wsi, wsi->rxflow_bitmap); */
106*1c60b9acSAndroid Build Coastguard Worker /* return LWS_HPI_RET_HANDLED; */
107*1c60b9acSAndroid Build Coastguard Worker /* } */
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker if (!(lwsi_role_client(wsi) && lwsi_state(wsi) != LRS_ESTABLISHED)) {
110*1c60b9acSAndroid Build Coastguard Worker /*
111*1c60b9acSAndroid Build Coastguard Worker * In case we are going to react to this rx by scheduling
112*1c60b9acSAndroid Build Coastguard Worker * writes, we need to restrict the amount of rx to the size
113*1c60b9acSAndroid Build Coastguard Worker * the protocol reported for rx buffer.
114*1c60b9acSAndroid Build Coastguard Worker *
115*1c60b9acSAndroid Build Coastguard Worker * Otherwise we get a situation we have to absorb possibly a
116*1c60b9acSAndroid Build Coastguard Worker * lot of reads before we get a chance to drain them by writing
117*1c60b9acSAndroid Build Coastguard Worker * them, eg, with echo type tests in autobahn.
118*1c60b9acSAndroid Build Coastguard Worker */
119*1c60b9acSAndroid Build Coastguard Worker
120*1c60b9acSAndroid Build Coastguard Worker buffered = 0;
121*1c60b9acSAndroid Build Coastguard Worker ebuf.token = pt->serv_buf;
122*1c60b9acSAndroid Build Coastguard Worker ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
123*1c60b9acSAndroid Build Coastguard Worker
124*1c60b9acSAndroid Build Coastguard Worker if ((unsigned int)ebuf.len > wsi->a.context->pt_serv_buf_size)
125*1c60b9acSAndroid Build Coastguard Worker ebuf.len = (int)wsi->a.context->pt_serv_buf_size;
126*1c60b9acSAndroid Build Coastguard Worker
127*1c60b9acSAndroid Build Coastguard Worker if ((int)pending > ebuf.len)
128*1c60b9acSAndroid Build Coastguard Worker pending = (unsigned int)ebuf.len;
129*1c60b9acSAndroid Build Coastguard Worker
130*1c60b9acSAndroid Build Coastguard Worker ebuf.len = lws_ssl_capable_read(wsi, ebuf.token,
131*1c60b9acSAndroid Build Coastguard Worker pending ? pending :
132*1c60b9acSAndroid Build Coastguard Worker (unsigned int)ebuf.len);
133*1c60b9acSAndroid Build Coastguard Worker switch (ebuf.len) {
134*1c60b9acSAndroid Build Coastguard Worker case 0:
135*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: zero length read\n",
136*1c60b9acSAndroid Build Coastguard Worker __func__);
137*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
138*1c60b9acSAndroid Build Coastguard Worker case LWS_SSL_CAPABLE_MORE_SERVICE:
139*1c60b9acSAndroid Build Coastguard Worker lwsl_info("SSL Capable more service\n");
140*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_HANDLED;
141*1c60b9acSAndroid Build Coastguard Worker case LWS_SSL_CAPABLE_ERROR:
142*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n",
143*1c60b9acSAndroid Build Coastguard Worker __func__);
144*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
145*1c60b9acSAndroid Build Coastguard Worker }
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker /*
148*1c60b9acSAndroid Build Coastguard Worker * coverity thinks ssl_capable_read() may read over
149*1c60b9acSAndroid Build Coastguard Worker * 2GB. Dissuade it...
150*1c60b9acSAndroid Build Coastguard Worker */
151*1c60b9acSAndroid Build Coastguard Worker ebuf.len &= 0x7fffffff;
152*1c60b9acSAndroid Build Coastguard Worker }
153*1c60b9acSAndroid Build Coastguard Worker
154*1c60b9acSAndroid Build Coastguard Worker drain:
155*1c60b9acSAndroid Build Coastguard Worker /* service incoming data */
156*1c60b9acSAndroid Build Coastguard Worker //lws_buflist_describe(&wsi->buflist, wsi, __func__);
157*1c60b9acSAndroid Build Coastguard Worker if (ebuf.len) {
158*1c60b9acSAndroid Build Coastguard Worker n = lws_read_mqtt(wsi, ebuf.token, (unsigned int)ebuf.len);
159*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
160*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: lws_read_mqtt returned %d\n",
161*1c60b9acSAndroid Build Coastguard Worker __func__, n);
162*1c60b9acSAndroid Build Coastguard Worker /* we closed wsi */
163*1c60b9acSAndroid Build Coastguard Worker goto fail;
164*1c60b9acSAndroid Build Coastguard Worker }
165*1c60b9acSAndroid Build Coastguard Worker // lws_buflist_describe(&wsi->buflist, wsi, __func__);
166*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: consuming %d / %d\n", __func__, n, ebuf.len);
167*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_aware_finished_consuming(wsi, &ebuf, ebuf.len,
168*1c60b9acSAndroid Build Coastguard Worker buffered, __func__))
169*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_PLEASE_CLOSE_ME;
170*1c60b9acSAndroid Build Coastguard Worker }
171*1c60b9acSAndroid Build Coastguard Worker
172*1c60b9acSAndroid Build Coastguard Worker ebuf.token = NULL;
173*1c60b9acSAndroid Build Coastguard Worker ebuf.len = 0;
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker pending = (unsigned int)lws_ssl_pending(wsi);
176*1c60b9acSAndroid Build Coastguard Worker if (pending) {
177*1c60b9acSAndroid Build Coastguard Worker pending = pending > wsi->a.context->pt_serv_buf_size ?
178*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->pt_serv_buf_size : pending;
179*1c60b9acSAndroid Build Coastguard Worker goto read;
180*1c60b9acSAndroid Build Coastguard Worker }
181*1c60b9acSAndroid Build Coastguard Worker
182*1c60b9acSAndroid Build Coastguard Worker if (buffered && /* were draining, now nothing left */
183*1c60b9acSAndroid Build Coastguard Worker !lws_buflist_next_segment_len(&wsi->buflist, NULL)) {
184*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s flow buf: drained\n", __func__, lws_wsi_tag(wsi));
185*1c60b9acSAndroid Build Coastguard Worker /* having drained the rxflow buffer, can rearm POLLIN */
186*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_SERVER)
187*1c60b9acSAndroid Build Coastguard Worker n =
188*1c60b9acSAndroid Build Coastguard Worker #endif
189*1c60b9acSAndroid Build Coastguard Worker __lws_rx_flow_control(wsi);
190*1c60b9acSAndroid Build Coastguard Worker /* n ignored, needed for NO_SERVER case */
191*1c60b9acSAndroid Build Coastguard Worker }
192*1c60b9acSAndroid Build Coastguard Worker
193*1c60b9acSAndroid Build Coastguard Worker /* n = 0 */
194*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_HANDLED;
195*1c60b9acSAndroid Build Coastguard Worker
196*1c60b9acSAndroid Build Coastguard Worker fail:
197*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: Failed, bailing\n", __func__);
198*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "mqtt svc fail");
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker return LWS_HPI_RET_WSI_ALREADY_DIED;
201*1c60b9acSAndroid Build Coastguard Worker }
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker #if 0 /* defined(LWS_WITH_SERVER) */
204*1c60b9acSAndroid Build Coastguard Worker
205*1c60b9acSAndroid Build Coastguard Worker static int
206*1c60b9acSAndroid Build Coastguard Worker rops_adoption_bind_mqtt(struct lws *wsi, int type, const char *vh_prot_name)
207*1c60b9acSAndroid Build Coastguard Worker {
208*1c60b9acSAndroid Build Coastguard Worker /* no http but socket... must be mqtt */
209*1c60b9acSAndroid Build Coastguard Worker if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
210*1c60b9acSAndroid Build Coastguard Worker (type & _LWS_ADOPT_FINISH))
211*1c60b9acSAndroid Build Coastguard Worker return 0; /* no match */
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
214*1c60b9acSAndroid Build Coastguard Worker LRS_ESTABLISHED, &role_ops_mqtt);
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker if (vh_prot_name)
217*1c60b9acSAndroid Build Coastguard Worker lws_bind_protocol(wsi, wsi->a.protocol, __func__);
218*1c60b9acSAndroid Build Coastguard Worker else
219*1c60b9acSAndroid Build Coastguard Worker /* this is the only time he will transition */
220*1c60b9acSAndroid Build Coastguard Worker lws_bind_protocol(wsi,
221*1c60b9acSAndroid Build Coastguard Worker &wsi->a.vhost->protocols[wsi->a.vhost->mqtt_protocol_index],
222*1c60b9acSAndroid Build Coastguard Worker __func__);
223*1c60b9acSAndroid Build Coastguard Worker
224*1c60b9acSAndroid Build Coastguard Worker return 1; /* bound */
225*1c60b9acSAndroid Build Coastguard Worker }
226*1c60b9acSAndroid Build Coastguard Worker #endif
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker static int
rops_client_bind_mqtt(struct lws * wsi,const struct lws_client_connect_info * i)229*1c60b9acSAndroid Build Coastguard Worker rops_client_bind_mqtt(struct lws *wsi, const struct lws_client_connect_info *i)
230*1c60b9acSAndroid Build Coastguard Worker {
231*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: i = %p\n", __func__, i);
232*1c60b9acSAndroid Build Coastguard Worker if (!i) {
233*1c60b9acSAndroid Build Coastguard Worker
234*1c60b9acSAndroid Build Coastguard Worker /* finalize */
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker if (!wsi->user_space && wsi->stash->cis[CIS_METHOD])
237*1c60b9acSAndroid Build Coastguard Worker if (lws_ensure_user_space(wsi))
238*1c60b9acSAndroid Build Coastguard Worker return 1;
239*1c60b9acSAndroid Build Coastguard Worker
240*1c60b9acSAndroid Build Coastguard Worker if (!wsi->stash->cis[CIS_METHOD] && !wsi->stash->cis[CIS_ALPN])
241*1c60b9acSAndroid Build Coastguard Worker wsi->stash->cis[CIS_ALPN] = "x-amzn-mqtt-ca";
242*1c60b9acSAndroid Build Coastguard Worker
243*1c60b9acSAndroid Build Coastguard Worker /* if we went on the ah waiting list, it's ok, we can
244*1c60b9acSAndroid Build Coastguard Worker * wait.
245*1c60b9acSAndroid Build Coastguard Worker *
246*1c60b9acSAndroid Build Coastguard Worker * When we do get the ah, now or later, he will end up
247*1c60b9acSAndroid Build Coastguard Worker * at lws_http_client_connect_via_info2().
248*1c60b9acSAndroid Build Coastguard Worker */
249*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
250*1c60b9acSAndroid Build Coastguard Worker if (lws_header_table_attach(wsi, 0) < 0)
251*1c60b9acSAndroid Build Coastguard Worker /*
252*1c60b9acSAndroid Build Coastguard Worker * if we failed here, the connection is already closed
253*1c60b9acSAndroid Build Coastguard Worker * and freed.
254*1c60b9acSAndroid Build Coastguard Worker */
255*1c60b9acSAndroid Build Coastguard Worker return -1;
256*1c60b9acSAndroid Build Coastguard Worker #else
257*1c60b9acSAndroid Build Coastguard Worker if (lws_header_table_attach(wsi, 0))
258*1c60b9acSAndroid Build Coastguard Worker return 0;
259*1c60b9acSAndroid Build Coastguard Worker #endif
260*1c60b9acSAndroid Build Coastguard Worker return 0;
261*1c60b9acSAndroid Build Coastguard Worker }
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker /* if a recognized mqtt method, bind to it */
264*1c60b9acSAndroid Build Coastguard Worker if (strcmp(i->method, "MQTT"))
265*1c60b9acSAndroid Build Coastguard Worker return 0; /* no match */
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker if (lws_create_client_mqtt_object(i, wsi))
268*1c60b9acSAndroid Build Coastguard Worker return 1;
269*1c60b9acSAndroid Build Coastguard Worker
270*1c60b9acSAndroid Build Coastguard Worker lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
271*1c60b9acSAndroid Build Coastguard Worker &role_ops_mqtt);
272*1c60b9acSAndroid Build Coastguard Worker return 1; /* matched */
273*1c60b9acSAndroid Build Coastguard Worker }
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker static int
rops_handle_POLLOUT_mqtt(struct lws * wsi)276*1c60b9acSAndroid Build Coastguard Worker rops_handle_POLLOUT_mqtt(struct lws *wsi)
277*1c60b9acSAndroid Build Coastguard Worker {
278*1c60b9acSAndroid Build Coastguard Worker struct lws **wsi2;
279*1c60b9acSAndroid Build Coastguard Worker
280*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s\n", __func__);
281*1c60b9acSAndroid Build Coastguard Worker
282*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
283*1c60b9acSAndroid Build Coastguard Worker if (wsi->mqtt && wsi->mqtt->send_pingreq && !wsi->mqtt->inside_payload) {
284*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[LWS_PRE + 2];
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker /*
287*1c60b9acSAndroid Build Coastguard Worker * We are swallowing this POLLOUT in order to send a PINGREQ
288*1c60b9acSAndroid Build Coastguard Worker * autonomously
289*1c60b9acSAndroid Build Coastguard Worker */
290*1c60b9acSAndroid Build Coastguard Worker
291*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_pingreq = 0;
292*1c60b9acSAndroid Build Coastguard Worker
293*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: issuing PINGREQ\n", __func__);
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE] = LMQCP_CTOS_PINGREQ << 4;
296*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE + 1] = 0;
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker if (lws_write(wsi, (uint8_t *)&buf[LWS_PRE], 2,
299*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_BINARY) != 2)
300*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_DIE;
301*1c60b9acSAndroid Build Coastguard Worker
302*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_OK;
303*1c60b9acSAndroid Build Coastguard Worker }
304*1c60b9acSAndroid Build Coastguard Worker #endif
305*1c60b9acSAndroid Build Coastguard Worker if (wsi->mqtt && !wsi->mqtt->inside_payload &&
306*1c60b9acSAndroid Build Coastguard Worker (wsi->mqtt->send_pubrec || wsi->mqtt->send_pubrel ||
307*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_pubcomp)) {
308*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[LWS_PRE + 4];
309*1c60b9acSAndroid Build Coastguard Worker /* Remaining len = 2 */
310*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE + 1] = 2;
311*1c60b9acSAndroid Build Coastguard Worker if (wsi->mqtt->send_pubrec) {
312*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: issuing PUBREC for pkt id: %d\n",
313*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->mqtt->peer_ack_pkt_id);
314*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE] = LMQCP_PUBREC << 4 | 0x2;
315*1c60b9acSAndroid Build Coastguard Worker /* Packet ID */
316*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&buf[LWS_PRE + 2],
317*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->peer_ack_pkt_id);
318*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_pubrec = 0;
319*1c60b9acSAndroid Build Coastguard Worker } else if (wsi->mqtt->send_pubrel) {
320*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: issuing PUBREL for pkt id: %d\n",
321*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->mqtt->ack_pkt_id);
322*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE] = LMQCP_PUBREL << 4 | 0x2;
323*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&buf[LWS_PRE + 2],
324*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->ack_pkt_id);
325*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_pubrel = 0;
326*1c60b9acSAndroid Build Coastguard Worker } else {
327*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: issuing PUBCOMP for pkt id: %d\n",
328*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->mqtt->peer_ack_pkt_id);
329*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE] = LMQCP_PUBCOMP << 4 | 0x2;
330*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&buf[LWS_PRE + 2],
331*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->peer_ack_pkt_id);
332*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_pubcomp = 0;
333*1c60b9acSAndroid Build Coastguard Worker }
334*1c60b9acSAndroid Build Coastguard Worker if (lws_write(wsi, (uint8_t *)&buf[LWS_PRE], 4,
335*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_BINARY) != 4)
336*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_DIE;
337*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_OK;
338*1c60b9acSAndroid Build Coastguard Worker }
339*1c60b9acSAndroid Build Coastguard Worker
340*1c60b9acSAndroid Build Coastguard Worker wsi = lws_get_network_wsi(wsi);
341*1c60b9acSAndroid Build Coastguard Worker
342*1c60b9acSAndroid Build Coastguard Worker wsi->mux.requested_POLLOUT = 0;
343*1c60b9acSAndroid Build Coastguard Worker
344*1c60b9acSAndroid Build Coastguard Worker wsi2 = &wsi->mux.child_list;
345*1c60b9acSAndroid Build Coastguard Worker if (!*wsi2) {
346*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: no children\n", __func__);
347*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_DROP_POLLOUT;
348*1c60b9acSAndroid Build Coastguard Worker }
349*1c60b9acSAndroid Build Coastguard Worker
350*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mqtt)
351*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_DIE;
352*1c60b9acSAndroid Build Coastguard Worker
353*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_dump_waiting_children(wsi);
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker do {
356*1c60b9acSAndroid Build Coastguard Worker struct lws *w, **wa;
357*1c60b9acSAndroid Build Coastguard Worker
358*1c60b9acSAndroid Build Coastguard Worker wa = &(*wsi2)->mux.sibling_list;
359*1c60b9acSAndroid Build Coastguard Worker if (!(*wsi2)->mux.requested_POLLOUT)
360*1c60b9acSAndroid Build Coastguard Worker goto next_child;
361*1c60b9acSAndroid Build Coastguard Worker
362*1c60b9acSAndroid Build Coastguard Worker if (!lwsi_state_can_handle_POLLOUT(wsi))
363*1c60b9acSAndroid Build Coastguard Worker goto next_child;
364*1c60b9acSAndroid Build Coastguard Worker
365*1c60b9acSAndroid Build Coastguard Worker /*
366*1c60b9acSAndroid Build Coastguard Worker * If the nwsi is in the middle of a frame, we can only
367*1c60b9acSAndroid Build Coastguard Worker * continue to send that
368*1c60b9acSAndroid Build Coastguard Worker */
369*1c60b9acSAndroid Build Coastguard Worker
370*1c60b9acSAndroid Build Coastguard Worker if (wsi->mqtt->inside_payload && !(*wsi2)->mqtt->inside_payload)
371*1c60b9acSAndroid Build Coastguard Worker goto next_child;
372*1c60b9acSAndroid Build Coastguard Worker
373*1c60b9acSAndroid Build Coastguard Worker /*
374*1c60b9acSAndroid Build Coastguard Worker * we're going to do writable callback for this child.
375*1c60b9acSAndroid Build Coastguard Worker * move him to be the last child
376*1c60b9acSAndroid Build Coastguard Worker */
377*1c60b9acSAndroid Build Coastguard Worker w = lws_wsi_mux_move_child_to_tail(wsi2);
378*1c60b9acSAndroid Build Coastguard Worker if (!w) {
379*1c60b9acSAndroid Build Coastguard Worker wa = &wsi->mux.child_list;
380*1c60b9acSAndroid Build Coastguard Worker goto next_child;
381*1c60b9acSAndroid Build Coastguard Worker }
382*1c60b9acSAndroid Build Coastguard Worker
383*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: child %s (wsistate 0x%x)\n", __func__,
384*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(w), (unsigned int)w->wsistate);
385*1c60b9acSAndroid Build Coastguard Worker
386*1c60b9acSAndroid Build Coastguard Worker if (lwsi_state(wsi) == LRS_ESTABLISHED &&
387*1c60b9acSAndroid Build Coastguard Worker !wsi->mqtt->inside_payload &&
388*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_puback) {
389*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[LWS_PRE + 4];
390*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: issuing PUBACK for pkt id: %d\n",
391*1c60b9acSAndroid Build Coastguard Worker __func__, wsi->mqtt->ack_pkt_id);
392*1c60b9acSAndroid Build Coastguard Worker
393*1c60b9acSAndroid Build Coastguard Worker /* Fixed header */
394*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE] = LMQCP_PUBACK << 4;
395*1c60b9acSAndroid Build Coastguard Worker /* Remaining len = 2 */
396*1c60b9acSAndroid Build Coastguard Worker buf[LWS_PRE + 1] = 2;
397*1c60b9acSAndroid Build Coastguard Worker /* Packet ID */
398*1c60b9acSAndroid Build Coastguard Worker lws_ser_wu16be(&buf[LWS_PRE + 2], wsi->mqtt->peer_ack_pkt_id);
399*1c60b9acSAndroid Build Coastguard Worker
400*1c60b9acSAndroid Build Coastguard Worker if (lws_write(wsi, (uint8_t *)&buf[LWS_PRE], 4,
401*1c60b9acSAndroid Build Coastguard Worker LWS_WRITE_BINARY) != 4)
402*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_DIE;
403*1c60b9acSAndroid Build Coastguard Worker
404*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->send_puback = 0;
405*1c60b9acSAndroid Build Coastguard Worker w->mux.requested_POLLOUT = 1;
406*1c60b9acSAndroid Build Coastguard Worker
407*1c60b9acSAndroid Build Coastguard Worker wa = &wsi->mux.child_list;
408*1c60b9acSAndroid Build Coastguard Worker goto next_child;
409*1c60b9acSAndroid Build Coastguard Worker }
410*1c60b9acSAndroid Build Coastguard Worker
411*1c60b9acSAndroid Build Coastguard Worker if (lws_callback_as_writeable(w)) {
412*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: Closing child %s\n", __func__, lws_wsi_tag(w));
413*1c60b9acSAndroid Build Coastguard Worker lws_close_free_wsi(w, LWS_CLOSE_STATUS_NOSTATUS,
414*1c60b9acSAndroid Build Coastguard Worker "mqtt pollout handle");
415*1c60b9acSAndroid Build Coastguard Worker wa = &wsi->mux.child_list;
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker
418*1c60b9acSAndroid Build Coastguard Worker next_child:
419*1c60b9acSAndroid Build Coastguard Worker wsi2 = wa;
420*1c60b9acSAndroid Build Coastguard Worker } while (wsi2 && *wsi2 && !lws_send_pipe_choked(wsi));
421*1c60b9acSAndroid Build Coastguard Worker
422*1c60b9acSAndroid Build Coastguard Worker // lws_wsi_mux_dump_waiting_children(wsi);
423*1c60b9acSAndroid Build Coastguard Worker
424*1c60b9acSAndroid Build Coastguard Worker if (lws_wsi_mux_action_pending_writeable_reqs(wsi))
425*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_DIE;
426*1c60b9acSAndroid Build Coastguard Worker
427*1c60b9acSAndroid Build Coastguard Worker return LWS_HP_RET_BAIL_OK;
428*1c60b9acSAndroid Build Coastguard Worker }
429*1c60b9acSAndroid Build Coastguard Worker
430*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
431*1c60b9acSAndroid Build Coastguard Worker static int
rops_issue_keepalive_mqtt(struct lws * wsi,int isvalid)432*1c60b9acSAndroid Build Coastguard Worker rops_issue_keepalive_mqtt(struct lws *wsi, int isvalid)
433*1c60b9acSAndroid Build Coastguard Worker {
434*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
435*1c60b9acSAndroid Build Coastguard Worker
436*1c60b9acSAndroid Build Coastguard Worker if (isvalid) {
437*1c60b9acSAndroid Build Coastguard Worker _lws_validity_confirmed_role(nwsi);
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker return 0;
440*1c60b9acSAndroid Build Coastguard Worker }
441*1c60b9acSAndroid Build Coastguard Worker
442*1c60b9acSAndroid Build Coastguard Worker nwsi->mqtt->send_pingreq = 1;
443*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(nwsi);
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker return 0;
446*1c60b9acSAndroid Build Coastguard Worker }
447*1c60b9acSAndroid Build Coastguard Worker #endif
448*1c60b9acSAndroid Build Coastguard Worker
449*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_role_mqtt(struct lws_context_per_thread * pt,struct lws * wsi)450*1c60b9acSAndroid Build Coastguard Worker rops_close_role_mqtt(struct lws_context_per_thread *pt, struct lws *wsi)
451*1c60b9acSAndroid Build Coastguard Worker {
452*1c60b9acSAndroid Build Coastguard Worker struct lws *nwsi = lws_get_network_wsi(wsi);
453*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_subs_t *s, *s1, *mysub;
454*1c60b9acSAndroid Build Coastguard Worker lws_mqttc_t *c;
455*1c60b9acSAndroid Build Coastguard Worker
456*1c60b9acSAndroid Build Coastguard Worker if (!wsi->mqtt)
457*1c60b9acSAndroid Build Coastguard Worker return 0;
458*1c60b9acSAndroid Build Coastguard Worker
459*1c60b9acSAndroid Build Coastguard Worker c = &wsi->mqtt->client;
460*1c60b9acSAndroid Build Coastguard Worker
461*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&wsi->mqtt->sul_qos_puback_pubrec_wait);
462*1c60b9acSAndroid Build Coastguard Worker
463*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(&c->username);
464*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(&c->password);
465*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(&c->will.message);
466*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(&c->will.topic);
467*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_str_free(&c->id);
468*1c60b9acSAndroid Build Coastguard Worker
469*1c60b9acSAndroid Build Coastguard Worker /* clean up any subscription allocations */
470*1c60b9acSAndroid Build Coastguard Worker
471*1c60b9acSAndroid Build Coastguard Worker s = wsi->mqtt->subs_head;
472*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->subs_head = NULL;
473*1c60b9acSAndroid Build Coastguard Worker while (s) {
474*1c60b9acSAndroid Build Coastguard Worker s1 = s->next;
475*1c60b9acSAndroid Build Coastguard Worker /*
476*1c60b9acSAndroid Build Coastguard Worker * Account for children no longer using nwsi subscription
477*1c60b9acSAndroid Build Coastguard Worker */
478*1c60b9acSAndroid Build Coastguard Worker mysub = lws_mqtt_find_sub(nwsi->mqtt, (const char *)&s[1]);
479*1c60b9acSAndroid Build Coastguard Worker // assert(mysub); /* if child subscribed, nwsi must feel the same */
480*1c60b9acSAndroid Build Coastguard Worker if (mysub) {
481*1c60b9acSAndroid Build Coastguard Worker assert(mysub->ref_count);
482*1c60b9acSAndroid Build Coastguard Worker mysub->ref_count--;
483*1c60b9acSAndroid Build Coastguard Worker }
484*1c60b9acSAndroid Build Coastguard Worker lws_free(s);
485*1c60b9acSAndroid Build Coastguard Worker s = s1;
486*1c60b9acSAndroid Build Coastguard Worker }
487*1c60b9acSAndroid Build Coastguard Worker
488*1c60b9acSAndroid Build Coastguard Worker lws_mqtt_publish_param_t *pub =
489*1c60b9acSAndroid Build Coastguard Worker (lws_mqtt_publish_param_t *)
490*1c60b9acSAndroid Build Coastguard Worker wsi->mqtt->rx_cpkt_param;
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker if (pub)
493*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(pub->topic);
494*1c60b9acSAndroid Build Coastguard Worker
495*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(wsi->mqtt->rx_cpkt_param);
496*1c60b9acSAndroid Build Coastguard Worker
497*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(wsi->mqtt);
498*1c60b9acSAndroid Build Coastguard Worker
499*1c60b9acSAndroid Build Coastguard Worker return 0;
500*1c60b9acSAndroid Build Coastguard Worker }
501*1c60b9acSAndroid Build Coastguard Worker
502*1c60b9acSAndroid Build Coastguard Worker static int
rops_callback_on_writable_mqtt(struct lws * wsi)503*1c60b9acSAndroid Build Coastguard Worker rops_callback_on_writable_mqtt(struct lws *wsi)
504*1c60b9acSAndroid Build Coastguard Worker {
505*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
506*1c60b9acSAndroid Build Coastguard Worker struct lws *network_wsi;
507*1c60b9acSAndroid Build Coastguard Worker #endif
508*1c60b9acSAndroid Build Coastguard Worker int already;
509*1c60b9acSAndroid Build Coastguard Worker
510*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: %s (wsistate 0x%x)\n", __func__, lws_wsi_tag(wsi),
511*1c60b9acSAndroid Build Coastguard Worker (unsigned int)wsi->wsistate);
512*1c60b9acSAndroid Build Coastguard Worker
513*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux.requested_POLLOUT
514*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
515*1c60b9acSAndroid Build Coastguard Worker && !wsi->client_h2_alpn
516*1c60b9acSAndroid Build Coastguard Worker #endif
517*1c60b9acSAndroid Build Coastguard Worker ) {
518*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("already pending writable\n");
519*1c60b9acSAndroid Build Coastguard Worker return 1;
520*1c60b9acSAndroid Build Coastguard Worker }
521*1c60b9acSAndroid Build Coastguard Worker #if 0
522*1c60b9acSAndroid Build Coastguard Worker /* is this for DATA or for control messages? */
523*1c60b9acSAndroid Build Coastguard Worker if (wsi->upgraded_to_http2 && !wsi->h2.h2n->pps &&
524*1c60b9acSAndroid Build Coastguard Worker !lws_h2_tx_cr_get(wsi)) {
525*1c60b9acSAndroid Build Coastguard Worker /*
526*1c60b9acSAndroid Build Coastguard Worker * other side is not able to cope with us sending DATA
527*1c60b9acSAndroid Build Coastguard Worker * anything so no matter if we have POLLOUT on our side if it's
528*1c60b9acSAndroid Build Coastguard Worker * DATA we want to send.
529*1c60b9acSAndroid Build Coastguard Worker *
530*1c60b9acSAndroid Build Coastguard Worker * Delay waiting for our POLLOUT until peer indicates he has
531*1c60b9acSAndroid Build Coastguard Worker * space for more using tx window command in http2 layer
532*1c60b9acSAndroid Build Coastguard Worker */
533*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: %p: skint (%d)\n", __func__, wsi,
534*1c60b9acSAndroid Build Coastguard Worker wsi->h2.tx_cr);
535*1c60b9acSAndroid Build Coastguard Worker wsi->h2.skint = 1;
536*1c60b9acSAndroid Build Coastguard Worker return 0;
537*1c60b9acSAndroid Build Coastguard Worker }
538*1c60b9acSAndroid Build Coastguard Worker
539*1c60b9acSAndroid Build Coastguard Worker wsi->h2.skint = 0;
540*1c60b9acSAndroid Build Coastguard Worker #endif
541*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
542*1c60b9acSAndroid Build Coastguard Worker network_wsi = lws_get_network_wsi(wsi);
543*1c60b9acSAndroid Build Coastguard Worker #endif
544*1c60b9acSAndroid Build Coastguard Worker already = lws_wsi_mux_mark_parents_needing_writeable(wsi);
545*1c60b9acSAndroid Build Coastguard Worker
546*1c60b9acSAndroid Build Coastguard Worker /* for network action, act only on the network wsi */
547*1c60b9acSAndroid Build Coastguard Worker
548*1c60b9acSAndroid Build Coastguard Worker if (already
549*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
550*1c60b9acSAndroid Build Coastguard Worker && !network_wsi->client_mux_substream
551*1c60b9acSAndroid Build Coastguard Worker #endif
552*1c60b9acSAndroid Build Coastguard Worker )
553*1c60b9acSAndroid Build Coastguard Worker return 1;
554*1c60b9acSAndroid Build Coastguard Worker
555*1c60b9acSAndroid Build Coastguard Worker return 0;
556*1c60b9acSAndroid Build Coastguard Worker }
557*1c60b9acSAndroid Build Coastguard Worker
558*1c60b9acSAndroid Build Coastguard Worker static int
rops_close_kill_connection_mqtt(struct lws * wsi,enum lws_close_status reason)559*1c60b9acSAndroid Build Coastguard Worker rops_close_kill_connection_mqtt(struct lws *wsi, enum lws_close_status reason)
560*1c60b9acSAndroid Build Coastguard Worker {
561*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" %s, his parent %s: child list %p, siblings:\n",
562*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi),
563*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi->mux.parent_wsi), wsi->mux.child_list);
564*1c60b9acSAndroid Build Coastguard Worker //lws_wsi_mux_dump_children(wsi);
565*1c60b9acSAndroid Build Coastguard Worker
566*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux_substream
567*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
568*1c60b9acSAndroid Build Coastguard Worker || wsi->client_mux_substream
569*1c60b9acSAndroid Build Coastguard Worker #endif
570*1c60b9acSAndroid Build Coastguard Worker ) {
571*1c60b9acSAndroid Build Coastguard Worker lwsl_info("closing %s: parent %s: first child %p\n",
572*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi),
573*1c60b9acSAndroid Build Coastguard Worker lws_wsi_tag(wsi->mux.parent_wsi),
574*1c60b9acSAndroid Build Coastguard Worker wsi->mux.child_list);
575*1c60b9acSAndroid Build Coastguard Worker
576*1c60b9acSAndroid Build Coastguard Worker if (wsi->mux.child_list && lwsl_visible(LLL_INFO)) {
577*1c60b9acSAndroid Build Coastguard Worker lwsl_info(" parent %s: closing children: list:\n", lws_wsi_tag(wsi));
578*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_dump_children(wsi);
579*1c60b9acSAndroid Build Coastguard Worker }
580*1c60b9acSAndroid Build Coastguard Worker
581*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_close_children(wsi, (int)reason);
582*1c60b9acSAndroid Build Coastguard Worker }
583*1c60b9acSAndroid Build Coastguard Worker
584*1c60b9acSAndroid Build Coastguard Worker if ((
585*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
586*1c60b9acSAndroid Build Coastguard Worker wsi->client_mux_substream ||
587*1c60b9acSAndroid Build Coastguard Worker #endif
588*1c60b9acSAndroid Build Coastguard Worker wsi->mux_substream) &&
589*1c60b9acSAndroid Build Coastguard Worker wsi->mux.parent_wsi) {
590*1c60b9acSAndroid Build Coastguard Worker lws_wsi_mux_sibling_disconnect(wsi);
591*1c60b9acSAndroid Build Coastguard Worker }
592*1c60b9acSAndroid Build Coastguard Worker
593*1c60b9acSAndroid Build Coastguard Worker return 0;
594*1c60b9acSAndroid Build Coastguard Worker }
595*1c60b9acSAndroid Build Coastguard Worker
596*1c60b9acSAndroid Build Coastguard Worker static const lws_rops_t rops_table_mqtt[] = {
597*1c60b9acSAndroid Build Coastguard Worker /* 1 */ { .handle_POLLIN = rops_handle_POLLIN_mqtt },
598*1c60b9acSAndroid Build Coastguard Worker /* 2 */ { .handle_POLLOUT = rops_handle_POLLOUT_mqtt },
599*1c60b9acSAndroid Build Coastguard Worker /* 3 */ { .callback_on_writable = rops_callback_on_writable_mqtt },
600*1c60b9acSAndroid Build Coastguard Worker /* 4 */ { .close_role = rops_close_role_mqtt },
601*1c60b9acSAndroid Build Coastguard Worker /* 5 */ { .close_kill_connection = rops_close_kill_connection_mqtt },
602*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
603*1c60b9acSAndroid Build Coastguard Worker /* 6 */ { .client_bind = rops_client_bind_mqtt },
604*1c60b9acSAndroid Build Coastguard Worker /* 7 */ { .issue_keepalive = rops_issue_keepalive_mqtt },
605*1c60b9acSAndroid Build Coastguard Worker #endif
606*1c60b9acSAndroid Build Coastguard Worker };
607*1c60b9acSAndroid Build Coastguard Worker
608*1c60b9acSAndroid Build Coastguard Worker struct lws_role_ops role_ops_mqtt = {
609*1c60b9acSAndroid Build Coastguard Worker /* role name */ "mqtt",
610*1c60b9acSAndroid Build Coastguard Worker /* alpn id */ "x-amzn-mqtt-ca", /* "mqtt/3.1.1" */
611*1c60b9acSAndroid Build Coastguard Worker
612*1c60b9acSAndroid Build Coastguard Worker /* rops_table */ rops_table_mqtt,
613*1c60b9acSAndroid Build Coastguard Worker /* rops_idx */ {
614*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_check_upgrades */
615*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_pt_init_destroy */ 0x00,
616*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_init_vhost */
617*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_destroy_vhost */ 0x00,
618*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_service_flag_pending */
619*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_handle_POLLIN */ 0x01,
620*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_handle_POLLOUT */
621*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_perform_user_POLLOUT */ 0x20,
622*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_callback_on_writable */
623*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_tx_credit */ 0x30,
624*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_write_role_protocol */
625*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_encapsulation_parent */ 0x00,
626*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_alpn_negotiated */
627*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_close_via_role_protocol */ 0x00,
628*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_close_role */
629*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_close_kill_connection */ 0x45,
630*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_destroy_role */
631*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_adoption_bind */ 0x00,
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_client_bind */
634*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_CLIENT)
635*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_issue_keepalive */ 0x67,
636*1c60b9acSAndroid Build Coastguard Worker #else
637*1c60b9acSAndroid Build Coastguard Worker /* LWS_ROPS_issue_keepalive */ 0x00,
638*1c60b9acSAndroid Build Coastguard Worker #endif
639*1c60b9acSAndroid Build Coastguard Worker },
640*1c60b9acSAndroid Build Coastguard Worker
641*1c60b9acSAndroid Build Coastguard Worker .adoption_cb = { LWS_CALLBACK_MQTT_NEW_CLIENT_INSTANTIATED,
642*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_NEW_CLIENT_INSTANTIATED },
643*1c60b9acSAndroid Build Coastguard Worker .rx_cb = { LWS_CALLBACK_MQTT_CLIENT_RX,
644*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_CLIENT_RX },
645*1c60b9acSAndroid Build Coastguard Worker .writeable_cb = { LWS_CALLBACK_MQTT_CLIENT_WRITEABLE,
646*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_CLIENT_WRITEABLE },
647*1c60b9acSAndroid Build Coastguard Worker .close_cb = { LWS_CALLBACK_MQTT_CLIENT_CLOSED,
648*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_CLIENT_CLOSED },
649*1c60b9acSAndroid Build Coastguard Worker .protocol_bind_cb = { LWS_CALLBACK_MQTT_IDLE,
650*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_IDLE },
651*1c60b9acSAndroid Build Coastguard Worker .protocol_unbind_cb = { LWS_CALLBACK_MQTT_DROP_PROTOCOL,
652*1c60b9acSAndroid Build Coastguard Worker LWS_CALLBACK_MQTT_DROP_PROTOCOL },
653*1c60b9acSAndroid Build Coastguard Worker .file_handle = 0,
654*1c60b9acSAndroid Build Coastguard Worker };
655