1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci#include "private-lib-abstract.h" 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci/** enum lwsgs_smtp_states - where we are in SMTP protocol sequence */ 29d4afb5ceSopenharmony_citypedef enum lwsgs_smtp_states { 30d4afb5ceSopenharmony_ci LGSSMTP_IDLE, /**< awaiting new email */ 31d4afb5ceSopenharmony_ci LGSSMTP_CONNECTING, /**< opening tcp connection to MTA */ 32d4afb5ceSopenharmony_ci LGSSMTP_CONNECTED, /**< tcp connection to MTA is connected */ 33d4afb5ceSopenharmony_ci /* (server sends greeting) */ 34d4afb5ceSopenharmony_ci LGSSMTP_SENT_HELO, /**< sent the HELO */ 35d4afb5ceSopenharmony_ci 36d4afb5ceSopenharmony_ci LGSSMTP_SENT_FROM, /**< sent FROM */ 37d4afb5ceSopenharmony_ci LGSSMTP_SENT_TO, /**< sent TO */ 38d4afb5ceSopenharmony_ci LGSSMTP_SENT_DATA, /**< sent DATA request */ 39d4afb5ceSopenharmony_ci LGSSMTP_SENT_BODY, /**< sent the email body */ 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci /* 42d4afb5ceSopenharmony_ci * (server sends, eg, "250 Ok: queued as 12345") 43d4afb5ceSopenharmony_ci * at this point we can return to LGSSMTP_SENT_HELO and send a 44d4afb5ceSopenharmony_ci * new email, or continue below to QUIT, or just wait 45d4afb5ceSopenharmony_ci */ 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_ci LGSSMTP_SENT_QUIT, /**< sent the session quit */ 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci /* (server sends, eg, "221 Bye" and closes the connection) */ 50d4afb5ceSopenharmony_ci} lwsgs_smtp_states_t; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci/** abstract protocol instance data */ 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_citypedef struct lws_smtp_client_protocol { 55d4afb5ceSopenharmony_ci const struct lws_abs *abs; 56d4afb5ceSopenharmony_ci lwsgs_smtp_states_t estate; 57d4afb5ceSopenharmony_ci 58d4afb5ceSopenharmony_ci lws_smtp_email_t *e; /* the email we are trying to send */ 59d4afb5ceSopenharmony_ci const char *helo; 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci unsigned char send_pending:1; 62d4afb5ceSopenharmony_ci} lws_smtpcp_t; 63d4afb5ceSopenharmony_ci 64d4afb5ceSopenharmony_cistatic const short retcodes[] = { 65d4afb5ceSopenharmony_ci 0, /* idle */ 66d4afb5ceSopenharmony_ci 0, /* connecting */ 67d4afb5ceSopenharmony_ci 220, /* connected */ 68d4afb5ceSopenharmony_ci 250, /* helo */ 69d4afb5ceSopenharmony_ci 250, /* from */ 70d4afb5ceSopenharmony_ci 250, /* to */ 71d4afb5ceSopenharmony_ci 354, /* data */ 72d4afb5ceSopenharmony_ci 250, /* body */ 73d4afb5ceSopenharmony_ci 221, /* quit */ 74d4afb5ceSopenharmony_ci}; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_cistatic void 77d4afb5ceSopenharmony_cilws_smtpc_state_transition(lws_smtpcp_t *c, lwsgs_smtp_states_t s) 78d4afb5ceSopenharmony_ci{ 79d4afb5ceSopenharmony_ci lwsl_debug("%s: cli %p: state %d -> %d\n", __func__, c, c->estate, s); 80d4afb5ceSopenharmony_ci c->estate = s; 81d4afb5ceSopenharmony_ci} 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_cistatic lws_smtp_email_t * 84d4afb5ceSopenharmony_cilws_smtpc_get_email(lws_smtpcp_t *c) 85d4afb5ceSopenharmony_ci{ 86d4afb5ceSopenharmony_ci const lws_token_map_t *tm; 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci /* ... the email we want to send */ 89d4afb5ceSopenharmony_ci tm = lws_abs_get_token(c->abs->ap_tokens, LTMI_PSMTP_V_LWS_SMTP_EMAIL_T); 90d4afb5ceSopenharmony_ci if (!tm) { 91d4afb5ceSopenharmony_ci assert(0); 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci return NULL; 94d4afb5ceSopenharmony_ci } 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci return (lws_smtp_email_t *)tm->u.value; 97d4afb5ceSopenharmony_ci} 98d4afb5ceSopenharmony_ci 99d4afb5ceSopenharmony_ci/* 100d4afb5ceSopenharmony_ci * Called when something happened so that we know now the final disposition of 101d4afb5ceSopenharmony_ci * the email send attempt, for good or ill. 102d4afb5ceSopenharmony_ci * 103d4afb5ceSopenharmony_ci * Inform the owner via the done callback and set up the next queued one if any. 104d4afb5ceSopenharmony_ci * 105d4afb5ceSopenharmony_ci * Returns nonzero if we queued a new one 106d4afb5ceSopenharmony_ci */ 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_cistatic int 109d4afb5ceSopenharmony_cilws_smtpc_email_disposition(lws_smtpcp_t *c, int disp, const void *buf, 110d4afb5ceSopenharmony_ci size_t len) 111d4afb5ceSopenharmony_ci{ 112d4afb5ceSopenharmony_ci lws_smtpcp_t *ch; 113d4afb5ceSopenharmony_ci lws_abs_t *ach; 114d4afb5ceSopenharmony_ci lws_dll2_t *d; 115d4afb5ceSopenharmony_ci 116d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_HELO); 117d4afb5ceSopenharmony_ci 118d4afb5ceSopenharmony_ci /* lifetime of the email object is handled by done callback */ 119d4afb5ceSopenharmony_ci c->e->done(c->e, c->e->data, disp, buf, len); 120d4afb5ceSopenharmony_ci c->e = NULL; 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci /* this may not be the time to try to send anything else... */ 123d4afb5ceSopenharmony_ci 124d4afb5ceSopenharmony_ci if (disp == LWS_SMTP_DISPOSITION_FAILED_DESTROY) 125d4afb5ceSopenharmony_ci return 0; 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci /* ... otherwise... do we have another queued? */ 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci d = lws_dll2_get_tail(&c->abs->children_owner); 130d4afb5ceSopenharmony_ci if (!d) 131d4afb5ceSopenharmony_ci return 0; 132d4afb5ceSopenharmony_ci 133d4afb5ceSopenharmony_ci ach = lws_container_of(d, lws_abs_t, bound); 134d4afb5ceSopenharmony_ci ch = (lws_smtpcp_t *)ach->api; 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_ci c->e = lws_smtpc_get_email(ch); 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci /* since we took it on, remove it from the queue */ 139d4afb5ceSopenharmony_ci lws_dll2_remove(d); 140d4afb5ceSopenharmony_ci 141d4afb5ceSopenharmony_ci return 1; 142d4afb5ceSopenharmony_ci} 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci/* 145d4afb5ceSopenharmony_ci * we became connected 146d4afb5ceSopenharmony_ci */ 147d4afb5ceSopenharmony_ci 148d4afb5ceSopenharmony_cistatic int 149d4afb5ceSopenharmony_cilws_smtpc_abs_accept(lws_abs_protocol_inst_t *api) 150d4afb5ceSopenharmony_ci{ 151d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)api; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci /* we have become connected in the tcp sense */ 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_CONNECTED); 156d4afb5ceSopenharmony_ci 157d4afb5ceSopenharmony_ci /* 158d4afb5ceSopenharmony_ci * From the accept(), the next thing that should happen is the SMTP 159d4afb5ceSopenharmony_ci * server sends its greeting like "220 smtp2.example.com ESMTP Postfix", 160d4afb5ceSopenharmony_ci * we'll hear about it in the rx callback, or time out 161d4afb5ceSopenharmony_ci */ 162d4afb5ceSopenharmony_ci 163d4afb5ceSopenharmony_ci c->abs->at->set_timeout(c->abs->ati, 164d4afb5ceSopenharmony_ci PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE, 3); 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci return 0; 167d4afb5ceSopenharmony_ci} 168d4afb5ceSopenharmony_ci 169d4afb5ceSopenharmony_cistatic int 170d4afb5ceSopenharmony_cilws_smtpc_abs_rx(lws_abs_protocol_inst_t *api, const uint8_t *buf, size_t len) 171d4afb5ceSopenharmony_ci{ 172d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)api; 173d4afb5ceSopenharmony_ci char dotstar[96], at[5]; 174d4afb5ceSopenharmony_ci int n; 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci c->abs->at->set_timeout(c->abs->ati, NO_PENDING_TIMEOUT, 0); 177d4afb5ceSopenharmony_ci 178d4afb5ceSopenharmony_ci lws_strncpy(at, (const char *)buf, sizeof(at)); 179d4afb5ceSopenharmony_ci n = atoi(at); 180d4afb5ceSopenharmony_ci 181d4afb5ceSopenharmony_ci switch (c->estate) { 182d4afb5ceSopenharmony_ci case LGSSMTP_CONNECTED: 183d4afb5ceSopenharmony_ci if (n != 220) { 184d4afb5ceSopenharmony_ci /* 185d4afb5ceSopenharmony_ci * The server did not properly greet us... we can't 186d4afb5ceSopenharmony_ci * even get started, so fail the transport connection 187d4afb5ceSopenharmony_ci * (and anything queued on it) 188d4afb5ceSopenharmony_ci */ 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci lws_strnncpy(dotstar, (const char *)buf, len, sizeof(dotstar)); 191d4afb5ceSopenharmony_ci lwsl_err("%s: server: %s\n", __func__, dotstar); 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci return 1; 194d4afb5ceSopenharmony_ci } 195d4afb5ceSopenharmony_ci break; 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci case LGSSMTP_SENT_BODY: 198d4afb5ceSopenharmony_ci /* 199d4afb5ceSopenharmony_ci * We finished one way or another... let's prepare to send a 200d4afb5ceSopenharmony_ci * new one... or wait until server hangs up on us 201d4afb5ceSopenharmony_ci */ 202d4afb5ceSopenharmony_ci if (!lws_smtpc_email_disposition(c, 203d4afb5ceSopenharmony_ci n == 250 ? LWS_SMTP_DISPOSITION_SENT : 204d4afb5ceSopenharmony_ci LWS_SMTP_DISPOSITION_FAILED, 205d4afb5ceSopenharmony_ci "destroyed", 0)) 206d4afb5ceSopenharmony_ci return 0; /* become idle */ 207d4afb5ceSopenharmony_ci 208d4afb5ceSopenharmony_ci break; /* ask to send */ 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci case LGSSMTP_SENT_QUIT: 211d4afb5ceSopenharmony_ci lwsl_debug("%s: done\n", __func__); 212d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_IDLE); 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci return 1; 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci default: 217d4afb5ceSopenharmony_ci if (n != retcodes[c->estate]) { 218d4afb5ceSopenharmony_ci lws_strnncpy(dotstar, buf, len, sizeof(dotstar)); 219d4afb5ceSopenharmony_ci lwsl_notice("%s: bad response: %d (state %d) %s\n", 220d4afb5ceSopenharmony_ci __func__, n, c->estate, dotstar); 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci lws_smtpc_email_disposition(c, 223d4afb5ceSopenharmony_ci LWS_SMTP_DISPOSITION_FAILED, buf, len); 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci return 0; 226d4afb5ceSopenharmony_ci } 227d4afb5ceSopenharmony_ci break; 228d4afb5ceSopenharmony_ci } 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci c->send_pending = 1; 231d4afb5ceSopenharmony_ci c->abs->at->ask_for_writeable(c->abs->ati); 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci return 0; 234d4afb5ceSopenharmony_ci} 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_cistatic int 237d4afb5ceSopenharmony_cilws_smtpc_abs_writeable(lws_abs_protocol_inst_t *api, size_t budget) 238d4afb5ceSopenharmony_ci{ 239d4afb5ceSopenharmony_ci char b[256 + LWS_PRE], *p = b + LWS_PRE; 240d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)api; 241d4afb5ceSopenharmony_ci int n; 242d4afb5ceSopenharmony_ci 243d4afb5ceSopenharmony_ci if (!c->send_pending || !c->e) 244d4afb5ceSopenharmony_ci return 0; 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci c->send_pending = 0; 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci lwsl_debug("%s: writing response for state %d\n", __func__, c->estate); 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci switch (c->estate) { 251d4afb5ceSopenharmony_ci case LGSSMTP_CONNECTED: 252d4afb5ceSopenharmony_ci n = lws_snprintf(p, sizeof(b) - LWS_PRE, "HELO %s\n", c->helo); 253d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_HELO); 254d4afb5ceSopenharmony_ci break; 255d4afb5ceSopenharmony_ci 256d4afb5ceSopenharmony_ci case LGSSMTP_SENT_HELO: 257d4afb5ceSopenharmony_ci n = lws_snprintf(p, sizeof(b) - LWS_PRE, "MAIL FROM: <%s>\n", 258d4afb5ceSopenharmony_ci c->e->from); 259d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_FROM); 260d4afb5ceSopenharmony_ci break; 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_ci case LGSSMTP_SENT_FROM: 263d4afb5ceSopenharmony_ci n = lws_snprintf(p, sizeof(b) - LWS_PRE, 264d4afb5ceSopenharmony_ci "RCPT TO: <%s>\n", c->e->to); 265d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_TO); 266d4afb5ceSopenharmony_ci break; 267d4afb5ceSopenharmony_ci 268d4afb5ceSopenharmony_ci case LGSSMTP_SENT_TO: 269d4afb5ceSopenharmony_ci n = lws_snprintf(p, sizeof(b) - LWS_PRE, "DATA\n"); 270d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_DATA); 271d4afb5ceSopenharmony_ci break; 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci case LGSSMTP_SENT_DATA: 274d4afb5ceSopenharmony_ci p = (char *)&c->e[1]; 275d4afb5ceSopenharmony_ci n = strlen(p); 276d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_BODY); 277d4afb5ceSopenharmony_ci break; 278d4afb5ceSopenharmony_ci 279d4afb5ceSopenharmony_ci case LGSSMTP_SENT_BODY: 280d4afb5ceSopenharmony_ci n = lws_snprintf(p, sizeof(b) - LWS_PRE, "quit\n"); 281d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_SENT_QUIT); 282d4afb5ceSopenharmony_ci break; 283d4afb5ceSopenharmony_ci 284d4afb5ceSopenharmony_ci case LGSSMTP_SENT_QUIT: 285d4afb5ceSopenharmony_ci return 0; 286d4afb5ceSopenharmony_ci 287d4afb5ceSopenharmony_ci default: 288d4afb5ceSopenharmony_ci return 0; 289d4afb5ceSopenharmony_ci } 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci //puts(p); 292d4afb5ceSopenharmony_ci c->abs->at->tx(c->abs->ati, (uint8_t *)p, n); 293d4afb5ceSopenharmony_ci 294d4afb5ceSopenharmony_ci return 0; 295d4afb5ceSopenharmony_ci} 296d4afb5ceSopenharmony_ci 297d4afb5ceSopenharmony_cistatic int 298d4afb5ceSopenharmony_cilws_smtpc_abs_closed(lws_abs_protocol_inst_t *api) 299d4afb5ceSopenharmony_ci{ 300d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)api; 301d4afb5ceSopenharmony_ci 302d4afb5ceSopenharmony_ci if (c) 303d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, LGSSMTP_IDLE); 304d4afb5ceSopenharmony_ci 305d4afb5ceSopenharmony_ci return 0; 306d4afb5ceSopenharmony_ci} 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci/* 309d4afb5ceSopenharmony_ci * Creating for initial transport and for piggybacking on another transport 310d4afb5ceSopenharmony_ci * both get created here the same. But piggybackers have ai->bound attached. 311d4afb5ceSopenharmony_ci */ 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_cistatic int 314d4afb5ceSopenharmony_cilws_smtpc_create(const lws_abs_t *ai) 315d4afb5ceSopenharmony_ci{ 316d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)ai->api; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci memset(c, 0, sizeof(*c)); 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci c->abs = ai; 321d4afb5ceSopenharmony_ci c->e = lws_smtpc_get_email(c); 322d4afb5ceSopenharmony_ci 323d4afb5ceSopenharmony_ci lws_smtpc_state_transition(c, lws_dll2_is_detached(&ai->bound) ? 324d4afb5ceSopenharmony_ci LGSSMTP_CONNECTING : LGSSMTP_IDLE); 325d4afb5ceSopenharmony_ci 326d4afb5ceSopenharmony_ci /* If we are initiating the transport, we will get an accept() next... 327d4afb5ceSopenharmony_ci * 328d4afb5ceSopenharmony_ci * If we are piggybacking, the parent will get a .child_bind() after 329d4afb5ceSopenharmony_ci * this to give it a chance to act on us joining (eg, it was completely 330d4afb5ceSopenharmony_ci * idle and we joined). 331d4afb5ceSopenharmony_ci */ 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci return 0; 334d4afb5ceSopenharmony_ci} 335d4afb5ceSopenharmony_ci 336d4afb5ceSopenharmony_cistatic void 337d4afb5ceSopenharmony_cilws_smtpc_destroy(lws_abs_protocol_inst_t **_c) 338d4afb5ceSopenharmony_ci{ 339d4afb5ceSopenharmony_ci lws_smtpcp_t *c = (lws_smtpcp_t *)*_c; 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci if (!c) 342d4afb5ceSopenharmony_ci return; 343d4afb5ceSopenharmony_ci 344d4afb5ceSopenharmony_ci /* so if we are still holding on to c->e, we have failed to send it */ 345d4afb5ceSopenharmony_ci if (c->e) 346d4afb5ceSopenharmony_ci lws_smtpc_email_disposition(c, 347d4afb5ceSopenharmony_ci LWS_SMTP_DISPOSITION_FAILED_DESTROY, "destroyed", 0); 348d4afb5ceSopenharmony_ci 349d4afb5ceSopenharmony_ci *_c = NULL; 350d4afb5ceSopenharmony_ci} 351d4afb5ceSopenharmony_ci 352d4afb5ceSopenharmony_cistatic int 353d4afb5ceSopenharmony_cilws_smtpc_compare(lws_abs_t *abs1, lws_abs_t *abs2) 354d4afb5ceSopenharmony_ci{ 355d4afb5ceSopenharmony_ci return 0; 356d4afb5ceSopenharmony_ci} 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_cistatic int 359d4afb5ceSopenharmony_cilws_smtpc_child_bind(lws_abs_t *abs) 360d4afb5ceSopenharmony_ci{ 361d4afb5ceSopenharmony_ci return 0; 362d4afb5ceSopenharmony_ci} 363d4afb5ceSopenharmony_ci 364d4afb5ceSopenharmony_ci/* events the transport invokes (handled by abstract protocol) */ 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ciconst lws_abs_protocol_t lws_abs_protocol_smtp = { 367d4afb5ceSopenharmony_ci .name = "smtp", 368d4afb5ceSopenharmony_ci .alloc = sizeof(lws_smtpcp_t), 369d4afb5ceSopenharmony_ci .flags = LWSABSPR_FLAG_PIPELINE, 370d4afb5ceSopenharmony_ci 371d4afb5ceSopenharmony_ci .create = lws_smtpc_create, 372d4afb5ceSopenharmony_ci .destroy = lws_smtpc_destroy, 373d4afb5ceSopenharmony_ci .compare = lws_smtpc_compare, 374d4afb5ceSopenharmony_ci 375d4afb5ceSopenharmony_ci .accept = lws_smtpc_abs_accept, 376d4afb5ceSopenharmony_ci .rx = lws_smtpc_abs_rx, 377d4afb5ceSopenharmony_ci .writeable = lws_smtpc_abs_writeable, 378d4afb5ceSopenharmony_ci .closed = lws_smtpc_abs_closed, 379d4afb5ceSopenharmony_ci .heartbeat = NULL, 380d4afb5ceSopenharmony_ci 381d4afb5ceSopenharmony_ci .child_bind = lws_smtpc_child_bind, 382d4afb5ceSopenharmony_ci}; 383