2 * libwebsockets lib/abstract/transports/raw-skt.c
4 * Copyright (C) 2019 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,
22 #include "core/private.h"
23 #include "abstract/private.h"
25 typedef struct lws_abstxp_raw_skt_priv {
29 lws_dll2_t same_abs_transport_list;
31 uint8_t established:1;
36 lws_dll2_owner_t owner;
40 heartbeat_cb(struct lws_dll2 *d, void *user)
42 abs_raw_skt_priv_t *priv = lws_container_of(d, abs_raw_skt_priv_t,
43 same_abs_transport_list);
45 if (priv->abs->ap->heartbeat)
46 priv->abs->ap->heartbeat(priv->abs->api);
52 callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
53 void *user, void *in, size_t len)
55 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)user;
56 struct vhd *vhd = (struct vhd *)
57 lws_protocol_vh_priv_get(lws_get_vhost(wsi),
58 lws_get_protocol(wsi));
61 case LWS_CALLBACK_PROTOCOL_INIT:
62 vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
63 lws_get_protocol(wsi), sizeof(struct vhd));
66 lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
67 lws_get_protocol(wsi),
68 LWS_CALLBACK_USER, 1);
71 case LWS_CALLBACK_USER:
73 * This comes at 1Hz without a wsi context, so there is no
74 * valid priv. We need to track the live abstract objects that
75 * are using our abstract protocol, and pass the heartbeat
76 * through to the ones that care.
81 lws_dll2_foreach_safe(&vhd->owner, NULL, heartbeat_cb);
83 lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
84 lws_get_protocol(wsi),
85 LWS_CALLBACK_USER, 1);
88 case LWS_CALLBACK_RAW_CONNECTED:
89 lwsl_debug("LWS_CALLBACK_RAW_CONNECTED\n");
91 priv->established = 1;
92 if (priv->abs->ap->accept)
93 priv->abs->ap->accept(priv->abs->api);
96 * we are bound to a sequencer who wants to know about
97 * our lifecycle events
100 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED,
104 case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
105 lwsl_user("CONNECTION_ERROR\n");
107 lwsl_user(" %s\n", (const char *)in);
111 * we are bound to a sequencer who wants to know about
112 * our lifecycle events
115 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL,
121 case LWS_CALLBACK_RAW_CLOSE:
127 * we are bound to a sequencer who wants to know about
128 * our lifecycle events
131 lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE,
135 lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n");
136 priv->established = 0;
137 priv->connecting = 0;
138 if (priv->abs && priv->abs->ap->closed)
139 priv->abs->ap->closed(priv->abs->api);
140 lws_set_wsi_user(wsi, NULL);
143 case LWS_CALLBACK_RAW_RX:
144 lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
145 return !!priv->abs->ap->rx(priv->abs->api, in, len);
147 case LWS_CALLBACK_RAW_WRITEABLE:
148 lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n");
149 priv->abs->ap->writeable(priv->abs->api,
150 lws_get_peer_write_allowance(priv->wsi));
153 case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL:
154 lws_dll2_add_tail(&priv->same_abs_transport_list, &vhd->owner);
157 case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL:
158 lws_dll2_remove(&priv->same_abs_transport_list);
169 lws_atcrs_close(lws_abs_transport_inst_t *ati)
171 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
172 struct lws *wsi = priv->wsi;
177 if (!lws_raw_transaction_completed(priv->wsi))
181 lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
183 /* priv is destroyed in the CLOSE callback */
189 const struct lws_protocols protocol_abs_client_raw_skt = {
190 "lws-abs-cli-raw-skt", callback_abs_client_raw_skt,
191 0, 1024, 1024, NULL, 0
195 lws_atcrs_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len)
197 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
200 lwsl_err("%s: NULL priv->wsi\n", __func__);
204 lwsl_debug("%s: priv %p, wsi %p, ro %p\n", __func__,
205 priv, priv->wsi, priv->wsi->role_ops);
207 if (lws_write(priv->wsi, buf, len, LWS_WRITE_RAW) < 0)
208 lws_atcrs_close(ati);
213 #if !defined(LWS_WITHOUT_CLIENT)
215 lws_atcrs_client_conn(const lws_abs_t *abs)
217 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)abs->ati;
218 struct lws_client_connect_info i;
219 const lws_token_map_t *tm;
221 if (priv->connecting)
224 if (priv->established) {
225 lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
230 memset(&i, 0, sizeof(i));
232 /* address and port are passed-in using the abstract transport tokens */
234 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_DNS_ADDRESS);
236 lwsl_notice("%s: raw_skt needs LTMI_PEER_V_DNS_ADDRESS\n",
241 i.address = tm->u.value;
243 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_PORT);
245 lwsl_notice("%s: raw_skt needs LTMI_PEER_LV_PORT\n", __func__);
249 i.port = tm->u.lvalue;
252 i.ssl_connection = 0;
253 tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_TLS_FLAGS);
255 i.ssl_connection = tm->u.lvalue;
258 lwsl_debug("%s: raw_skt priv %p connecting to %s:%u %p\n",
259 __func__, priv, i.address, i.port, abs->vh->context);
267 i.origin = i.address;
268 i.context = abs->vh->context;
269 i.local_protocol_name = "lws-abs-cli-raw-skt";
271 i.opaque_user_data = abs->opaque_user_data;
273 priv->wsi = lws_client_connect_via_info(&i);
277 priv->connecting = 1;
284 lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t *ati)
286 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
288 if (!priv->wsi || !priv->established)
291 lws_callback_on_writable(priv->wsi);
297 lws_atcrs_create(struct lws_abs *ai)
299 abs_raw_skt_priv_t *at = (abs_raw_skt_priv_t *)ai->ati;
301 memset(at, 0, sizeof(*at));
308 lws_atcrs_destroy(lws_abs_transport_inst_t **pati)
311 * We don't free anything because the abstract layer combined our
312 * allocation with that of the instance, and it will free the whole
319 lws_atcrs_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs)
321 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
323 lws_set_timeout(priv->wsi, reason, secs);
329 lws_atcrs_state(lws_abs_transport_inst_t *ati)
331 abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
333 if (!priv || !priv->wsi || (!priv->established && !priv->connecting))
339 const lws_abs_transport_t lws_abs_transport_cli_raw_skt = {
341 .alloc = sizeof(abs_raw_skt_priv_t),
343 .create = lws_atcrs_create,
344 .destroy = lws_atcrs_destroy,
347 #if defined(LWS_WITHOUT_CLIENT)
350 .client_conn = lws_atcrs_client_conn,
352 .close = lws_atcrs_close,
353 .ask_for_writeable = lws_atcrs_ask_for_writeable,
354 .set_timeout = lws_atcrs_set_timeout,
355 .state = lws_atcrs_state,