diff --git a/OAT.xml b/OAT.xml index 2887edf2739ed2df911794e5dbb29fb84fc82f7c..d84e0d6d845cc37b2a64360ef528d6385d9a36dc 100644 --- a/OAT.xml +++ b/OAT.xml @@ -47,8 +47,30 @@ + + + + + + + + + + + + + + + + + - + @@ -59,7 +81,23 @@ + + + + + + + + + + diff --git a/include/libwebsockets/lws-mqtt.h b/include/libwebsockets/lws-mqtt.h deleted file mode 100644 index 72f770185df6b912a89e0903efe2fb9cf2819568..0000000000000000000000000000000000000000 --- a/include/libwebsockets/lws-mqtt.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * libwebsockets - protocol - mqtt - * - * Copyright (C) 2010 - 2020 Andy Green - * - * 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 - * - * included from libwebsockets.h - */ - -#ifndef _LWS_MQTT_H -#define _LWS_MQTT_H 1 - -struct _lws_mqtt_related; -typedef struct _lws_mqtt_related lws_mqtt_related_t; -struct lws_mqtt_str_st; -typedef struct lws_mqtt_str_st lws_mqtt_str_t; - -#define MQTT_VER_3_1_1 4 - -#define LWS_MQTT_FINAL_PART 1 - -typedef enum { - QOS0, - QOS1, - QOS2, /* not supported */ - RESERVED_QOS_LEVEL, - FAILURE_QOS_LEVEL = 0x80 -} lws_mqtt_qos_levels_t; - -typedef union { - struct { - uint8_t retain:1; - uint8_t qos:2; - uint8_t dup:1; - uint8_t ctrl_pkt_type:4; - } flags; - uint8_t bits; -} lws_mqtt_fixed_hdr_t; - -/* - * MQTT connection parameters, passed into struct - * lws_client_connect_info to establish a connection using - * lws_client_connect_via_info(). -*/ -typedef struct lws_mqtt_client_connect_param_s { - const char *client_id; /* Client ID */ - uint16_t keep_alive; /* MQTT keep alive - interval in - seconds */ - uint8_t clean_start; /* MQTT clean - session */ - struct { - const char *topic; - const char *message; - lws_mqtt_qos_levels_t qos; - uint8_t retain; - } will_param; /* MQTT LWT - parameters */ - const char *username; - const char *password; -} lws_mqtt_client_connect_param_t; - -/* - * MQTT publish parameters -*/ -typedef struct lws_mqtt_publish_param_s { - char *topic; /* Topic Name */ - uint16_t topic_len; - const void *payload; /* Publish Payload */ - uint32_t payload_len; /* Size of the - complete payload */ - uint32_t payload_pos; /* where we are in payload */ - lws_mqtt_qos_levels_t qos; - - /*--v-Following will be used by LWS-v--*/ - uint16_t packet_id; /* Packet ID for QoS > - 0 */ - uint8_t dup:1; /* Retried PUBLISH, - for QoS > 0 */ -} lws_mqtt_publish_param_t; - -typedef struct topic_elem { - const char *name; /* Topic Name */ - lws_mqtt_qos_levels_t qos; /* Requested QoS */ - - /*--v-Following will be used by LWS-v--*/ - uint8_t acked; -} lws_mqtt_topic_elem_t; - -/* - * MQTT publish parameters -*/ -typedef struct lws_mqtt_subscribe_param_s { - uint32_t num_topics; /* Number of topics */ - lws_mqtt_topic_elem_t *topic; /* Array of topic elements */ - - /*--v-Following will be used by LWS-v--*/ - uint16_t packet_id; -} lws_mqtt_subscribe_param_t; - -typedef enum { - LMQCP_RESERVED, - LMQCP_CTOS_CONNECT, /* Connection request */ - LMQCP_STOC_CONNACK, /* Connection acknowledgment */ - LMQCP_PUBLISH, /* Publish Message */ - LMQCP_PUBACK, /* QoS 1: Publish acknowledgment */ - LMQCP_PUBREC, /* QoS 2.1: Publish received */ - LMQCP_PUBREL, /* QoS 2.2: Publish release */ - LMQCP_PUBCOMP, /* QoS 2.3: Publish complete */ - LMQCP_CTOS_SUBSCRIBE, /* Subscribe request */ - LMQCP_STOC_SUBACK, /* Subscribe acknowledgment */ - LMQCP_CTOS_UNSUBSCRIBE, /* Unsubscribe request */ - LMQCP_STOC_UNSUBACK, /* Unsubscribe acknowledgment */ - LMQCP_CTOS_PINGREQ, /* PING request */ - LMQCP_STOC_PINGRESP, /* PONG response */ - LMQCP_DISCONNECT, /* Disconnect notification */ - LMQCP_AUTH /* Authentication exchange */ -} lws_mqtt_control_packet_t; - -/* flags from byte 8 of C_TO_S CONNECT */ -typedef enum { - LMQCFT_USERNAME = (1 << 7), - LMQCFT_PASSWORD = (1 << 6), - LMQCFT_WILL_RETAIN = (1 << 5), - LMQCFT_WILL_QOS = (1 << 3), - LMQCFT_WILL_FLAG = (1 << 2), - LMQCFT_CLEAN_START = (1 << 1), - LMQCFT_RESERVED = (1 << 0), - - LMQCFT_WILL_QOS_MASK = (3 << 3), -} lws_mqtt_connect_flags_t; - -/* flags for S_TO_C CONNACK */ -typedef enum { - LMQCFT_SESSION_PRESENT = (1 << 0), -} lws_mqtt_connack_flags_t; - -typedef enum { - LMQCP_REASON_SUCCESS = 0x00, - LMQCP_REASON_NORMAL_DISCONNECTION = 0x00, - LMQCP_REASON_GRANTED_QOS0 = 0x00, - LMQCP_REASON_GRANTED_QOS1 = 0x01, - LMQCP_REASON_GRANTED_QOS2 = 0x02, - LMQCP_REASON_DISCONNECT_WILL = 0x04, - LMQCP_REASON_NO_MATCHING_SUBSCRIBER = 0x10, - LMQCP_REASON_NO_SUBSCRIPTION_EXISTED = 0x11, - LMQCP_REASON_CONTINUE_AUTHENTICATION = 0x18, - LMQCP_REASON_RE_AUTHENTICATE = 0x19, - - LMQCP_REASON_UNSPECIFIED_ERROR = 0x80, - LMQCP_REASON_MALFORMED_PACKET = 0x81, - LMQCP_REASON_PROTOCOL_ERROR = 0x82, - LMQCP_REASON_IMPLEMENTATION_SPECIFIC_ERROR = 0x83, - - /* Begin - Error codes for CONNACK */ - LMQCP_REASON_UNSUPPORTED_PROTOCOL = 0x84, - LMQCP_REASON_CLIENT_ID_INVALID = 0x85, - LMQCP_REASON_BAD_CREDENTIALS = 0x86, - LMQCP_REASON_NOT_AUTHORIZED = 0x87, - /* End - Error codes for CONNACK */ - - LMQCP_REASON_SERVER_UNAVAILABLE = 0x88, - LMQCP_REASON_SERVER_BUSY = 0x89, - LMQCP_REASON_BANNED = 0x8a, - LMQCP_REASON_SERVER_SHUTTING_DOWN = 0x8b, - LMQCP_REASON_BAD_AUTHENTICATION_METHOD = 0x8c, - LMQCP_REASON_KEEPALIVE_TIMEOUT = 0x8d, - LMQCP_REASON_SESSION_TAKEN_OVER = 0x8e, - LMQCP_REASON_TOPIC_FILTER_INVALID = 0x8f, - LMQCP_REASON_TOPIC_NAME_INVALID = 0x90, - LMQCP_REASON_PACKET_ID_IN_USE = 0x91, - LMQCP_REASON_PACKET_ID_NOT_FOUND = 0x92, - LMQCP_REASON_MAX_RX_EXCEEDED = 0x93, - LMQCP_REASON_TOPIC_ALIAS_INVALID = 0x94, - LMQCP_REASON_PACKET_TOO_LARGE = 0x95, - LMQCP_REASON_RATELIMIT = 0x96, - LMQCP_REASON_QUOTA_EXCEEDED = 0x97, - LMQCP_REASON_ADMINISTRATIVE_ACTION = 0x98, - LMQCP_REASON_PAYLOAD_FORMAT_INVALID = 0x99, - LMQCP_REASON_RETAIN_NOT_SUPPORTED = 0x9a, - LMQCP_REASON_QOS_NOT_SUPPORTED = 0x9b, - LMQCP_REASON_USE_ANOTHER_SERVER = 0x9c, - LMQCP_REASON_SERVER_MOVED = 0x9d, - LMQCP_REASON_SHARED_SUBSCRIPTIONS_NOT_SUPPORTED = 0x9e, - LMQCP_REASON_CONNECTION_RATE_EXCEEDED = 0x9f, - LMQCP_REASON_MAXIMUM_CONNECT_TIME = 0xa0, - LMQCP_REASON_SUBSCRIPTION_IDS_NOT_SUPPORTED = 0xa1, - LMQCP_REASON_WILDCARD_SUBSCRIPTIONS_NOT_SUPPORTED = 0xa2, -} lws_mqtt_reason_t; - -typedef enum { - LMQPROP_INVALID, - LMQPROP_PAYLOAD_FORMAT_INDICATOR = 0x01, - LMQPROP_MESSAGE_EXPIRY_INTERVAL = 0x02, - LMQPROP_CONTENT_TYPE = 0x03, - LMQPROP_RESPONSE_TOPIC = 0x08, - LMQPROP_CORRELATION_DATA = 0x09, - LMQPROP_SUBSCRIPTION_IDENTIFIER = 0x0b, - LMQPROP_SESSION_EXPIRY_INTERVAL = 0x11, - LMQPROP_ASSIGNED_CLIENT_IDENTIFIER = 0x12, - LMQPROP_SERVER_KEEP_ALIVE = 0x13, - LMQPROP_AUTHENTICATION_METHOD = 0x15, - LMQPROP_AUTHENTICATION_DATA = 0x16, - LMQPROP_REQUEST_PROBLEM_INFORMATION = 0x17, - LMQPROP_WILL_DELAY_INTERVAL = 0x18, - LMQPROP_REQUEST_RESPONSE_INFORMATION = 0x19, - LMQPROP_RESPONSE_INFORMATION = 0x1a, - LMQPROP_SERVER_REFERENCE = 0x1c, - LMQPROP_REASON_STRING = 0x1f, - LMQPROP_RECEIVE_MAXIMUM = 0x21, - LMQPROP_TOPIC_ALIAS_MAXIMUM = 0x22, - LMQPROP_TOPIC_ALIAS = 0x23, - LMQPROP_MAXIMUM_QOS = 0x24, - LMQPROP_RETAIN_AVAILABLE = 0x25, - LMQPROP_USER_PROPERTY = 0x26, - LMQPROP_MAXIMUM_PACKET_SIZE = 0x27, - LMQPROP_WILDCARD_SUBSCRIPTION_AVAIL = 0x28, - LMQPROP_SUBSCRIPTION_IDENTIFIER_AVAIL = 0x29, - LMQPROP_SHARED_SUBSCRIPTION_AVAIL = 0x2a -} lws_mqtt_property; - -int -lws_read_mqtt(struct lws *wsi, unsigned char *buf, lws_filepos_t len); - -/* returns 0 if bd1 and bd2 are "the same", that includes empty, else nonzero */ -LWS_VISIBLE LWS_EXTERN int -lws_mqtt_bindata_cmp(const lws_mqtt_str_t *bd1, const lws_mqtt_str_t *bd2); - -LWS_VISIBLE LWS_EXTERN void -lws_mqtt_str_init(lws_mqtt_str_t *s, uint8_t *buf, uint16_t lim, char nf); - -LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * -lws_mqtt_str_create(uint16_t lim); - -LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * -lws_mqtt_str_create_init(uint8_t *buf, uint16_t len, uint16_t lim); - -LWS_VISIBLE LWS_EXTERN lws_mqtt_str_t * -lws_mqtt_str_create_cstr_dup(const char *buf, uint16_t lim); - -LWS_VISIBLE LWS_EXTERN uint8_t * -lws_mqtt_str_next(lws_mqtt_str_t *s, uint16_t *budget); - -LWS_VISIBLE LWS_EXTERN int -lws_mqtt_str_advance(lws_mqtt_str_t *s, int n); - -LWS_VISIBLE LWS_EXTERN void -lws_mqtt_str_free(lws_mqtt_str_t **s); - - -/** - * lws_mqtt_client_send_publish() - lws_write a publish packet - * - * \param wsi: the mqtt child wsi - * \param pub: additional information on what we're publishing - * \param buf: payload to send - * \param len: length of data in buf - * \param final: flag indicating this is the last part - * - * Issues part of, or the whole of, a PUBLISH frame. The first part of the - * frame contains the header, and uses the .qos and .payload_len parts of \p pub - * since MQTT requires the frame to specify the PUBLISH message length at the - * start. The \p len paramter may be less than \p pub.payload_len, in which - * case subsequent calls with more payload are needed to complete the frame. - * - * Although the connection is stuck waiting for the remainder, in that it can't - * issue any other frames until the current one is completed, lws returns to the - * event loop normally and can continue the calls with additional payload even - * for huge frames as the data becomes available, consistent with timeout needs - * and latency to start any new frame (even, eg, related to ping / pong). - * - * If you're sending large frames, the OS will typically not allow the data to - * be sent all at once to kernel side. So you should ideally cut the payload - * up into 1 or 2- mtu sized chunks and send that. - * - * Final should be set when you're calling with the last part of the payload. - */ -LWS_VISIBLE LWS_EXTERN int -lws_mqtt_client_send_publish(struct lws *wsi, lws_mqtt_publish_param_t *pub, - const void *buf, uint32_t len, int final); - -/** - * lws_mqtt_client_send_subcribe() - lws_write a subscribe packet - * - * \param wsi: the mqtt child wsi - * \param sub: which topic(s) we want to subscribe to - * - * For topics other child streams have not already subscribed to, send a packet - * to the server asking to subscribe to them. If all topics listed are already - * subscribed to be the shared network connection, just trigger the - * LWS_CALLBACK_MQTT_SUBSCRIBED callback as if a SUBACK had come. - * - * \p sub doesn't need to exist after the return from this function. - */ -LWS_VISIBLE LWS_EXTERN int -lws_mqtt_client_send_subcribe(struct lws *wsi, lws_mqtt_subscribe_param_t *sub); - -/** - * lws_mqtt_client_send_unsubcribe() - lws_write a unsubscribe packet - * - * \param wsi: the mqtt child wsi - * \param sub: which topic(s) we want to unsubscribe from - * - * For topics other child streams are not subscribed to, send a packet - * to the server asking to unsubscribe from them. If all topics - * listed are already subscribed by other child streams on the shared - * network connection, just trigger the LWS_CALLBACK_MQTT_UNSUBSCRIBED - * callback as if a UNSUBACK had come. - * - * \p unsub doesn't need to exist after the return from this function. - */ -LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT -lws_mqtt_client_send_unsubcribe(struct lws *wsi, - const lws_mqtt_subscribe_param_t *unsub); - -#endif /* _LWS_MQTT_H */ diff --git a/lib/abstract/protocols/smtp/smtp-sequencer.c b/lib/abstract/protocols/smtp/smtp-sequencer.c deleted file mode 100644 index 4b745aab1e7c55719f785e436f23b1971d6dd9bd..0000000000000000000000000000000000000000 --- a/lib/abstract/protocols/smtp/smtp-sequencer.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Abstract SMTP support for libwebsockets - SMTP sequencer - * - * Copyright (C) 2016-2019 Andy Green - * - * 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 - * - * This sequencer sits above the abstract protocol, and manages queueing, - * retrying mail transmission, and retry limits. - * - * Having the sequencer means that, eg, we can manage retries after complete - * connection failure. - * - * Connections to the smtp server are serialized - */ - -#include "private-lib-core.h" -#include "private-lib-abstract-protocols-smtp.h" - -typedef enum { - LSMTPSS_DISCONNECTED, - LSMTPSS_CONNECTING, - LSMTPSS_CONNECTED, - LSMTPSS_BUSY, -} smtpss_connstate_t; - -typedef struct lws_smtp_sequencer { - struct lws_dll2_owner emails_owner; /* email queue */ - - lws_abs_t *abs, *instance; - lws_smtp_sequencer_args_t args; - struct lws_sequencer *seq; - - smtpss_connstate_t connstate; - - time_t email_connect_started; - - /* holds the HELO for the smtp protocol to consume */ - lws_token_map_t apt[3]; -} lws_smtp_sequencer_t; - -/* sequencer messages specific to this sequencer */ - -enum { - SEQ_MSG_CLIENT_FAILED = LWSSEQ_USER_BASE, - SEQ_MSG_CLIENT_DONE, -}; - -/* - * We're going to bind to the raw-skt transport, so tell that what we want it - * to connect to - */ - -static const lws_token_map_t smtp_rs_transport_tokens[] = { - { - .u = { .value = "127.0.0.1" }, - .name_index = LTMI_PEER_V_DNS_ADDRESS, - }, { - .u = { .lvalue = 25 }, - .name_index = LTMI_PEER_LV_PORT, - }, { - } -}; - -static void -lws_smtpc_kick_internal(lws_smtp_sequencer_t *s) -{ - lws_smtp_email_t *e; - lws_dll2_t *d; - char buf[64]; - int n; - lws_dll2_t *pd2; - - pd2 = lws_dll2_get_head(&s->emails_owner); - if (!pd2) - return; - - e = lws_container_of(pd2, lws_smtp_email_t, list); - if (!e) - return; - - /* Is there something to do? If so, we need a connection... */ - - if (s->connstate == LSMTPSS_DISCONNECTED) { - - s->apt[0].u.value = s->args.helo; - s->apt[0].name_index = LTMI_PSMTP_V_HELO; - s->apt[1].u.value = (void *)e; - s->apt[1].name_index = LTMI_PSMTP_V_LWS_SMTP_EMAIL_T; - - /* - * create and connect the smtp protocol + transport - */ - - s->abs = lws_abstract_alloc(s->args.vhost, NULL, "smtp.raw_skt", - s->apt, smtp_rs_transport_tokens, - s->seq, NULL); - if (!s->abs) - return; - - s->instance = lws_abs_bind_and_create_instance(s->abs); - if (!s->instance) { - lws_abstract_free(&s->abs); - lwsl_err("%s: failed to create SMTP client\n", __func__); - - goto bail1; - } - - s->connstate = LSMTPSS_CONNECTING; - lws_seq_timeout_us(s->seq, 10 * LWS_USEC_PER_SEC); - return; - } - - /* ask the transport if we have a connection to the server ongoing */ - - if (s->abs->at->state(s->abs->ati)) { - /* - * there's a connection, it could be still trying to connect - * or established - */ - s->abs->at->ask_for_writeable(s->abs->ati); - - return; - } - - /* there's no existing connection */ - - lws_smtpc_state_transition(c, LGSSMTP_CONNECTING); - - if (s->abs->at->client_conn(s->abs)) { - lwsl_err("%s: failed to connect\n", __func__); - - return; - } - - e->tries++; - e->last_try = lws_now_secs(); -} - - -/* - * The callback we get from the smtp protocol... we use this to drive - * decisions about destroy email, retry and fail. - * - * Sequencer will handle it via the event loop. - */ - -static int -email_result(void *e, void *d, int disp, void *b, size_t l) -{ - lws_smtp_sequencer_t *s = (lws_smtp_sequencer_t *)d; - - lws_sequencer_event(s->seq, LWSSEQ_USER_BASE + disp, e); - - return 0; -} - -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); - - lws_dll2_remove(d); - lws_free(e); - - return 0; -} - -static lws_seq_cb_return_t -smtp_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data) -{ - struct lws_smtp_sequencer_t *s = (struct lws_smtp_sequencer_t *)user; - - switch ((int)event) { - case LWSSEQ_CREATED: /* our sequencer just got started */ - lwsl_notice("%s: %s: created\n", __func__, - lws_sequencer_name(seq)); - s->connstate = LSMTPSS_DISCONNECTED; - s->state = 0; /* first thing we'll do is the first url */ - goto step; - - case LWSSEQ_DESTROYED: - lws_dll2_foreach_safe(&s->pending_owner, NULL, cleanup); - break; - - case LWSSEQ_TIMED_OUT: - lwsl_notice("%s: LWSSEQ_TIMED_OUT\n", __func__); - break; - - case LWSSEQ_USER_BASE + LWS_SMTP_DISPOSITION_SENT: - lws_smtpc_free_email(data); - break; - - case LWSSEQ_WSI_CONNECTED: - s->connstate = LSMTPSS_CONNECTED; - lws_smtpc_kick_internal(s); - break; - - case LWSSEQ_WSI_CONN_FAIL: - case LWSSEQ_WSI_CONN_CLOSE: - s->connstate = LSMTPSS_DISCONNECTED; - lws_smtpc_kick_internal(s); - break; - - case SEQ_MSG_SENT: - break; - - default: - break; - } - - return LWSSEQ_RET_CONTINUE; -} - -/* - * Creates an lws_sequencer to manage the test sequence - */ - -lws_smtp_sequencer_t * -lws_smtp_sequencer_create(const lws_smtp_sequencer_args_t *args) -{ - lws_smtp_sequencer_t *s; - struct lws_sequencer *seq; - - /* - * Create a sequencer in the event loop to manage the SMTP queue - */ - - seq = lws_sequencer_create(args->vhost->context, 0, - sizeof(lws_smtp_sequencer_t), (void **)&s, - smtp_sequencer_cb, "smtp-seq"); - if (!seq) { - lwsl_err("%s: unable to create sequencer\n", __func__); - return NULL; - } - - s->abs = *args->abs; - s->args = *args; - s->seq = seq; - - /* set defaults in our copy of the args */ - - if (!s->args.helo[0]) - strcpy(s->args.helo, "default-helo"); - if (!s->args.email_queue_max) - s->args.email_queue_max = 8; - if (!s->args.retry_interval) - s->args.retry_interval = 15 * 60; - if (!s->args.delivery_timeout) - s->args.delivery_timeout = 12 * 60 * 60; - - return s; -} - -void -lws_smtp_sequencer_destroy(lws_smtp_sequencer_t *s) -{ - /* sequencer destruction destroys all assets */ - lws_sequencer_destroy(&s->seq); -} - -int -lws_smtpc_add_email(lws_smtp_sequencer_t *s, const char *payload, - size_t payload_len, const char *sender, - const char *recipient, void *data, lws_smtp_cb_t done) -{ - lws_smtp_email_t *e; - - if (s->emails_owner.count > s->args.email_queue_max) { - lwsl_err("%s: email queue at limit of %d\n", __func__, - (int)s->args.email_queue_max); - - return 1; - } - - if (!done) - return 1; - - e = malloc(sizeof(*e) + payload_len + 1); - if (!e) - return 1; - - memset(e, 0, sizeof(*e)); - - e->data = data; - e->done = done; - - lws_strncpy(e->from, sender, sizeof(e->from)); - lws_strncpy(e->to, recipient, sizeof(e->to)); - - memcpy((char *)&e[1], payload, payload_len + 1); - - e->added = lws_now_secs(); - e->last_try = 0; - e->tries = 0; - - lws_dll2_clear(&e->list); - lws_dll2_add_tail(&e->list, &s->emails_owner); - - lws_smtpc_kick_internal(s); - - return 0; -}