xref: /dflybsd-src/usr.sbin/installer/libdfui/conn_tcp.c (revision d056b4791691895675342b2abe77a65087658bb1)
1*21c1c48aSSascha Wildner /*
2*21c1c48aSSascha Wildner  *
3*21c1c48aSSascha Wildner  * Copyright (c) 2004 Scott Ullrich <GeekGod@GeekGod.com>
4*21c1c48aSSascha Wildner  * Portions Copyright (c) 2004 Chris Pressey <cpressey@catseye.mine.nu>
5*21c1c48aSSascha Wildner  *
6*21c1c48aSSascha Wildner  * Copyright (c) 2004 The DragonFly Project.
7*21c1c48aSSascha Wildner  * All rights reserved.
8*21c1c48aSSascha Wildner  *
9*21c1c48aSSascha Wildner  * This code is derived from software contributed to The DragonFly Project
10*21c1c48aSSascha Wildner  * by Scott Ullrich and Chris Pressey (see above for e-mail addresses).
11*21c1c48aSSascha Wildner  *
12*21c1c48aSSascha Wildner  * Redistribution and use in source and binary forms, with or without
13*21c1c48aSSascha Wildner  * modification, are permitted provided that the following conditions
14*21c1c48aSSascha Wildner  * are met:
15*21c1c48aSSascha Wildner  *
16*21c1c48aSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
17*21c1c48aSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
18*21c1c48aSSascha Wildner  *
19*21c1c48aSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
20*21c1c48aSSascha Wildner  *    notice, this list of conditions and the following disclaimer in
21*21c1c48aSSascha Wildner  *    the documentation and/or other materials provided with the
22*21c1c48aSSascha Wildner  *    distribution.
23*21c1c48aSSascha Wildner  *
24*21c1c48aSSascha Wildner  * 3. Neither the name of The DragonFly Project nor the names of its
25*21c1c48aSSascha Wildner  *    contributors may be used to endorse or promote products derived
26*21c1c48aSSascha Wildner  *    from this software without specific, prior written permission.
27*21c1c48aSSascha Wildner  *
28*21c1c48aSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29*21c1c48aSSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30*21c1c48aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31*21c1c48aSSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
32*21c1c48aSSascha Wildner  * COPYRIGHT HOLDERS, CONTRIBUTORS OR VOICES IN THE AUTHOR'S HEAD
33*21c1c48aSSascha Wildner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY
34*21c1c48aSSascha Wildner  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
35*21c1c48aSSascha Wildner  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
36*21c1c48aSSascha Wildner  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
37*21c1c48aSSascha Wildner  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
38*21c1c48aSSascha Wildner  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39*21c1c48aSSascha Wildner  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40*21c1c48aSSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
41*21c1c48aSSascha Wildner  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
42*21c1c48aSSascha Wildner  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43*21c1c48aSSascha Wildner  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
44*21c1c48aSSascha Wildner  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45*21c1c48aSSascha Wildner  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46*21c1c48aSSascha Wildner  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47*21c1c48aSSascha Wildner  * SUCH DAMAGE.
48*21c1c48aSSascha Wildner  */
49*21c1c48aSSascha Wildner 
50*21c1c48aSSascha Wildner /*
51*21c1c48aSSascha Wildner  * conn_tcp.c
52*21c1c48aSSascha Wildner  * $Id: conn_tcp.c,v 1.16 2005/02/06 19:53:19 cpressey Exp $
53*21c1c48aSSascha Wildner  */
54*21c1c48aSSascha Wildner 
55*21c1c48aSSascha Wildner #include "system.h"
56*21c1c48aSSascha Wildner #ifdef HAS_TCP
57*21c1c48aSSascha Wildner 
58*21c1c48aSSascha Wildner #include <sys/types.h>
59*21c1c48aSSascha Wildner #include <sys/stat.h>
60*21c1c48aSSascha Wildner #include <sys/time.h>
61*21c1c48aSSascha Wildner #include <sys/errno.h>
62*21c1c48aSSascha Wildner #include <sys/socket.h>
63*21c1c48aSSascha Wildner #include <netinet/in.h>
64*21c1c48aSSascha Wildner #include <arpa/inet.h>
65*21c1c48aSSascha Wildner 
66*21c1c48aSSascha Wildner #include <err.h>
67*21c1c48aSSascha Wildner #include <stdarg.h>
68*21c1c48aSSascha Wildner #include <stdio.h>
69*21c1c48aSSascha Wildner #include <stdlib.h>
70*21c1c48aSSascha Wildner #include <string.h>
71*21c1c48aSSascha Wildner #include <unistd.h>
72*21c1c48aSSascha Wildner 
73*21c1c48aSSascha Wildner #include <libaura/buffer.h>
74*21c1c48aSSascha Wildner 
75*21c1c48aSSascha Wildner #define	NEEDS_DFUI_STRUCTURE_DEFINITIONS
76*21c1c48aSSascha Wildner #include "dfui.h"
77*21c1c48aSSascha Wildner #undef	NEEDS_DFUI_STRUCTURE_DEFINITIONS
78*21c1c48aSSascha Wildner #include "encoding.h"
79*21c1c48aSSascha Wildner #include "conn_tcp.h"
80*21c1c48aSSascha Wildner #include "dump.h"
81*21c1c48aSSascha Wildner 
82*21c1c48aSSascha Wildner /***** BACKEND ******/
83*21c1c48aSSascha Wildner 
84*21c1c48aSSascha Wildner /** High Level **/
85*21c1c48aSSascha Wildner 
86*21c1c48aSSascha Wildner /*
87*21c1c48aSSascha Wildner  * Connect to the frontend.
88*21c1c48aSSascha Wildner  */
89*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_be_start(struct dfui_connection * c)90*21c1c48aSSascha Wildner dfui_tcp_be_start(struct dfui_connection *c)
91*21c1c48aSSascha Wildner {
92*21c1c48aSSascha Wildner 	struct sockaddr_in servaddr;
93*21c1c48aSSascha Wildner 	int server_port;
94*21c1c48aSSascha Wildner 	int tru = 1;
95*21c1c48aSSascha Wildner 
96*21c1c48aSSascha Wildner 	server_port = atoi(c->rendezvous);
97*21c1c48aSSascha Wildner 
98*21c1c48aSSascha Wildner 	/*
99*21c1c48aSSascha Wildner 	 * Create the tcp socket
100*21c1c48aSSascha Wildner 	 */
101*21c1c48aSSascha Wildner 	errno = 0;
102*21c1c48aSSascha Wildner 	if ((T_TCP(c)->listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
103*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
104*21c1c48aSSascha Wildner 	dfui_debug("LISTEN_SOCKET<<%d>>\n", T_TCP(c)->listen_sd);
105*21c1c48aSSascha Wildner 
106*21c1c48aSSascha Wildner 	if (setsockopt(T_TCP(c)->listen_sd, SOL_SOCKET, SO_REUSEADDR,
107*21c1c48aSSascha Wildner 	    &tru, sizeof(tru)) == -1) {
108*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
109*21c1c48aSSascha Wildner 	}
110*21c1c48aSSascha Wildner 
111*21c1c48aSSascha Wildner 	bzero(&servaddr, sizeof(servaddr));
112*21c1c48aSSascha Wildner 	servaddr.sin_family = AF_INET;
113*21c1c48aSSascha Wildner 	servaddr.sin_port = htons(server_port);
114*21c1c48aSSascha Wildner 	switch(inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr)) {
115*21c1c48aSSascha Wildner 	case 0:
116*21c1c48aSSascha Wildner 		warnx("inet_pton(): address not parseable");
117*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
118*21c1c48aSSascha Wildner 	case 1:
119*21c1c48aSSascha Wildner 		break;
120*21c1c48aSSascha Wildner 	default:
121*21c1c48aSSascha Wildner 		warn("inet_pton()");
122*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
123*21c1c48aSSascha Wildner 	}
124*21c1c48aSSascha Wildner 
125*21c1c48aSSascha Wildner 	if (bind(T_TCP(c)->listen_sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
126*21c1c48aSSascha Wildner 		warn("bind()");
127*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
128*21c1c48aSSascha Wildner 	}
129*21c1c48aSSascha Wildner 	dfui_debug("BOUND_ON<<%d>>\n", T_TCP(c)->listen_sd);
130*21c1c48aSSascha Wildner 	if (listen(T_TCP(c)->listen_sd, 0) == -1)
131*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
132*21c1c48aSSascha Wildner 	dfui_debug("LISTENING_ON<<%d>>\n", T_TCP(c)->listen_sd);
133*21c1c48aSSascha Wildner 	/* at this point we should be listening on the rendezvous port */
134*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
135*21c1c48aSSascha Wildner }
136*21c1c48aSSascha Wildner 
137*21c1c48aSSascha Wildner /*
138*21c1c48aSSascha Wildner  * Tell the frontend that we're done and disconnect from it.
139*21c1c48aSSascha Wildner  */
140*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_be_stop(struct dfui_connection * c)141*21c1c48aSSascha Wildner dfui_tcp_be_stop(struct dfui_connection *c)
142*21c1c48aSSascha Wildner {
143*21c1c48aSSascha Wildner 	if (dfui_tcp_be_ll_exchange(c, DFUI_BE_MSG_STOP, "")) {
144*21c1c48aSSascha Wildner 		close(T_TCP(c)->listen_sd);
145*21c1c48aSSascha Wildner 		close(T_TCP(c)->connected_sd);
146*21c1c48aSSascha Wildner 		fclose(T_TCP(c)->stream);
147*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
148*21c1c48aSSascha Wildner 	} else
149*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
150*21c1c48aSSascha Wildner }
151*21c1c48aSSascha Wildner 
152*21c1c48aSSascha Wildner /** Low Level **/
153*21c1c48aSSascha Wildner 
154*21c1c48aSSascha Wildner /*
155*21c1c48aSSascha Wildner  * Exchange a message with the frontend.  This involves two receive()/reply()
156*21c1c48aSSascha Wildner  * cycles: one to provide our message, one to get a reply from the frontend.
157*21c1c48aSSascha Wildner  *
158*21c1c48aSSascha Wildner  * Note that this does not immediately send the message to the frontend -
159*21c1c48aSSascha Wildner  * it can't, because we're a service and it's a client.  What it does is
160*21c1c48aSSascha Wildner  * keep the message handy and wait for a frontend request to come in.  It
161*21c1c48aSSascha Wildner  * then replies to that request with our message.
162*21c1c48aSSascha Wildner  *
163*21c1c48aSSascha Wildner  * The protocol looks something like the following, using the PRESENT and
164*21c1c48aSSascha Wildner  * SUBMIT exchange as an example:
165*21c1c48aSSascha Wildner  *
166*21c1c48aSSascha Wildner  * frontend (client) | backend (service)
167*21c1c48aSSascha Wildner  * ------------------+------------------
168*21c1c48aSSascha Wildner  *
169*21c1c48aSSascha Wildner  *                                     [stage 1]
170*21c1c48aSSascha Wildner  * READY            -->                ll_receive()
171*21c1c48aSSascha Wildner  *                 <--  PRESENT(form)  ll_reply()
172*21c1c48aSSascha Wildner  *
173*21c1c48aSSascha Wildner  *                                     [stage 2]
174*21c1c48aSSascha Wildner  * SUBMIT(form)     -->                ll_receive()
175*21c1c48aSSascha Wildner  *                 <--  READY          ll_reply()
176*21c1c48aSSascha Wildner  *
177*21c1c48aSSascha Wildner  * Each of those exchanges is a pair of calls, on our end, to
178*21c1c48aSSascha Wildner  * dfui_tcp_be_ll_receive() and dfui_npipe_be_ll_reply().
179*21c1c48aSSascha Wildner  *
180*21c1c48aSSascha Wildner  * The set of messages that the client can pass us is determined by
181*21c1c48aSSascha Wildner  * the conversation state:
182*21c1c48aSSascha Wildner  *
183*21c1c48aSSascha Wildner  *   o  In stage 1, only READY and ABORT are meaningful.
184*21c1c48aSSascha Wildner  *   o  After a PRESENT, the messages SUBMIT and ABORT are meaningul
185*21c1c48aSSascha Wildner  *      in stage 2.
186*21c1c48aSSascha Wildner  *   o  During a PROG_*, the messages CONTINUE, CANCEL, and ABORT
187*21c1c48aSSascha Wildner  *      are meaningful in stage 2.
188*21c1c48aSSascha Wildner  *
189*21c1c48aSSascha Wildner  * If the frontend sends us with READY in stage 2, we assume it has
190*21c1c48aSSascha Wildner  * fallen out of sync, so we send the same initial reply again, going
191*21c1c48aSSascha Wildner  * back to stage 1 as it were.
192*21c1c48aSSascha Wildner  *
193*21c1c48aSSascha Wildner  * After this call, the message is available in c->ebuf.
194*21c1c48aSSascha Wildner  */
195*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_be_ll_exchange(struct dfui_connection * c,char msgtype,const char * msg)196*21c1c48aSSascha Wildner dfui_tcp_be_ll_exchange(struct dfui_connection *c, char msgtype, const char *msg)
197*21c1c48aSSascha Wildner {
198*21c1c48aSSascha Wildner 	char *fmsg;
199*21c1c48aSSascha Wildner 
200*21c1c48aSSascha Wildner 	/*
201*21c1c48aSSascha Wildner 	 * Construct our message to send.
202*21c1c48aSSascha Wildner 	 */
203*21c1c48aSSascha Wildner 
204*21c1c48aSSascha Wildner 	fmsg = malloc(strlen(msg) + 2);
205*21c1c48aSSascha Wildner 	fmsg[0] = msgtype;
206*21c1c48aSSascha Wildner 	strcpy(fmsg + 1, msg);
207*21c1c48aSSascha Wildner 
208*21c1c48aSSascha Wildner 	/*
209*21c1c48aSSascha Wildner 	 * Get the frontend's message.
210*21c1c48aSSascha Wildner 	 */
211*21c1c48aSSascha Wildner 
212*21c1c48aSSascha Wildner 	dfui_tcp_be_ll_receive(c);
213*21c1c48aSSascha Wildner 
214*21c1c48aSSascha Wildner 	/*
215*21c1c48aSSascha Wildner 	 * Frontend message should have been either READY or ABORT.
216*21c1c48aSSascha Wildner 	 * If ABORT, we get out of here pronto.
217*21c1c48aSSascha Wildner 	 */
218*21c1c48aSSascha Wildner 
219*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
220*21c1c48aSSascha Wildner 		free(fmsg);
221*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
222*21c1c48aSSascha Wildner 	}
223*21c1c48aSSascha Wildner 
224*21c1c48aSSascha Wildner 	/* XXX if (!READY) ??? */
225*21c1c48aSSascha Wildner 
226*21c1c48aSSascha Wildner 	do {
227*21c1c48aSSascha Wildner 		dfui_tcp_be_ll_reply(c, fmsg);
228*21c1c48aSSascha Wildner 
229*21c1c48aSSascha Wildner 		/*
230*21c1c48aSSascha Wildner 		 * Here, the frontend has picked up our request and is
231*21c1c48aSSascha Wildner 		 * processing it.  We have to wait for the response.
232*21c1c48aSSascha Wildner 		 */
233*21c1c48aSSascha Wildner 
234*21c1c48aSSascha Wildner 		dfui_tcp_be_ll_receive(c);
235*21c1c48aSSascha Wildner 
236*21c1c48aSSascha Wildner 		/*
237*21c1c48aSSascha Wildner 		 * Did we get READY from this?
238*21c1c48aSSascha Wildner 		 * If so, loop!
239*21c1c48aSSascha Wildner 		 */
240*21c1c48aSSascha Wildner 
241*21c1c48aSSascha Wildner 	} while (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_READY);
242*21c1c48aSSascha Wildner 
243*21c1c48aSSascha Wildner 	fmsg[0] = DFUI_BE_MSG_READY;
244*21c1c48aSSascha Wildner 	fmsg[1] = '\0';
245*21c1c48aSSascha Wildner 	dfui_tcp_be_ll_reply(c, fmsg);
246*21c1c48aSSascha Wildner 
247*21c1c48aSSascha Wildner 	free(fmsg);
248*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
249*21c1c48aSSascha Wildner }
250*21c1c48aSSascha Wildner 
251*21c1c48aSSascha Wildner /*
252*21c1c48aSSascha Wildner  * Receive a message from the frontend.
253*21c1c48aSSascha Wildner  * This call is synchronous.
254*21c1c48aSSascha Wildner  * After this call, the NUL-terminated message is available in
255*21c1c48aSSascha Wildner  * c->ebuf.
256*21c1c48aSSascha Wildner  */
257*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_be_ll_receive(struct dfui_connection * c)258*21c1c48aSSascha Wildner dfui_tcp_be_ll_receive(struct dfui_connection *c)
259*21c1c48aSSascha Wildner {
260*21c1c48aSSascha Wildner 	int length;
261*21c1c48aSSascha Wildner 	char *buf;
262*21c1c48aSSascha Wildner 
263*21c1c48aSSascha Wildner 	top:
264*21c1c48aSSascha Wildner 
265*21c1c48aSSascha Wildner 	if (!T_TCP(c)->is_connected) {
266*21c1c48aSSascha Wildner 	dfui_debug("NOT_CONNECTED,ACCEPTING_ON<<%d>>\n", T_TCP(c)->listen_sd);
267*21c1c48aSSascha Wildner 		T_TCP(c)->connected_sd = accept(T_TCP(c)->listen_sd, NULL, NULL);
268*21c1c48aSSascha Wildner 		dfui_debug("ACCEPTED<<%d>>\n", T_TCP(c)->connected_sd);
269*21c1c48aSSascha Wildner 		T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+");
270*21c1c48aSSascha Wildner 		T_TCP(c)->is_connected = 1;
271*21c1c48aSSascha Wildner 	} else {
272*21c1c48aSSascha Wildner 		dfui_debug("ALREADY_CONNECTED<<>>\n");
273*21c1c48aSSascha Wildner 	}
274*21c1c48aSSascha Wildner 
275*21c1c48aSSascha Wildner 	dfui_debug("WAITING<<>>\n");
276*21c1c48aSSascha Wildner 
277*21c1c48aSSascha Wildner 	if (read_data(T_TCP(c)->stream, (char *)&length, sizeof(length)) == -1) {
278*21c1c48aSSascha Wildner 		dfui_debug("LOST_THEM<<>>\n");
279*21c1c48aSSascha Wildner 		fclose(T_TCP(c)->stream);
280*21c1c48aSSascha Wildner 		T_TCP(c)->is_connected = 0;
281*21c1c48aSSascha Wildner 		goto top;
282*21c1c48aSSascha Wildner 	}
283*21c1c48aSSascha Wildner 
284*21c1c48aSSascha Wildner 	buf = malloc(length + 1);
285*21c1c48aSSascha Wildner 	if (read_data(T_TCP(c)->stream, buf, length) == -1) {
286*21c1c48aSSascha Wildner 		dfui_debug("LOST_THEM<<>>\n");
287*21c1c48aSSascha Wildner 		fclose(T_TCP(c)->stream);
288*21c1c48aSSascha Wildner 		T_TCP(c)->is_connected = 0;
289*21c1c48aSSascha Wildner 		goto top;
290*21c1c48aSSascha Wildner 	}
291*21c1c48aSSascha Wildner 
292*21c1c48aSSascha Wildner 	aura_buffer_set(c->ebuf, buf, length);
293*21c1c48aSSascha Wildner 	free(buf);
294*21c1c48aSSascha Wildner 
295*21c1c48aSSascha Wildner 	dfui_debug("RECEIVED<<%s>>\n", aura_buffer_buf(c->ebuf));
296*21c1c48aSSascha Wildner 
297*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
298*21c1c48aSSascha Wildner }
299*21c1c48aSSascha Wildner 
300*21c1c48aSSascha Wildner /*
301*21c1c48aSSascha Wildner  * Send a NUL-terminated reply to the frontend.
302*21c1c48aSSascha Wildner  */
303*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_be_ll_reply(struct dfui_connection * c,const char * fmsg)304*21c1c48aSSascha Wildner dfui_tcp_be_ll_reply(struct dfui_connection *c, const char *fmsg)
305*21c1c48aSSascha Wildner {
306*21c1c48aSSascha Wildner 	int length;
307*21c1c48aSSascha Wildner 
308*21c1c48aSSascha Wildner 	dfui_debug("SEND<<%s>>\n", fmsg);
309*21c1c48aSSascha Wildner 	length = strlen(fmsg);
310*21c1c48aSSascha Wildner 	write_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
311*21c1c48aSSascha Wildner 	write_data(T_TCP(c)->stream, fmsg, length);
312*21c1c48aSSascha Wildner 
313*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
314*21c1c48aSSascha Wildner }
315*21c1c48aSSascha Wildner 
316*21c1c48aSSascha Wildner /******** FRONTEND ********/
317*21c1c48aSSascha Wildner 
318*21c1c48aSSascha Wildner /** High Level **/
319*21c1c48aSSascha Wildner 
320*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_fe_connect(struct dfui_connection * c)321*21c1c48aSSascha Wildner dfui_tcp_fe_connect(struct dfui_connection *c)
322*21c1c48aSSascha Wildner {
323*21c1c48aSSascha Wildner         struct sockaddr_in servaddr;
324*21c1c48aSSascha Wildner         int server_port;
325*21c1c48aSSascha Wildner 	int connected = 0;
326*21c1c48aSSascha Wildner 
327*21c1c48aSSascha Wildner         server_port = atoi(c->rendezvous);
328*21c1c48aSSascha Wildner 
329*21c1c48aSSascha Wildner         /*
330*21c1c48aSSascha Wildner          * Create the tcp socket
331*21c1c48aSSascha Wildner          */
332*21c1c48aSSascha Wildner 	while (!connected) {
333*21c1c48aSSascha Wildner 		errno = 0;
334*21c1c48aSSascha Wildner 		if ((T_TCP(c)->connected_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
335*21c1c48aSSascha Wildner 			return(DFUI_FAILURE);
336*21c1c48aSSascha Wildner 		}
337*21c1c48aSSascha Wildner 
338*21c1c48aSSascha Wildner 		dfui_debug("CLIENT_SOCKET<<%d>>\n", T_TCP(c)->connected_sd);
339*21c1c48aSSascha Wildner 		bzero(&servaddr, sizeof(servaddr));
340*21c1c48aSSascha Wildner 		servaddr.sin_family = AF_INET;
341*21c1c48aSSascha Wildner 		servaddr.sin_port = htons(server_port);
342*21c1c48aSSascha Wildner 		inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
343*21c1c48aSSascha Wildner 
344*21c1c48aSSascha Wildner 		if (connect(T_TCP(c)->connected_sd, (struct sockaddr *)&servaddr,
345*21c1c48aSSascha Wildner 		    sizeof(servaddr)) == 0) {
346*21c1c48aSSascha Wildner 			dfui_debug("CONNECTED<<>>\n");
347*21c1c48aSSascha Wildner 			connected = 1;
348*21c1c48aSSascha Wildner 		} else {
349*21c1c48aSSascha Wildner 			dfui_debug("NO_CONNECT<<>>\n");
350*21c1c48aSSascha Wildner 			close(T_TCP(c)->connected_sd);
351*21c1c48aSSascha Wildner 			sleep(1);
352*21c1c48aSSascha Wildner 		}
353*21c1c48aSSascha Wildner 	}
354*21c1c48aSSascha Wildner 
355*21c1c48aSSascha Wildner         /* at this point we should be connected */
356*21c1c48aSSascha Wildner 
357*21c1c48aSSascha Wildner 	T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+");
358*21c1c48aSSascha Wildner 
359*21c1c48aSSascha Wildner         return(DFUI_SUCCESS);
360*21c1c48aSSascha Wildner }
361*21c1c48aSSascha Wildner 
362*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_fe_disconnect(struct dfui_connection * c)363*21c1c48aSSascha Wildner dfui_tcp_fe_disconnect(struct dfui_connection *c)
364*21c1c48aSSascha Wildner {
365*21c1c48aSSascha Wildner 	close(T_TCP(c)->connected_sd);
366*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
367*21c1c48aSSascha Wildner }
368*21c1c48aSSascha Wildner 
369*21c1c48aSSascha Wildner /** Low Level **/
370*21c1c48aSSascha Wildner 
371*21c1c48aSSascha Wildner /*
372*21c1c48aSSascha Wildner  * Ask for, and subsequently receieve, a message from the backend.
373*21c1c48aSSascha Wildner  * msgtype should be one of the DFUI_FE_MSG_* constants.
374*21c1c48aSSascha Wildner  * This call is synchronous.
375*21c1c48aSSascha Wildner  * After this call, the null-terminated, encoded message is
376*21c1c48aSSascha Wildner  * available in T_TCP(c)->buf.
377*21c1c48aSSascha Wildner  */
378*21c1c48aSSascha Wildner dfui_err_t
dfui_tcp_fe_ll_request(struct dfui_connection * c,char msgtype,const char * msg)379*21c1c48aSSascha Wildner dfui_tcp_fe_ll_request(struct dfui_connection *c, char msgtype, const char *msg)
380*21c1c48aSSascha Wildner {
381*21c1c48aSSascha Wildner 	char *fmsg, *buf;
382*21c1c48aSSascha Wildner 	int length, result;
383*21c1c48aSSascha Wildner 
384*21c1c48aSSascha Wildner 	/*
385*21c1c48aSSascha Wildner 	 * First, assert that the connection is open.
386*21c1c48aSSascha Wildner 	 */
387*21c1c48aSSascha Wildner 
388*21c1c48aSSascha Wildner 	if (c == NULL || T_TCP(c)->connected_sd == -1)
389*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
390*21c1c48aSSascha Wildner 
391*21c1c48aSSascha Wildner 	/*
392*21c1c48aSSascha Wildner 	 * Construct a message.
393*21c1c48aSSascha Wildner 	 */
394*21c1c48aSSascha Wildner 
395*21c1c48aSSascha Wildner 	fmsg = malloc(strlen(msg) + 2);
396*21c1c48aSSascha Wildner 	fmsg[0] = msgtype;
397*21c1c48aSSascha Wildner 	strcpy(fmsg + 1, msg);
398*21c1c48aSSascha Wildner 	dfui_debug("SEND<<%s>>\n", fmsg);
399*21c1c48aSSascha Wildner 
400*21c1c48aSSascha Wildner 	/*
401*21c1c48aSSascha Wildner 	 * Send a NUL-terminated message to the backend.
402*21c1c48aSSascha Wildner 	 */
403*21c1c48aSSascha Wildner 
404*21c1c48aSSascha Wildner         length = strlen(fmsg);
405*21c1c48aSSascha Wildner         result = write_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
406*21c1c48aSSascha Wildner 	dfui_debug("result<<%d>>\n", result);
407*21c1c48aSSascha Wildner 	result = write_data(T_TCP(c)->stream, (char *)fmsg, length);
408*21c1c48aSSascha Wildner 	dfui_debug("result<<%d>>\n", result);
409*21c1c48aSSascha Wildner 
410*21c1c48aSSascha Wildner 	/*
411*21c1c48aSSascha Wildner 	 * Receive a reply from the backend.
412*21c1c48aSSascha Wildner 	 * If our message was a READY, this should be a message like PRESENT.
413*21c1c48aSSascha Wildner 	 * Otherwise it should simply be a READY.
414*21c1c48aSSascha Wildner 	 */
415*21c1c48aSSascha Wildner 
416*21c1c48aSSascha Wildner 	dfui_debug("WAITING<<>>\n");
417*21c1c48aSSascha Wildner         result = read_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
418*21c1c48aSSascha Wildner 	dfui_debug("result<<%d>>\n", result);
419*21c1c48aSSascha Wildner         buf = malloc(length + 1);
420*21c1c48aSSascha Wildner         result = read_data(T_TCP(c)->stream, buf, length);
421*21c1c48aSSascha Wildner 	dfui_debug("result<<%d>>\n", result);
422*21c1c48aSSascha Wildner         aura_buffer_set(c->ebuf, buf, length);
423*21c1c48aSSascha Wildner         free(buf);
424*21c1c48aSSascha Wildner 
425*21c1c48aSSascha Wildner 	dfui_debug("RECV<<%s>>\n", aura_buffer_buf(c->ebuf));
426*21c1c48aSSascha Wildner 
427*21c1c48aSSascha Wildner 	free(fmsg);
428*21c1c48aSSascha Wildner 
429*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
430*21c1c48aSSascha Wildner }
431*21c1c48aSSascha Wildner 
432*21c1c48aSSascha Wildner int
read_data(FILE * f,char * buf,int n)433*21c1c48aSSascha Wildner read_data(FILE *f, char *buf, int n)
434*21c1c48aSSascha Wildner {
435*21c1c48aSSascha Wildner 	int bcount;	/* counts bytes read */
436*21c1c48aSSascha Wildner 	int br;		/* bytes read this pass */
437*21c1c48aSSascha Wildner 
438*21c1c48aSSascha Wildner 	bcount = 0;
439*21c1c48aSSascha Wildner 	br = 0;
440*21c1c48aSSascha Wildner 	while (bcount < n) {
441*21c1c48aSSascha Wildner 		if ((br = fread(buf, 1, n - bcount, f)) > 0) {
442*21c1c48aSSascha Wildner 			dfui_debug("READ_BYTES<<%d>>\n", br);
443*21c1c48aSSascha Wildner 			bcount += br;
444*21c1c48aSSascha Wildner 			buf += br;
445*21c1c48aSSascha Wildner 		} else if (br <= 0) {
446*21c1c48aSSascha Wildner 			dfui_debug("read_data_error<<%d>>\n", br);
447*21c1c48aSSascha Wildner 			return(-1);
448*21c1c48aSSascha Wildner 		}
449*21c1c48aSSascha Wildner 	}
450*21c1c48aSSascha Wildner 	return(bcount);
451*21c1c48aSSascha Wildner }
452*21c1c48aSSascha Wildner 
453*21c1c48aSSascha Wildner int
write_data(FILE * f,const char * buf,int n)454*21c1c48aSSascha Wildner write_data(FILE *f, const char *buf, int n)
455*21c1c48aSSascha Wildner {
456*21c1c48aSSascha Wildner         int bcount;	/* counts bytes written */
457*21c1c48aSSascha Wildner         int bw;		/* bytes written this pass */
458*21c1c48aSSascha Wildner 
459*21c1c48aSSascha Wildner         bcount = 0;
460*21c1c48aSSascha Wildner         bw = 0;
461*21c1c48aSSascha Wildner         while (bcount < n) {
462*21c1c48aSSascha Wildner                 if ((bw = fwrite(buf, 1, n - bcount, f)) > 0) {
463*21c1c48aSSascha Wildner 			dfui_debug("WROTE_BYTES<<%d>>\n", bw);
464*21c1c48aSSascha Wildner                         bcount += bw;
465*21c1c48aSSascha Wildner                         buf += bw;
466*21c1c48aSSascha Wildner                 } else if (bw <= 0) {
467*21c1c48aSSascha Wildner 			dfui_debug("write_data_error<<%d>>\n", bw);
468*21c1c48aSSascha Wildner 			return(-1);
469*21c1c48aSSascha Wildner 		}
470*21c1c48aSSascha Wildner         }
471*21c1c48aSSascha Wildner         return(bcount);
472*21c1c48aSSascha Wildner }
473*21c1c48aSSascha Wildner 
474*21c1c48aSSascha Wildner #endif /* HAS_TCP */
475