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