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