2019-04-21 19:57:19 +01:00
|
|
|
/*
|
2019-06-22 06:59:49 +01:00
|
|
|
* libwebsockets lib/abstract/transports/raw-skt.c
|
2019-04-21 19:57:19 +01:00
|
|
|
*
|
|
|
|
* Copyright (C) 2019 Andy Green <andy@warmcat.com>
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "core/private.h"
|
|
|
|
#include "abstract/private.h"
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
typedef struct lws_abstxp_raw_skt_priv {
|
|
|
|
struct lws_abs *abs;
|
2019-04-21 19:57:19 +01:00
|
|
|
struct lws *wsi;
|
|
|
|
|
|
|
|
lws_dll2_t same_abs_transport_list;
|
|
|
|
|
|
|
|
uint8_t established:1;
|
|
|
|
uint8_t connecting:1;
|
2019-06-22 06:59:49 +01:00
|
|
|
} abs_raw_skt_priv_t;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
struct vhd {
|
|
|
|
lws_dll2_owner_t owner;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
heartbeat_cb(struct lws_dll2 *d, void *user)
|
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = lws_container_of(d, abs_raw_skt_priv_t,
|
|
|
|
same_abs_transport_list);
|
|
|
|
|
|
|
|
if (priv->abs->ap->heartbeat)
|
|
|
|
priv->abs->ap->heartbeat(priv->abs->api);
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
|
|
|
|
void *user, void *in, size_t len)
|
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)user;
|
2019-04-21 19:57:19 +01:00
|
|
|
struct vhd *vhd = (struct vhd *)
|
|
|
|
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
|
|
|
lws_get_protocol(wsi));
|
|
|
|
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_PROTOCOL_INIT:
|
|
|
|
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
|
|
|
lws_get_protocol(wsi), sizeof(struct vhd));
|
|
|
|
if (!vhd)
|
|
|
|
return 1;
|
|
|
|
lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
|
|
|
|
lws_get_protocol(wsi),
|
|
|
|
LWS_CALLBACK_USER, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_USER:
|
|
|
|
/*
|
|
|
|
* This comes at 1Hz without a wsi context, so there is no
|
|
|
|
* valid priv. We need to track the live abstract objects that
|
|
|
|
* are using our abstract protocol, and pass the heartbeat
|
|
|
|
* through to the ones that care.
|
|
|
|
*/
|
|
|
|
if (!vhd)
|
|
|
|
break;
|
|
|
|
|
|
|
|
lws_dll2_foreach_safe(&vhd->owner, NULL, heartbeat_cb);
|
|
|
|
|
|
|
|
lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
|
|
|
|
lws_get_protocol(wsi),
|
|
|
|
LWS_CALLBACK_USER, 1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_RAW_CONNECTED:
|
|
|
|
lwsl_debug("LWS_CALLBACK_RAW_CONNECTED\n");
|
|
|
|
priv->connecting = 0;
|
|
|
|
priv->established = 1;
|
2019-06-22 06:59:49 +01:00
|
|
|
if (priv->abs->ap->accept)
|
|
|
|
priv->abs->ap->accept(priv->abs->api);
|
2019-04-21 19:57:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
|
|
|
lwsl_user("CONNECTION_ERROR\n");
|
|
|
|
if (in)
|
|
|
|
lwsl_user(" %s\n", (const char *)in);
|
|
|
|
|
|
|
|
/* fallthru */
|
|
|
|
case LWS_CALLBACK_RAW_CLOSE:
|
|
|
|
if (!user)
|
|
|
|
break;
|
|
|
|
lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n");
|
|
|
|
priv->established = 0;
|
|
|
|
priv->connecting = 0;
|
2019-06-22 06:59:49 +01:00
|
|
|
if (priv->abs && priv->abs->ap->closed)
|
|
|
|
priv->abs->ap->closed(priv->abs->api);
|
2019-04-21 19:57:19 +01:00
|
|
|
lws_set_wsi_user(wsi, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_RAW_RX:
|
|
|
|
lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
|
2019-06-22 06:59:49 +01:00
|
|
|
return !!priv->abs->ap->rx(priv->abs->api, in, len);
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
case LWS_CALLBACK_RAW_WRITEABLE:
|
|
|
|
lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n");
|
2019-06-22 06:59:49 +01:00
|
|
|
priv->abs->ap->writeable(priv->abs->api,
|
2019-04-21 19:57:19 +01:00
|
|
|
lws_get_peer_write_allowance(priv->wsi));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL:
|
|
|
|
lws_dll2_add_tail(&priv->same_abs_transport_list, &vhd->owner);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL:
|
|
|
|
lws_dll2_remove(&priv->same_abs_transport_list);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
static int
|
|
|
|
lws_atcrs_close(lws_abs_transport_inst_t *ati)
|
|
|
|
{
|
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
|
|
|
|
struct lws *wsi = priv->wsi;
|
|
|
|
|
|
|
|
if (!priv->wsi)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!lws_raw_transaction_completed(priv->wsi))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
priv->wsi = NULL;
|
|
|
|
lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
|
|
|
|
|
|
|
|
/* priv is destroyed in the CLOSE callback */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-04-21 19:57:19 +01:00
|
|
|
const struct lws_protocols protocol_abs_client_raw_skt = {
|
|
|
|
"lws-abs-cli-raw-skt", callback_abs_client_raw_skt,
|
|
|
|
0, 1024, 1024, NULL, 0
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
if (!priv->wsi) {
|
|
|
|
lwsl_err("%s: NULL priv->wsi\n", __func__);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lwsl_debug("%s: priv %p, wsi %p, ro %p\n", __func__,
|
|
|
|
priv, priv->wsi, priv->wsi->role_ops);
|
|
|
|
|
|
|
|
if (lws_write(priv->wsi, buf, len, LWS_WRITE_RAW) < 0)
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_close(ati);
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !defined(LWS_WITHOUT_CLIENT)
|
|
|
|
static int
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_client_conn(const lws_abs_t *abs)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)abs->ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
struct lws_client_connect_info i;
|
2019-06-19 19:10:14 +01:00
|
|
|
const lws_token_map_t *tm;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
if (priv->connecting)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (priv->established) {
|
|
|
|
lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&i, 0, sizeof(i));
|
|
|
|
|
2019-06-19 19:10:14 +01:00
|
|
|
/* address and port are passed-in using the abstract transport tokens */
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_DNS_ADDRESS);
|
2019-06-19 19:10:14 +01:00
|
|
|
if (!tm) {
|
2019-06-22 06:59:49 +01:00
|
|
|
lwsl_notice("%s: raw_skt needs LTMI_PEER_V_DNS_ADDRESS\n",
|
2019-06-19 19:10:14 +01:00
|
|
|
__func__);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i.address = tm->u.value;
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_PORT);
|
2019-06-19 19:10:14 +01:00
|
|
|
if (!tm) {
|
2019-06-22 06:59:49 +01:00
|
|
|
lwsl_notice("%s: raw_skt needs LTMI_PEER_LV_PORT\n", __func__);
|
2019-06-19 19:10:14 +01:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i.port = tm->u.lvalue;
|
|
|
|
|
|
|
|
/* optional */
|
|
|
|
i.ssl_connection = 0;
|
2019-06-22 06:59:49 +01:00
|
|
|
tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_TLS_FLAGS);
|
2019-06-19 19:10:14 +01:00
|
|
|
if (tm)
|
|
|
|
i.ssl_connection = tm->u.lvalue;
|
|
|
|
|
|
|
|
|
|
|
|
lwsl_debug("%s: raw_skt priv %p connecting to %s:%u %p\n",
|
2019-06-22 06:59:49 +01:00
|
|
|
__func__, priv, i.address, i.port, abs->vh->context);
|
2019-06-19 19:10:14 +01:00
|
|
|
|
2019-04-21 19:57:19 +01:00
|
|
|
i.path = "";
|
|
|
|
i.method = "RAW";
|
2019-06-22 06:59:49 +01:00
|
|
|
i.vhost = abs->vh;
|
2019-04-21 19:57:19 +01:00
|
|
|
i.userdata = priv;
|
|
|
|
i.host = i.address;
|
|
|
|
i.pwsi = &priv->wsi;
|
|
|
|
i.origin = i.address;
|
2019-06-22 06:59:49 +01:00
|
|
|
i.context = abs->vh->context;
|
2019-04-21 19:57:19 +01:00
|
|
|
i.local_protocol_name = "lws-abs-cli-raw-skt";
|
|
|
|
|
|
|
|
priv->wsi = lws_client_connect_via_info(&i);
|
|
|
|
if (!priv->wsi)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
priv->connecting = 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t *ati)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
if (!priv->wsi || !priv->established)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
lws_callback_on_writable(priv->wsi);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
static int
|
|
|
|
lws_atcrs_create(struct lws_abs *ai)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *at = (abs_raw_skt_priv_t *)ai->ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
memset(at, 0, sizeof(*at));
|
|
|
|
at->abs = ai;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
return 0;
|
2019-04-21 19:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_destroy(lws_abs_transport_inst_t **pati)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
/*
|
|
|
|
* We don't free anything because the abstract layer combined our
|
|
|
|
* allocation with that of the instance, and it will free the whole
|
|
|
|
* thing after this.
|
|
|
|
*/
|
|
|
|
*pati = NULL;
|
2019-04-21 19:57:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
lws_set_timeout(priv->wsi, reason, secs);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2019-06-22 06:59:49 +01:00
|
|
|
lws_atcrs_state(lws_abs_transport_inst_t *ati)
|
2019-04-21 19:57:19 +01:00
|
|
|
{
|
2019-06-22 06:59:49 +01:00
|
|
|
abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
|
2019-04-21 19:57:19 +01:00
|
|
|
|
|
|
|
if (!priv || !priv->wsi || (!priv->established && !priv->connecting))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
const lws_abs_transport_t lws_abs_transport_cli_raw_skt = {
|
|
|
|
.name = "raw_skt",
|
|
|
|
.alloc = sizeof(abs_raw_skt_priv_t),
|
|
|
|
|
|
|
|
.create = lws_atcrs_create,
|
|
|
|
.destroy = lws_atcrs_destroy,
|
2019-04-21 19:57:19 +01:00
|
|
|
|
2019-06-22 06:59:49 +01:00
|
|
|
.tx = lws_atcrs_tx,
|
2019-04-21 19:57:19 +01:00
|
|
|
#if defined(LWS_WITHOUT_CLIENT)
|
2019-06-22 06:59:49 +01:00
|
|
|
.client_conn = NULL,
|
2019-04-21 19:57:19 +01:00
|
|
|
#else
|
2019-06-22 06:59:49 +01:00
|
|
|
.client_conn = lws_atcrs_client_conn,
|
2019-04-21 19:57:19 +01:00
|
|
|
#endif
|
2019-06-22 06:59:49 +01:00
|
|
|
.close = lws_atcrs_close,
|
|
|
|
.ask_for_writeable = lws_atcrs_ask_for_writeable,
|
|
|
|
.set_timeout = lws_atcrs_set_timeout,
|
|
|
|
.state = lws_atcrs_state,
|
2019-04-21 19:57:19 +01:00
|
|
|
};
|