diff options
author | Andy Green <andy@warmcat.com> | 2019-04-21 19:57:19 +0100 |
---|---|---|
committer | Andy Green <andy@warmcat.com> | 2019-05-04 08:28:31 +0100 |
commit | 8d473ad78c4d816d3e872f6d2d67e59a0e92b84f (patch) | |
tree | fd19ec0a79aeebce5d108819537393fd0334c6ae /lib/abstract | |
parent | ae6346db64cda88128a964d6df8ec302a3818a54 (diff) | |
download | libwebsockets-8d473ad78c4d816d3e872f6d2d67e59a0e92b84f.tar.gz |
smtp: make abstract
Diffstat (limited to 'lib/abstract')
-rw-r--r-- | lib/abstract/abstract.c | 52 | ||||
-rw-r--r-- | lib/abstract/private.h | 68 | ||||
-rw-r--r-- | lib/abstract/smtp/private.h | 51 | ||||
-rw-r--r-- | lib/abstract/smtp/smtp.c | 395 | ||||
-rw-r--r-- | lib/abstract/transports/raw-skt.c | 309 |
5 files changed, 875 insertions, 0 deletions
diff --git a/lib/abstract/abstract.c b/lib/abstract/abstract.c new file mode 100644 index 00000000..2a602cf7 --- /dev/null +++ b/lib/abstract/abstract.c @@ -0,0 +1,52 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010-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> + +extern lws_abstract_t lws_abstract_transport_cli_raw_skt; + +static const lws_abstract_t *available_abstractions[] = { + &lws_abstract_transport_cli_raw_skt, +}; + +/* + * the definition is opaque, so a helper to copy it into place + */ + +void +lws_abstract_copy(lws_abstract_t *dest, const lws_abstract_t *src) +{ + memcpy(dest, src, sizeof(*dest)); +} + + +const lws_abstract_t * +lws_abstract_get_by_name(const char *name) +{ + int n; + + for (n = 0; n < (int)LWS_ARRAY_SIZE(available_abstractions); n++) + if (!strcmp(name, available_abstractions[n]->name)) + return available_abstractions[n]; + + return NULL; +} diff --git a/lib/abstract/private.h b/lib/abstract/private.h new file mode 100644 index 00000000..4962268d --- /dev/null +++ b/lib/abstract/private.h @@ -0,0 +1,68 @@ +/* + * libwebsockets - small server side websockets and web server implementation + * + * Copyright (C) 2010-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 + */ + +struct lws_abstract; + +typedef void lws_abs_user_t; +typedef void lws_abs_t; + +/* + * The abstract callbacks are in three parts + * + * - create and destroy + * + * - events handled by the transport + * + * - events handled by the user of the transport + * + * the canned abstract transports only define the first two types... the + * remaining callbacks must be filled in to callback functions specific to + * the user of the abstract transport. + */ + +typedef struct lws_abstract { + + const char *name; + + lws_abs_user_t * (*create)(struct lws_abstract *abs, void *user); + void (*destroy)(lws_abs_user_t **d); + + /* events the abstract object invokes (filled in by transport) */ + + int (*tx)(lws_abs_user_t *d, uint8_t *buf, size_t len); + int (*client_conn)(lws_abs_user_t *d, struct lws_vhost *vh, + const char *ip, uint16_t port, int tls_flags); + int (*close)(lws_abs_user_t *d); + int (*ask_for_writeable)(lws_abs_user_t *d); + int (*set_timeout)(lws_abs_user_t *d, int reason, int secs); + int (*state)(lws_abs_user_t *d); + + /* events the transport invokes (filled in by abstract object) */ + + int (*accept)(lws_abs_user_t *d); + int (*rx)(lws_abs_user_t *d, uint8_t *buf, size_t len); + int (*writeable)(lws_abs_user_t *d, size_t budget); + int (*closed)(lws_abs_user_t *d); + int (*heartbeat)(lws_abs_user_t *d); + +} lws_abstract_t; + + diff --git a/lib/abstract/smtp/private.h b/lib/abstract/smtp/private.h new file mode 100644 index 00000000..bbc51f85 --- /dev/null +++ b/lib/abstract/smtp/private.h @@ -0,0 +1,51 @@ +/* + * libwebsockets lib/abstruct/smtp/private.h + * + * 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 "abstract/private.h" + +/** enum lwsgs_smtp_states - where we are in SMTP protocol sequence */ +typedef enum lwsgs_smtp_states { + LGSSMTP_IDLE, /**< awaiting new email */ + LGSSMTP_CONNECTING, /**< opening tcp connection to MTA */ + LGSSMTP_CONNECTED, /**< tcp connection to MTA is connected */ + LGSSMTP_SENT_HELO, /**< sent the HELO */ + LGSSMTP_SENT_FROM, /**< sent FROM */ + LGSSMTP_SENT_TO, /**< sent TO */ + LGSSMTP_SENT_DATA, /**< sent DATA request */ + LGSSMTP_SENT_BODY, /**< sent the email body */ + LGSSMTP_SENT_QUIT, /**< sent the session quit */ +} lwsgs_smtp_states_t; + +/** struct lws_email - abstract context for performing SMTP operations */ +typedef struct lws_smtp_client { + struct lws_dll2_owner pending_owner; + + lws_smtp_client_info_t i; + lws_abstract_t abs; + + lws_abs_user_t *abs_conn; + + lwsgs_smtp_states_t estate; + time_t email_connect_started; + + unsigned char send_pending:1; +} lws_smtp_client_t; + diff --git a/lib/abstract/smtp/smtp.c b/lib/abstract/smtp/smtp.c new file mode 100644 index 00000000..988700f8 --- /dev/null +++ b/lib/abstract/smtp/smtp.c @@ -0,0 +1,395 @@ +/* + * Abstract SMTP support for libwebsockets + * + * Copyright (C) 2016-2019 Andy Green <andy@warmcat.com> + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU 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/smtp/private.h" + +static const short retcodes[] = { + 0, /* idle */ + 0, /* connecting */ + 220, /* connected */ + 250, /* helo */ + 250, /* from */ + 250, /* to */ + 354, /* data */ + 250, /* body */ + 221, /* quit */ +}; + +static void +lws_smtp_client_state_transition(lws_smtp_client_t *c, lwsgs_smtp_states_t s) +{ + lwsl_debug("%s: cli %p: state %d -> %d\n", __func__, c, c->estate, s); + c->estate = s; +} + +void +lws_smtp_client_kick(lws_smtp_client_t *c) +{ + lws_smtp_email_t *e; + lws_dll2_t *d; + char buf[64]; + int n; + + if (c->estate != LGSSMTP_IDLE) + return; + + /* is there something to do? */ + +again: + d = lws_dll2_get_head(&c->pending_owner); + if (!d) + return; + + e = lws_container_of(d, lws_smtp_email_t, list); + + /* do we need to time out this guy? */ + + if ((time_t)lws_now_secs() - e->added > (time_t)c->i.delivery_timeout) { + lwsl_err("%s: timing out email\n", __func__); + lws_dll2_remove(&e->list); + n = lws_snprintf(buf, sizeof(buf), "0 Timed out retrying send"); + e->done(e, buf, n); + + if (lws_dll2_get_head(&c->pending_owner)) + goto again; + + return; + } + + /* is it time for his retry yet? */ + + if (e->last_try && + (time_t)lws_now_secs() - e->last_try < (time_t)c->i.retry_interval) { + /* no... send him to the tail */ + lws_dll2_remove(&e->list); + lws_dll2_add_tail(&e->list, &c->pending_owner); + return; + } + + /* check if we have a connection to the server ongoing */ + + if (c->abs.state(c->abs_conn)) { + /* + * there's a connection, it could be still trying to connect + * or established + */ + c->abs.ask_for_writeable(c->abs_conn); + + return; + } + + /* there's no existing connection */ + + lws_smtp_client_state_transition(c, LGSSMTP_CONNECTING); + lwsl_notice("LGSSMTP_IDLE: connecting to %s:25\n", c->i.ip); + + if (c->abs.client_conn(c->abs_conn, c->i.vh, c->i.ip, 25, 0)) { + lwsl_err("%s: failed to connect to %s:25\n", + __func__, c->i.ip); + + return; + } + + e->tries++; + e->last_try = lws_now_secs(); +} + +/* + * we became connected + */ + +static int +lws_smtp_client_abs_accept(lws_abs_user_t *abs_priv) +{ + lws_smtp_client_t *c = (lws_smtp_client_t *)abs_priv; + + lws_smtp_client_state_transition(c, LGSSMTP_CONNECTED); + + return 0; +} + +static int +lws_smtp_client_abs_rx(lws_abs_user_t *abs_priv, uint8_t *buf, size_t len) +{ + lws_smtp_client_t *c = (lws_smtp_client_t *)abs_priv; + lws_smtp_email_t *e; + lws_dll2_t *pd2; + int n; + + pd2 = lws_dll2_get_head(&c->pending_owner); + if (!pd2) + return 0; + + e = lws_container_of(pd2, lws_smtp_email_t, list); + if (!e) + return 0; + + lwsl_debug("%s: rx: '%.*s'\n", __func__, (int)len, (const char *)buf); + + n = atoi((char *)buf); + if (n != retcodes[c->estate]) { + lwsl_notice("%s: bad response from server: %d (state %d) %.*s\n", + __func__, n, c->estate, (int)len, buf); + + lws_dll2_remove(&e->list); + lws_dll2_add_tail(&e->list, &c->pending_owner); + lws_smtp_client_state_transition(c, LGSSMTP_IDLE); + lws_smtp_client_kick(c); + + return 0; + } + + if (c->estate == LGSSMTP_SENT_QUIT) { + lwsl_debug("%s: done\n", __func__); + lws_smtp_client_state_transition(c, LGSSMTP_IDLE); + + lws_dll2_remove(&e->list); + if (e->done && e->done(e, "sent OK", 7)) + return 1; + + return 1; + } + + c->send_pending = 1; + c->abs.ask_for_writeable(c->abs_conn); + + return 0; +} + +static int +lws_smtp_client_abs_writeable(lws_abs_user_t *abs_priv, size_t budget) +{ + lws_smtp_client_t *c = (lws_smtp_client_t *)abs_priv; + char b[256 + LWS_PRE], *p = b + LWS_PRE; + lws_smtp_email_t *e; + lws_dll2_t *pd2; + int n; + + pd2 = lws_dll2_get_head(&c->pending_owner); + if (!pd2) + return 0; + + e = lws_container_of(pd2, lws_smtp_email_t, list); + if (!e) + return 0; + + + if (!c->send_pending) + return 0; + + c->send_pending = 0; + + lwsl_debug("%s: writing response for state %d\n", __func__, c->estate); + + switch (c->estate) { + case LGSSMTP_CONNECTED: + n = lws_snprintf(p, sizeof(b) - LWS_PRE, "HELO %s\n", c->i.helo); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_HELO); + break; + case LGSSMTP_SENT_HELO: + n = lws_snprintf(p, sizeof(b) - LWS_PRE, "MAIL FROM: <%s>\n", + e->email_from); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_FROM); + break; + case LGSSMTP_SENT_FROM: + n = lws_snprintf(p, sizeof(b) - LWS_PRE, + "RCPT TO: <%s>\n", e->email_to); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_TO); + break; + case LGSSMTP_SENT_TO: + n = lws_snprintf(p, sizeof(b) - LWS_PRE, "DATA\n"); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_DATA); + break; + case LGSSMTP_SENT_DATA: + p = (char *)e->payload; + n = strlen(e->payload); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_BODY); + break; + case LGSSMTP_SENT_BODY: + n = lws_snprintf(p, sizeof(b) - LWS_PRE, "quit\n"); + lws_smtp_client_state_transition(c, LGSSMTP_SENT_QUIT); + break; + case LGSSMTP_SENT_QUIT: + return 0; + + default: + return 0; + } + + //puts(p); + c->abs.tx(c->abs_conn, (uint8_t *)p, n); + + return 0; +} + +static int +lws_smtp_client_abs_closed(lws_abs_user_t *abs_priv) +{ + lws_smtp_client_t *c = (lws_smtp_client_t *)abs_priv; + + c->abs_conn = NULL; + + return 0; +} + +static int +lws_smtp_client_abs_heartbeat(lws_abs_user_t *abs_priv) +{ + lws_smtp_client_t *c = (lws_smtp_client_t *)abs_priv; + + lws_smtp_client_kick(c); + + return 0; +} + +lws_smtp_email_t * +lws_smtp_client_alloc_email_helper(const char *payload, size_t payload_len, + const char *sender, const char *recipient, + const char *extra, size_t extra_len, void *data, + int (*done)(struct lws_smtp_email *e, + void *buf, size_t len)) +{ + size_t ls = strlen(sender), lr = strlen(recipient); + lws_smtp_email_t *em; + char *p; + + em = malloc(sizeof(*em) + payload_len + ls + lr + extra_len + 4); + if (!em) { + lwsl_err("OOM\n"); + return NULL; + } + + p = (char *)&em[1]; + + memset(em, 0, sizeof(*em)); + + em->data = data; + em->done = done; + + em->email_from = p; + memcpy(p, sender, ls + 1); + p += ls + 1; + em->email_to = p; + memcpy(p, recipient, lr + 1); + p += lr + 1; + em->payload = p; + memcpy(p, payload, payload_len + 1); + p += payload_len + 1; + + if (extra) { + em->extra = p; + memcpy(p, extra, extra_len + 1); + } + + return em; +} + +int +lws_smtp_client_add_email(lws_smtp_client_t *c, lws_smtp_email_t *e) +{ + if (c->pending_owner.count > c->i.email_queue_max) { + lwsl_err("%s: email queue at limit of %d\n", __func__, + (int)c->i.email_queue_max); + + return 1; + } + + e->added = lws_now_secs(); + e->last_try = 0; + e->tries = 0; + + lws_dll2_clear(&e->list); + lws_dll2_add_tail(&e->list, &c->pending_owner); + + lws_smtp_client_kick(c); + + return 0; +} + +lws_smtp_client_t * +lws_smtp_client_create(const lws_smtp_client_info_t *ci) +{ + lws_smtp_client_t *c; + + c = lws_zalloc(sizeof(*c), "email client"); + if (!c) + return NULL; + + c->i = *ci; + c->abs = *ci->abs; + + /* fill in the additional abstract callbacks we fulfil */ + + c->abs.accept = lws_smtp_client_abs_accept; + c->abs.rx = lws_smtp_client_abs_rx; + c->abs.writeable = lws_smtp_client_abs_writeable; + c->abs.closed = lws_smtp_client_abs_closed; + c->abs.heartbeat = lws_smtp_client_abs_heartbeat; + + if (!c->i.email_queue_max) + c->i.email_queue_max = 8; + + if (!c->i.retry_interval) + c->i.retry_interval = 15 * 60; + + if (!c->i.delivery_timeout) + c->i.delivery_timeout = 12 * 60 * 60; + + c->abs_conn = c->abs.create(&c->abs, c); + if (!c->abs_conn) { + lws_free(c); + + return NULL; + } + + lws_smtp_client_state_transition(c, LGSSMTP_IDLE); + + return c; +} + +static int +cleanup(struct lws_dll2 *d, void *user) +{ + lws_smtp_email_t *e; + + e = lws_container_of(d, lws_smtp_email_t, list); + if (e->done && e->done(e, "destroying", 10)) + return 1; + + return 0; +} + +void +lws_smtp_client_destroy(lws_smtp_client_t **c) +{ + if (!*c) + return; + + lws_dll2_foreach_safe(&(*c)->pending_owner, NULL, cleanup); + + if ((*c)->abs_conn) { + (*c)->abs.close((*c)->abs_conn); + (*c)->abs.destroy(&(*c)->abs_conn); + } + + lws_free_set_NULL(*c); +} diff --git a/lib/abstract/transports/raw-skt.c b/lib/abstract/transports/raw-skt.c new file mode 100644 index 00000000..739b7a0d --- /dev/null +++ b/lib/abstract/transports/raw-skt.c @@ -0,0 +1,309 @@ +/* + * libwebsockets lib/abstruct/transports/raw-skt.c + * + * 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" + +typedef struct lws_atrs_priv { + struct lws_abstract *abs; + struct lws *wsi; + void *user; + + lws_dll2_t same_abs_transport_list; + + uint8_t established:1; + uint8_t connecting:1; +} lws_atrs_priv_t; + +struct vhd { + lws_dll2_owner_t owner; +}; + +static int +heartbeat_cb(struct lws_dll2 *d, void *user) +{ + lws_atrs_priv_t *priv = lws_container_of(d, lws_atrs_priv_t, + same_abs_transport_list); + if (priv->abs->heartbeat) + priv->abs->heartbeat(priv->user); + + return 0; +} + +static int +callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason, + void *user, void *in, size_t len) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)user; + 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; + if (priv->abs->accept) + priv->abs->accept(priv->user); + 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; + if (priv->abs && priv->abs->closed) + priv->abs->closed(priv->user); + lws_free(priv); + lws_set_wsi_user(wsi, NULL); + break; + + case LWS_CALLBACK_RAW_RX: + lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len); + return !!priv->abs->rx(priv->user, in, len); + + case LWS_CALLBACK_RAW_WRITEABLE: + lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n"); + priv->abs->writeable(priv->user, + 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; +} + +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 +lws_atcrs_tx(lws_abs_user_t *abs_priv, uint8_t *buf, size_t len) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)abs_priv; + + 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) + priv->abs->close(priv->user); + + return 0; +} + +#if !defined(LWS_WITHOUT_CLIENT) +static int +lws_atcrs_client_conn(lws_abs_user_t *abs_priv, struct lws_vhost *vh, + const char *ip, uint16_t port, int tls_flags) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)abs_priv; + struct lws_client_connect_info i; + + if (priv->connecting) + return 0; + + if (priv->established) { + lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5); + + return 0; + } + + lwsl_debug("%s: priv %p connecting to %s:%u %p\n", __func__, priv, + ip, port, vh->context); + + memset(&i, 0, sizeof(i)); + + i.path = ""; + i.vhost = vh; + i.port = port; + i.address = ip; + i.method = "RAW"; + i.userdata = priv; + i.host = i.address; + i.pwsi = &priv->wsi; + i.origin = i.address; + i.context = vh->context; + i.ssl_connection = tls_flags; + 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 +lws_atcrs_close(lws_abs_user_t *abs_priv) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)abs_priv; + 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; +} + +static int +lws_atcrs_ask_for_writeable(lws_abs_user_t *abs_priv) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)abs_priv; + + if (!priv->wsi || !priv->established) + return 1; + + lws_callback_on_writable(priv->wsi); + + return 0; +} + +static lws_abs_user_t * +lws_atcrs_create(struct lws_abstract *abs, void *user) +{ + lws_atrs_priv_t *p = lws_zalloc(sizeof(*p), __func__); + + if (!p) + return NULL; + + lwsl_debug("%s: created priv %p\n", __func__, p); + + p->abs = abs; + p->user = user; + + return (lws_abs_user_t *)p; +} + +static void +lws_atcrs_destroy(lws_abs_user_t **abs_priv) +{ + lws_free_set_NULL(*abs_priv); +} + +static int +lws_atcrs_set_timeout(lws_abs_user_t *d, int reason, int secs) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)d; + + lws_set_timeout(priv->wsi, reason, secs); + + return 0; +} + +static int +lws_atcrs_state(lws_abs_user_t *abs_priv) +{ + lws_atrs_priv_t *priv = (lws_atrs_priv_t *)abs_priv; + + if (!priv || !priv->wsi || (!priv->established && !priv->connecting)) + return 0; + + return 1; +} + +lws_abstract_t lws_abstract_transport_cli_raw_skt = { + "raw-skt", + lws_atcrs_create, + lws_atcrs_destroy, + + lws_atcrs_tx, +#if defined(LWS_WITHOUT_CLIENT) + NULL, +#else + lws_atcrs_client_conn, +#endif + lws_atcrs_close, + lws_atcrs_ask_for_writeable, + lws_atcrs_set_timeout, + lws_atcrs_state, + + /* + * remaining callbacks must be defined by abstract object and are + * called by this protocol handler + */ + + NULL, /* accept */ + NULL, /* rx */ + NULL, /* writeable */ + NULL /* closed */ +}; |