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