1*21c1c48aSSascha Wildner /*
2*21c1c48aSSascha Wildner  * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
3*21c1c48aSSascha Wildner  *
4*21c1c48aSSascha Wildner  * Redistribution and use in source and binary forms, with or without
5*21c1c48aSSascha Wildner  * modification, are permitted provided that the following conditions
6*21c1c48aSSascha Wildner  * are met:
7*21c1c48aSSascha Wildner  *
8*21c1c48aSSascha Wildner  *   Redistributions of source code must retain the above copyright
9*21c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer.
10*21c1c48aSSascha Wildner  *
11*21c1c48aSSascha Wildner  *   Redistributions in binary form must reproduce the above copyright
12*21c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer in
13*21c1c48aSSascha Wildner  *   the documentation and/or other materials provided with the
14*21c1c48aSSascha Wildner  *   distribution.
15*21c1c48aSSascha Wildner  *
16*21c1c48aSSascha Wildner  *   Neither the name of Cat's Eye Technologies nor the names of its
17*21c1c48aSSascha Wildner  *   contributors may be used to endorse or promote products derived
18*21c1c48aSSascha Wildner  *   from this software without specific prior written permission.
19*21c1c48aSSascha Wildner  *
20*21c1c48aSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*21c1c48aSSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*21c1c48aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*21c1c48aSSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24*21c1c48aSSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25*21c1c48aSSascha Wildner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26*21c1c48aSSascha Wildner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27*21c1c48aSSascha Wildner  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*21c1c48aSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29*21c1c48aSSascha Wildner  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30*21c1c48aSSascha Wildner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31*21c1c48aSSascha Wildner  * OF THE POSSIBILITY OF SUCH DAMAGE.
32*21c1c48aSSascha Wildner  */
33*21c1c48aSSascha Wildner 
34*21c1c48aSSascha Wildner /*
35*21c1c48aSSascha Wildner  * connection.c
36*21c1c48aSSascha Wildner  * $Id: connection.c,v 1.20 2005/02/07 06:39:59 cpressey Exp $
37*21c1c48aSSascha Wildner  * This code was derived in part from:
38*21c1c48aSSascha Wildner  * $_DragonFly: src/test/caps/client.c,v 1.3 2004/03/31 20:27:34 dillon Exp $
39*21c1c48aSSascha Wildner  * and is therefore also subject to the license conditions on that file.
40*21c1c48aSSascha Wildner  */
41*21c1c48aSSascha Wildner 
42*21c1c48aSSascha Wildner #include <stdarg.h>
43*21c1c48aSSascha Wildner #include <stdlib.h>
44*21c1c48aSSascha Wildner #include <string.h>
45*21c1c48aSSascha Wildner 
46*21c1c48aSSascha Wildner #include <libaura/mem.h>
47*21c1c48aSSascha Wildner #include <libaura/buffer.h>
48*21c1c48aSSascha Wildner 
49*21c1c48aSSascha Wildner #include "system.h"
50*21c1c48aSSascha Wildner #define	NEEDS_DFUI_STRUCTURE_DEFINITIONS
51*21c1c48aSSascha Wildner #include "dfui.h"
52*21c1c48aSSascha Wildner #undef	NEEDS_DFUI_STRUCTURE_DEFINITIONS
53*21c1c48aSSascha Wildner #include "encoding.h"
54*21c1c48aSSascha Wildner #include "dump.h"
55*21c1c48aSSascha Wildner 
56*21c1c48aSSascha Wildner #include "conn_npipe.h"
57*21c1c48aSSascha Wildner #include "conn_tcp.h"
58*21c1c48aSSascha Wildner 
59*21c1c48aSSascha Wildner struct dfui_connection *
dfui_connection_new(int transport,const char * rendezvous)60*21c1c48aSSascha Wildner dfui_connection_new(int transport, const char *rendezvous)
61*21c1c48aSSascha Wildner {
62*21c1c48aSSascha Wildner 	struct dfui_connection *c = NULL;
63*21c1c48aSSascha Wildner 
64*21c1c48aSSascha Wildner 	if (
65*21c1c48aSSascha Wildner #ifdef HAS_NPIPE
66*21c1c48aSSascha Wildner 	    transport == DFUI_TRANSPORT_NPIPE ||
67*21c1c48aSSascha Wildner #endif
68*21c1c48aSSascha Wildner #ifdef HAS_TCP
69*21c1c48aSSascha Wildner 	    transport == DFUI_TRANSPORT_TCP ||
70*21c1c48aSSascha Wildner #endif
71*21c1c48aSSascha Wildner 	    0) {
72*21c1c48aSSascha Wildner 		/* We're OK. */
73*21c1c48aSSascha Wildner 	} else {
74*21c1c48aSSascha Wildner 		return(NULL);
75*21c1c48aSSascha Wildner 	}
76*21c1c48aSSascha Wildner 
77*21c1c48aSSascha Wildner 	if (dfui_debug_file == NULL) {
78*21c1c48aSSascha Wildner 		dfui_debug_file = stderr;
79*21c1c48aSSascha Wildner 	} else {
80*21c1c48aSSascha Wildner 		setvbuf(dfui_debug_file, NULL, _IOLBF, 0);
81*21c1c48aSSascha Wildner 	}
82*21c1c48aSSascha Wildner 
83*21c1c48aSSascha Wildner 	AURA_MALLOC(c, dfui_connection);
84*21c1c48aSSascha Wildner 	c->rendezvous = aura_strdup(rendezvous);
85*21c1c48aSSascha Wildner 	c->transport = transport;
86*21c1c48aSSascha Wildner 	c->ebuf = aura_buffer_new(16384);
87*21c1c48aSSascha Wildner 	c->is_connected = 0;
88*21c1c48aSSascha Wildner 	c->t_data = NULL;
89*21c1c48aSSascha Wildner 
90*21c1c48aSSascha Wildner 	switch (transport) {
91*21c1c48aSSascha Wildner #ifdef HAS_NPIPE
92*21c1c48aSSascha Wildner 	case DFUI_TRANSPORT_NPIPE:
93*21c1c48aSSascha Wildner 		AURA_MALLOC(c->t_data, dfui_conn_npipe);
94*21c1c48aSSascha Wildner 		T_NPIPE(c)->in_pipename = NULL;
95*21c1c48aSSascha Wildner 		T_NPIPE(c)->out_pipename = NULL;
96*21c1c48aSSascha Wildner 		T_NPIPE(c)->in = NULL;
97*21c1c48aSSascha Wildner 		T_NPIPE(c)->out = NULL;
98*21c1c48aSSascha Wildner 
99*21c1c48aSSascha Wildner 		/*
100*21c1c48aSSascha Wildner 		 * Set up dispatch functions.
101*21c1c48aSSascha Wildner 		 */
102*21c1c48aSSascha Wildner 		c->be_start = dfui_npipe_be_start;
103*21c1c48aSSascha Wildner 		c->be_stop = dfui_npipe_be_stop;
104*21c1c48aSSascha Wildner 		c->be_ll_exchange = dfui_npipe_be_ll_exchange;
105*21c1c48aSSascha Wildner 
106*21c1c48aSSascha Wildner 		c->fe_connect = dfui_npipe_fe_connect;
107*21c1c48aSSascha Wildner 		c->fe_disconnect = dfui_npipe_fe_disconnect;
108*21c1c48aSSascha Wildner 		c->fe_ll_request = dfui_npipe_fe_ll_request;
109*21c1c48aSSascha Wildner 		break;
110*21c1c48aSSascha Wildner #endif /* HAS_NPIPE */
111*21c1c48aSSascha Wildner 
112*21c1c48aSSascha Wildner #ifdef HAS_TCP
113*21c1c48aSSascha Wildner 	case DFUI_TRANSPORT_TCP:
114*21c1c48aSSascha Wildner                 AURA_MALLOC(c->t_data, dfui_conn_tcp);
115*21c1c48aSSascha Wildner 		T_TCP(c)->listen_sd = -1;
116*21c1c48aSSascha Wildner 		T_TCP(c)->connected_sd = -1;
117*21c1c48aSSascha Wildner 		T_TCP(c)->is_connected = 0;
118*21c1c48aSSascha Wildner 
119*21c1c48aSSascha Wildner                 /*
120*21c1c48aSSascha Wildner                  * Set up dispatch functions.
121*21c1c48aSSascha Wildner                  */
122*21c1c48aSSascha Wildner                 c->be_start = dfui_tcp_be_start;
123*21c1c48aSSascha Wildner                 c->be_stop = dfui_tcp_be_stop;
124*21c1c48aSSascha Wildner 		c->be_ll_exchange = dfui_tcp_be_ll_exchange;
125*21c1c48aSSascha Wildner 
126*21c1c48aSSascha Wildner                 c->fe_connect = dfui_tcp_fe_connect;
127*21c1c48aSSascha Wildner                 c->fe_disconnect = dfui_tcp_fe_disconnect;
128*21c1c48aSSascha Wildner 		c->fe_ll_request = dfui_tcp_fe_ll_request;
129*21c1c48aSSascha Wildner 		break;
130*21c1c48aSSascha Wildner #endif /* HAS_TCP */
131*21c1c48aSSascha Wildner 	}
132*21c1c48aSSascha Wildner 
133*21c1c48aSSascha Wildner 	return(c);
134*21c1c48aSSascha Wildner }
135*21c1c48aSSascha Wildner 
136*21c1c48aSSascha Wildner void
dfui_connection_free(struct dfui_connection * c)137*21c1c48aSSascha Wildner dfui_connection_free(struct dfui_connection *c)
138*21c1c48aSSascha Wildner {
139*21c1c48aSSascha Wildner 	if (c == NULL)
140*21c1c48aSSascha Wildner 		return;
141*21c1c48aSSascha Wildner 
142*21c1c48aSSascha Wildner 	switch (c->transport) {
143*21c1c48aSSascha Wildner #ifdef HAS_NPIPE
144*21c1c48aSSascha Wildner 	case DFUI_TRANSPORT_NPIPE:
145*21c1c48aSSascha Wildner 		if (T_NPIPE(c) != NULL) {
146*21c1c48aSSascha Wildner 			if (T_NPIPE(c)->in_pipename != NULL)
147*21c1c48aSSascha Wildner 				aura_free(T_NPIPE(c)->in_pipename, "pipename");
148*21c1c48aSSascha Wildner 			if (T_NPIPE(c)->out_pipename != NULL)
149*21c1c48aSSascha Wildner 				aura_free(T_NPIPE(c)->out_pipename, "pipename");
150*21c1c48aSSascha Wildner 			if (T_NPIPE(c)->in != NULL)
151*21c1c48aSSascha Wildner 				fclose(T_NPIPE(c)->in);
152*21c1c48aSSascha Wildner 			if (T_NPIPE(c)->out != NULL)
153*21c1c48aSSascha Wildner 				fclose(T_NPIPE(c)->out);
154*21c1c48aSSascha Wildner 			AURA_FREE(T_NPIPE(c), dfui_conn_npipe);
155*21c1c48aSSascha Wildner 		}
156*21c1c48aSSascha Wildner 		break;
157*21c1c48aSSascha Wildner #endif
158*21c1c48aSSascha Wildner #ifdef HAS_TCP
159*21c1c48aSSascha Wildner 	case DFUI_TRANSPORT_TCP:
160*21c1c48aSSascha Wildner 		if (T_TCP(c) != NULL) {
161*21c1c48aSSascha Wildner 			/* XXX close sockets/files here */
162*21c1c48aSSascha Wildner 			AURA_FREE(T_NPIPE(c), dfui_conn_tcp);
163*21c1c48aSSascha Wildner 		}
164*21c1c48aSSascha Wildner 		break;
165*21c1c48aSSascha Wildner #endif
166*21c1c48aSSascha Wildner 	}
167*21c1c48aSSascha Wildner 
168*21c1c48aSSascha Wildner 	if (c->rendezvous != NULL)
169*21c1c48aSSascha Wildner 		free(c->rendezvous);
170*21c1c48aSSascha Wildner 	AURA_FREE(c, dfui_connection);
171*21c1c48aSSascha Wildner }
172*21c1c48aSSascha Wildner 
173*21c1c48aSSascha Wildner /*
174*21c1c48aSSascha Wildner  * VERY HIGH LEVEL
175*21c1c48aSSascha Wildner  */
176*21c1c48aSSascha Wildner 
177*21c1c48aSSascha Wildner /*
178*21c1c48aSSascha Wildner  * Create and present a generic `dialog box'-type form for the user
179*21c1c48aSSascha Wildner  * and return their response.  actions is a pipe-seperated list of
180*21c1c48aSSascha Wildner  * actions to be put on the form (e.g. "OK|Cancel".)  The return
181*21c1c48aSSascha Wildner  * value is the ordinal position of the action that was selected,
182*21c1c48aSSascha Wildner  * starting at 1 for the first action.  A return value of 0 indicates
183*21c1c48aSSascha Wildner  * that an error occurred.  A return value of -1 indicates that the
184*21c1c48aSSascha Wildner  * front end aborted the communications.
185*21c1c48aSSascha Wildner  */
186*21c1c48aSSascha Wildner int
dfui_be_present_dialog(struct dfui_connection * c,const char * title,const char * actions,const char * fmt,...)187*21c1c48aSSascha Wildner dfui_be_present_dialog(struct dfui_connection *c, const char *title,
188*21c1c48aSSascha Wildner 			const char *actions, const char *fmt, ...)
189*21c1c48aSSascha Wildner {
190*21c1c48aSSascha Wildner 	struct dfui_form *f;
191*21c1c48aSSascha Wildner 	struct dfui_response *r;
192*21c1c48aSSascha Wildner 	va_list args;
193*21c1c48aSSascha Wildner 	char *message;
194*21c1c48aSSascha Wildner 	char action_id[256], action_name[256];
195*21c1c48aSSascha Wildner 	size_t start, end, counter, i;
196*21c1c48aSSascha Wildner 
197*21c1c48aSSascha Wildner 	va_start(args, fmt);
198*21c1c48aSSascha Wildner 	vasprintf(&message, fmt, args);
199*21c1c48aSSascha Wildner 	va_end(args);
200*21c1c48aSSascha Wildner 
201*21c1c48aSSascha Wildner 	f = dfui_form_create("dialog", title, message, "", NULL);
202*21c1c48aSSascha Wildner 
203*21c1c48aSSascha Wildner 	free(message);
204*21c1c48aSSascha Wildner 
205*21c1c48aSSascha Wildner 	start = end = 0;
206*21c1c48aSSascha Wildner 	while (actions[end] != '\0') {
207*21c1c48aSSascha Wildner 		end = start;
208*21c1c48aSSascha Wildner 		while (actions[end] != '|' && actions[end] != '\0')
209*21c1c48aSSascha Wildner 			end++;
210*21c1c48aSSascha Wildner 
211*21c1c48aSSascha Wildner 		if ((end - start) >= 256)
212*21c1c48aSSascha Wildner 			break;
213*21c1c48aSSascha Wildner 		strncpy(action_name, &actions[start], end - start);
214*21c1c48aSSascha Wildner 		action_name[end - start] = '\0';
215*21c1c48aSSascha Wildner 		strcpy(action_id, action_name);
216*21c1c48aSSascha Wildner 		for(i = 0; action_id[i] != '\0'; i++) {
217*21c1c48aSSascha Wildner 			if (action_id[i] == ' ')
218*21c1c48aSSascha Wildner 				action_id[i] = '_';
219*21c1c48aSSascha Wildner 		}
220*21c1c48aSSascha Wildner 		dfui_form_action_add(f, action_id,
221*21c1c48aSSascha Wildner 		    dfui_info_new(action_name, "", ""));
222*21c1c48aSSascha Wildner 
223*21c1c48aSSascha Wildner 		start = end + 1;
224*21c1c48aSSascha Wildner 	}
225*21c1c48aSSascha Wildner 
226*21c1c48aSSascha Wildner 	if (!dfui_be_present(c, f, &r)) {
227*21c1c48aSSascha Wildner 		dfui_form_free(f);
228*21c1c48aSSascha Wildner 		dfui_response_free(r);
229*21c1c48aSSascha Wildner 		return(-1);
230*21c1c48aSSascha Wildner 	}
231*21c1c48aSSascha Wildner 
232*21c1c48aSSascha Wildner 	strlcpy(action_name, dfui_response_get_action_id(r), 256);
233*21c1c48aSSascha Wildner 	for(i = 0; action_name[i] != '\0'; i++) {
234*21c1c48aSSascha Wildner 		if (action_name[i] == '_')
235*21c1c48aSSascha Wildner 			action_name[i] = ' ';
236*21c1c48aSSascha Wildner 	}
237*21c1c48aSSascha Wildner 
238*21c1c48aSSascha Wildner 	start = end = 0;
239*21c1c48aSSascha Wildner 	counter = 1;
240*21c1c48aSSascha Wildner 	while (actions[end] != '\0') {
241*21c1c48aSSascha Wildner 		end = start;
242*21c1c48aSSascha Wildner 		while (actions[end] != '|' && actions[end] != '\0')
243*21c1c48aSSascha Wildner 			end++;
244*21c1c48aSSascha Wildner 
245*21c1c48aSSascha Wildner 		if ((end - start) >= 256)
246*21c1c48aSSascha Wildner 			break;
247*21c1c48aSSascha Wildner 		if (strlen(action_name) == (end - start) &&
248*21c1c48aSSascha Wildner 		    strncmp(action_name, &actions[start], end - start) == 0) {
249*21c1c48aSSascha Wildner 			break;
250*21c1c48aSSascha Wildner 		}
251*21c1c48aSSascha Wildner 		counter++;
252*21c1c48aSSascha Wildner 
253*21c1c48aSSascha Wildner 		start = end + 1;
254*21c1c48aSSascha Wildner 	}
255*21c1c48aSSascha Wildner 
256*21c1c48aSSascha Wildner 	dfui_form_free(f);
257*21c1c48aSSascha Wildner 	dfui_response_free(r);
258*21c1c48aSSascha Wildner 
259*21c1c48aSSascha Wildner 	return(counter);
260*21c1c48aSSascha Wildner }
261*21c1c48aSSascha Wildner 
262*21c1c48aSSascha Wildner /******** BACKEND ********/
263*21c1c48aSSascha Wildner 
264*21c1c48aSSascha Wildner /*
265*21c1c48aSSascha Wildner  * Connect to the frontend.
266*21c1c48aSSascha Wildner  */
267*21c1c48aSSascha Wildner dfui_err_t
dfui_be_start(struct dfui_connection * c)268*21c1c48aSSascha Wildner dfui_be_start(struct dfui_connection *c)
269*21c1c48aSSascha Wildner {
270*21c1c48aSSascha Wildner 	if (c->is_connected) {
271*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
272*21c1c48aSSascha Wildner 	} else if (c->be_start(c)) {
273*21c1c48aSSascha Wildner 		c->is_connected = 1;
274*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
275*21c1c48aSSascha Wildner 	} else {
276*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
277*21c1c48aSSascha Wildner 	}
278*21c1c48aSSascha Wildner }
279*21c1c48aSSascha Wildner 
280*21c1c48aSSascha Wildner /*
281*21c1c48aSSascha Wildner  * Tell the frontend that we're done and disconnect from it.
282*21c1c48aSSascha Wildner  */
283*21c1c48aSSascha Wildner dfui_err_t
dfui_be_stop(struct dfui_connection * c)284*21c1c48aSSascha Wildner dfui_be_stop(struct dfui_connection *c)
285*21c1c48aSSascha Wildner {
286*21c1c48aSSascha Wildner 	if (!c->is_connected) {
287*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
288*21c1c48aSSascha Wildner 	} else if (c->be_stop(c)) {
289*21c1c48aSSascha Wildner 		c->is_connected = 0;
290*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
291*21c1c48aSSascha Wildner 	} else {
292*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
293*21c1c48aSSascha Wildner 	}
294*21c1c48aSSascha Wildner }
295*21c1c48aSSascha Wildner 
296*21c1c48aSSascha Wildner /*
297*21c1c48aSSascha Wildner  * Present a form to the user.  This call is synchronous;
298*21c1c48aSSascha Wildner  * it does not return until the user has selected an action.
299*21c1c48aSSascha Wildner  */
300*21c1c48aSSascha Wildner dfui_err_t
dfui_be_present(struct dfui_connection * c,struct dfui_form * f,struct dfui_response ** r)301*21c1c48aSSascha Wildner dfui_be_present(struct dfui_connection *c,
302*21c1c48aSSascha Wildner 		struct dfui_form *f, struct dfui_response **r)
303*21c1c48aSSascha Wildner {
304*21c1c48aSSascha Wildner 	struct aura_buffer *e;
305*21c1c48aSSascha Wildner 
306*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
307*21c1c48aSSascha Wildner 	dfui_encode_form(e, f);
308*21c1c48aSSascha Wildner 
309*21c1c48aSSascha Wildner 	c->be_ll_exchange(c, DFUI_BE_MSG_PRESENT, aura_buffer_buf(e));
310*21c1c48aSSascha Wildner 
311*21c1c48aSSascha Wildner 	aura_buffer_free(e);
312*21c1c48aSSascha Wildner 
313*21c1c48aSSascha Wildner 	/* check for ABORT reply */
314*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
315*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
316*21c1c48aSSascha Wildner 	}
317*21c1c48aSSascha Wildner 
318*21c1c48aSSascha Wildner 	/*
319*21c1c48aSSascha Wildner 	 * Now we've got the response; so decode it.
320*21c1c48aSSascha Wildner 	 */
321*21c1c48aSSascha Wildner 
322*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
323*21c1c48aSSascha Wildner 	aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
324*21c1c48aSSascha Wildner 	*r = dfui_decode_response(e);
325*21c1c48aSSascha Wildner 	aura_buffer_free(e);
326*21c1c48aSSascha Wildner 
327*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
328*21c1c48aSSascha Wildner }
329*21c1c48aSSascha Wildner 
330*21c1c48aSSascha Wildner /*
331*21c1c48aSSascha Wildner  * Begin showing a progress bar to the user.
332*21c1c48aSSascha Wildner  * This function is asynchronous; it returns immediately.
333*21c1c48aSSascha Wildner  * The assumption is that the backend will make subsequent
334*21c1c48aSSascha Wildner  * calls to dfui_be_progress_update() frequently, and in
335*21c1c48aSSascha Wildner  * them, check to see if the user cancelled.
336*21c1c48aSSascha Wildner  */
337*21c1c48aSSascha Wildner dfui_err_t
dfui_be_progress_begin(struct dfui_connection * c,struct dfui_progress * pr)338*21c1c48aSSascha Wildner dfui_be_progress_begin(struct dfui_connection *c, struct dfui_progress *pr)
339*21c1c48aSSascha Wildner {
340*21c1c48aSSascha Wildner 	struct aura_buffer *e;
341*21c1c48aSSascha Wildner 
342*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
343*21c1c48aSSascha Wildner 	dfui_encode_progress(e, pr);
344*21c1c48aSSascha Wildner 
345*21c1c48aSSascha Wildner 	c->be_ll_exchange(c, DFUI_BE_MSG_PROG_BEGIN, aura_buffer_buf(e));
346*21c1c48aSSascha Wildner 	aura_buffer_free(e);
347*21c1c48aSSascha Wildner 
348*21c1c48aSSascha Wildner 	/* response might have been be READY or ABORT */
349*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
350*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
351*21c1c48aSSascha Wildner 	} else {
352*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
353*21c1c48aSSascha Wildner 	}
354*21c1c48aSSascha Wildner }
355*21c1c48aSSascha Wildner 
356*21c1c48aSSascha Wildner dfui_err_t
dfui_be_progress_update(struct dfui_connection * c,struct dfui_progress * pr,int * cancelled)357*21c1c48aSSascha Wildner dfui_be_progress_update(struct dfui_connection *c,
358*21c1c48aSSascha Wildner 			struct dfui_progress *pr, int *cancelled)
359*21c1c48aSSascha Wildner {
360*21c1c48aSSascha Wildner 	struct aura_buffer *e;
361*21c1c48aSSascha Wildner 
362*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
363*21c1c48aSSascha Wildner 	dfui_encode_progress(e, pr);
364*21c1c48aSSascha Wildner 
365*21c1c48aSSascha Wildner 	c->be_ll_exchange(c, DFUI_BE_MSG_PROG_UPDATE, aura_buffer_buf(e));
366*21c1c48aSSascha Wildner 	aura_buffer_free(e);
367*21c1c48aSSascha Wildner 
368*21c1c48aSSascha Wildner 	/* response might have been READY, CANCEL, or ABORT */
369*21c1c48aSSascha Wildner 
370*21c1c48aSSascha Wildner 	*cancelled = 0;
371*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_CANCEL) {
372*21c1c48aSSascha Wildner 		*cancelled = 1;
373*21c1c48aSSascha Wildner 	}
374*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
375*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
376*21c1c48aSSascha Wildner 	} else {
377*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
378*21c1c48aSSascha Wildner 	}
379*21c1c48aSSascha Wildner }
380*21c1c48aSSascha Wildner 
381*21c1c48aSSascha Wildner dfui_err_t
dfui_be_progress_end(struct dfui_connection * c)382*21c1c48aSSascha Wildner dfui_be_progress_end(struct dfui_connection *c)
383*21c1c48aSSascha Wildner {
384*21c1c48aSSascha Wildner 	c->be_ll_exchange(c, DFUI_BE_MSG_PROG_END, "");
385*21c1c48aSSascha Wildner 
386*21c1c48aSSascha Wildner 	/* response might have been be READY or ABORT */
387*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
388*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
389*21c1c48aSSascha Wildner 	} else {
390*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
391*21c1c48aSSascha Wildner 	}
392*21c1c48aSSascha Wildner }
393*21c1c48aSSascha Wildner 
394*21c1c48aSSascha Wildner dfui_err_t
dfui_be_set_global_setting(struct dfui_connection * c,const char * key,const char * value,int * cancelled)395*21c1c48aSSascha Wildner dfui_be_set_global_setting(struct dfui_connection *c,
396*21c1c48aSSascha Wildner 			   const char *key, const char *value,
397*21c1c48aSSascha Wildner 			   int *cancelled)
398*21c1c48aSSascha Wildner {
399*21c1c48aSSascha Wildner 	struct aura_buffer *e;
400*21c1c48aSSascha Wildner 	struct dfui_property *p;
401*21c1c48aSSascha Wildner 
402*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
403*21c1c48aSSascha Wildner 	p = dfui_property_new(key, value);
404*21c1c48aSSascha Wildner 	dfui_encode_property(e, p);
405*21c1c48aSSascha Wildner 	c->be_ll_exchange(c, DFUI_BE_MSG_SET_GLOBAL, aura_buffer_buf(e));
406*21c1c48aSSascha Wildner 	aura_buffer_free(e);
407*21c1c48aSSascha Wildner 	dfui_property_free(p);
408*21c1c48aSSascha Wildner 
409*21c1c48aSSascha Wildner 	/* response might have been READY, CANCEL, or ABORT */
410*21c1c48aSSascha Wildner 
411*21c1c48aSSascha Wildner 	*cancelled = 0;
412*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_CANCEL) {
413*21c1c48aSSascha Wildner 		*cancelled = 1;
414*21c1c48aSSascha Wildner 	}
415*21c1c48aSSascha Wildner 	if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
416*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
417*21c1c48aSSascha Wildner 	} else {
418*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
419*21c1c48aSSascha Wildner 	}
420*21c1c48aSSascha Wildner }
421*21c1c48aSSascha Wildner 
422*21c1c48aSSascha Wildner /******** FRONTEND ********/
423*21c1c48aSSascha Wildner 
424*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_connect(struct dfui_connection * c)425*21c1c48aSSascha Wildner dfui_fe_connect(struct dfui_connection *c)
426*21c1c48aSSascha Wildner {
427*21c1c48aSSascha Wildner 	return(c->fe_connect(c));
428*21c1c48aSSascha Wildner }
429*21c1c48aSSascha Wildner 
430*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_disconnect(struct dfui_connection * c)431*21c1c48aSSascha Wildner dfui_fe_disconnect(struct dfui_connection *c)
432*21c1c48aSSascha Wildner {
433*21c1c48aSSascha Wildner 	dfui_debug("DISCONNECTING<<>>\n");
434*21c1c48aSSascha Wildner 	return(c->fe_disconnect(c));
435*21c1c48aSSascha Wildner }
436*21c1c48aSSascha Wildner 
437*21c1c48aSSascha Wildner /*
438*21c1c48aSSascha Wildner  * Receive a message from the backend.  This call is synchronous;
439*21c1c48aSSascha Wildner  * it does not return until a message comes in from the backend.
440*21c1c48aSSascha Wildner  * After this call, the message type is available in *msgtype,
441*21c1c48aSSascha Wildner  * and the message itself (if any) is available in *payload, ready
442*21c1c48aSSascha Wildner  * to be casted to its real type (as per *msgtype).
443*21c1c48aSSascha Wildner  */
444*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_receive(struct dfui_connection * c,char * msgtype,void ** payload)445*21c1c48aSSascha Wildner dfui_fe_receive(struct dfui_connection *c, char *msgtype, void **payload)
446*21c1c48aSSascha Wildner {
447*21c1c48aSSascha Wildner 	struct aura_buffer *e;
448*21c1c48aSSascha Wildner 
449*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_READY, "");
450*21c1c48aSSascha Wildner 	*msgtype = aura_buffer_buf(c->ebuf)[0];
451*21c1c48aSSascha Wildner 	switch (*msgtype) {
452*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PRESENT:
453*21c1c48aSSascha Wildner 		e = aura_buffer_new(16384);
454*21c1c48aSSascha Wildner 		aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
455*21c1c48aSSascha Wildner 		*payload = dfui_decode_form(e);
456*21c1c48aSSascha Wildner 		aura_buffer_free(e);
457*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
458*21c1c48aSSascha Wildner 
459*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_BEGIN:
460*21c1c48aSSascha Wildner 		e = aura_buffer_new(16384);
461*21c1c48aSSascha Wildner 		aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
462*21c1c48aSSascha Wildner 		*payload = dfui_decode_progress(e);
463*21c1c48aSSascha Wildner 		aura_buffer_free(e);
464*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
465*21c1c48aSSascha Wildner 
466*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_UPDATE:
467*21c1c48aSSascha Wildner 		e = aura_buffer_new(16384);
468*21c1c48aSSascha Wildner 		aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
469*21c1c48aSSascha Wildner 		*payload = dfui_decode_progress(e);
470*21c1c48aSSascha Wildner 		aura_buffer_free(e);
471*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
472*21c1c48aSSascha Wildner 
473*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_END:
474*21c1c48aSSascha Wildner 		*payload = NULL;
475*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
476*21c1c48aSSascha Wildner 
477*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_SET_GLOBAL:
478*21c1c48aSSascha Wildner 		e = aura_buffer_new(16384);
479*21c1c48aSSascha Wildner 		aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
480*21c1c48aSSascha Wildner 		*payload = dfui_decode_property(e);
481*21c1c48aSSascha Wildner 		aura_buffer_free(e);
482*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
483*21c1c48aSSascha Wildner 
484*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_STOP:
485*21c1c48aSSascha Wildner 		*payload = NULL;
486*21c1c48aSSascha Wildner 		return(DFUI_SUCCESS);
487*21c1c48aSSascha Wildner 
488*21c1c48aSSascha Wildner 	default:
489*21c1c48aSSascha Wildner 		/* XXX ??? */
490*21c1c48aSSascha Wildner 		return(DFUI_FAILURE);
491*21c1c48aSSascha Wildner 	}
492*21c1c48aSSascha Wildner }
493*21c1c48aSSascha Wildner 
494*21c1c48aSSascha Wildner /*
495*21c1c48aSSascha Wildner  * Wrapper function for dfui_fe_receive for binding generators which
496*21c1c48aSSascha Wildner  * seem to (understandably) have problems wrapping void *'s themselves.
497*21c1c48aSSascha Wildner  */
498*21c1c48aSSascha Wildner struct dfui_payload *
dfui_fe_receive_payload(struct dfui_connection * c)499*21c1c48aSSascha Wildner dfui_fe_receive_payload(struct dfui_connection *c)
500*21c1c48aSSascha Wildner {
501*21c1c48aSSascha Wildner 	char msgtype;
502*21c1c48aSSascha Wildner 	void *v;
503*21c1c48aSSascha Wildner 	struct dfui_payload *payload;
504*21c1c48aSSascha Wildner 
505*21c1c48aSSascha Wildner 	if (!dfui_fe_receive(c, &msgtype, &v)) {
506*21c1c48aSSascha Wildner 		return(NULL);
507*21c1c48aSSascha Wildner 	}
508*21c1c48aSSascha Wildner 
509*21c1c48aSSascha Wildner 	AURA_MALLOC(payload, dfui_payload);
510*21c1c48aSSascha Wildner 
511*21c1c48aSSascha Wildner 	payload->msgtype = msgtype;
512*21c1c48aSSascha Wildner 	payload->form = NULL;
513*21c1c48aSSascha Wildner 	payload->progress = NULL;
514*21c1c48aSSascha Wildner 
515*21c1c48aSSascha Wildner 	switch (msgtype) {
516*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PRESENT:
517*21c1c48aSSascha Wildner 		payload->form = v;
518*21c1c48aSSascha Wildner 		break;
519*21c1c48aSSascha Wildner 
520*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_BEGIN:
521*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_UPDATE:
522*21c1c48aSSascha Wildner 		payload->progress = v;
523*21c1c48aSSascha Wildner 		break;
524*21c1c48aSSascha Wildner 
525*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_SET_GLOBAL:
526*21c1c48aSSascha Wildner 		payload->global_setting = v;
527*21c1c48aSSascha Wildner 		break;
528*21c1c48aSSascha Wildner 
529*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_PROG_END:
530*21c1c48aSSascha Wildner 	case DFUI_BE_MSG_STOP:
531*21c1c48aSSascha Wildner 		break;
532*21c1c48aSSascha Wildner 	}
533*21c1c48aSSascha Wildner 
534*21c1c48aSSascha Wildner 	return(payload);
535*21c1c48aSSascha Wildner }
536*21c1c48aSSascha Wildner 
537*21c1c48aSSascha Wildner char
dfui_payload_get_msg_type(const struct dfui_payload * p)538*21c1c48aSSascha Wildner dfui_payload_get_msg_type(const struct dfui_payload *p)
539*21c1c48aSSascha Wildner {
540*21c1c48aSSascha Wildner 	if (p == NULL)
541*21c1c48aSSascha Wildner 		return(' ');
542*21c1c48aSSascha Wildner 	return(p->msgtype);
543*21c1c48aSSascha Wildner }
544*21c1c48aSSascha Wildner 
545*21c1c48aSSascha Wildner struct dfui_form *
dfui_payload_get_form(const struct dfui_payload * p)546*21c1c48aSSascha Wildner dfui_payload_get_form(const struct dfui_payload *p)
547*21c1c48aSSascha Wildner {
548*21c1c48aSSascha Wildner 	if (p == NULL)
549*21c1c48aSSascha Wildner 		return(NULL);
550*21c1c48aSSascha Wildner 	return(p->form);
551*21c1c48aSSascha Wildner }
552*21c1c48aSSascha Wildner 
553*21c1c48aSSascha Wildner struct dfui_progress *
dfui_payload_get_progress(const struct dfui_payload * p)554*21c1c48aSSascha Wildner dfui_payload_get_progress(const struct dfui_payload *p)
555*21c1c48aSSascha Wildner {
556*21c1c48aSSascha Wildner 	if (p == NULL)
557*21c1c48aSSascha Wildner 		return(NULL);
558*21c1c48aSSascha Wildner 	return(p->progress);
559*21c1c48aSSascha Wildner }
560*21c1c48aSSascha Wildner 
561*21c1c48aSSascha Wildner void
dfui_payload_free(struct dfui_payload * p)562*21c1c48aSSascha Wildner dfui_payload_free(struct dfui_payload *p)
563*21c1c48aSSascha Wildner {
564*21c1c48aSSascha Wildner 	if (p == NULL)
565*21c1c48aSSascha Wildner 		return;
566*21c1c48aSSascha Wildner 	if (p->form != NULL)
567*21c1c48aSSascha Wildner 		dfui_form_free(p->form);
568*21c1c48aSSascha Wildner 	if (p->progress != NULL)
569*21c1c48aSSascha Wildner 		dfui_progress_free(p->progress);
570*21c1c48aSSascha Wildner 	AURA_FREE(p, dfui_payload);
571*21c1c48aSSascha Wildner }
572*21c1c48aSSascha Wildner 
573*21c1c48aSSascha Wildner /*
574*21c1c48aSSascha Wildner  * Submit the result of a form to the backend.
575*21c1c48aSSascha Wildner  */
576*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_submit(struct dfui_connection * c,struct dfui_response * r)577*21c1c48aSSascha Wildner dfui_fe_submit(struct dfui_connection *c, struct dfui_response *r)
578*21c1c48aSSascha Wildner {
579*21c1c48aSSascha Wildner 	struct aura_buffer *e;
580*21c1c48aSSascha Wildner 	dfui_err_t request_error;
581*21c1c48aSSascha Wildner 
582*21c1c48aSSascha Wildner 	e = aura_buffer_new(16384);
583*21c1c48aSSascha Wildner 	dfui_encode_response(e, r);
584*21c1c48aSSascha Wildner 
585*21c1c48aSSascha Wildner 	dfui_debug("ENCODE<<%s>>\n", aura_buffer_buf(e));
586*21c1c48aSSascha Wildner 	request_error = c->fe_ll_request(c, DFUI_FE_MSG_SUBMIT,
587*21c1c48aSSascha Wildner 	    aura_buffer_buf(e));
588*21c1c48aSSascha Wildner 	/* XXX we should check for READY from the backend? */
589*21c1c48aSSascha Wildner 	aura_buffer_free(e);
590*21c1c48aSSascha Wildner 
591*21c1c48aSSascha Wildner 	return(request_error);
592*21c1c48aSSascha Wildner }
593*21c1c48aSSascha Wildner 
594*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_progress_continue(struct dfui_connection * c)595*21c1c48aSSascha Wildner dfui_fe_progress_continue(struct dfui_connection *c)
596*21c1c48aSSascha Wildner {
597*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
598*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
599*21c1c48aSSascha Wildner }
600*21c1c48aSSascha Wildner 
601*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_progress_cancel(struct dfui_connection * c)602*21c1c48aSSascha Wildner dfui_fe_progress_cancel(struct dfui_connection *c)
603*21c1c48aSSascha Wildner {
604*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_CANCEL, "");
605*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
606*21c1c48aSSascha Wildner }
607*21c1c48aSSascha Wildner 
608*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_confirm_set_global(struct dfui_connection * c)609*21c1c48aSSascha Wildner dfui_fe_confirm_set_global(struct dfui_connection *c)
610*21c1c48aSSascha Wildner {
611*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
612*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
613*21c1c48aSSascha Wildner }
614*21c1c48aSSascha Wildner 
615*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_cancel_set_global(struct dfui_connection * c)616*21c1c48aSSascha Wildner dfui_fe_cancel_set_global(struct dfui_connection *c)
617*21c1c48aSSascha Wildner {
618*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_CANCEL, "");
619*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
620*21c1c48aSSascha Wildner }
621*21c1c48aSSascha Wildner 
622*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_confirm_stop(struct dfui_connection * c)623*21c1c48aSSascha Wildner dfui_fe_confirm_stop(struct dfui_connection *c)
624*21c1c48aSSascha Wildner {
625*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
626*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
627*21c1c48aSSascha Wildner }
628*21c1c48aSSascha Wildner 
629*21c1c48aSSascha Wildner /*
630*21c1c48aSSascha Wildner  * Abort the backend.
631*21c1c48aSSascha Wildner  * Note that you still must call dfui_fe_disconnect after this.
632*21c1c48aSSascha Wildner  */
633*21c1c48aSSascha Wildner dfui_err_t
dfui_fe_abort(struct dfui_connection * c)634*21c1c48aSSascha Wildner dfui_fe_abort(struct dfui_connection *c)
635*21c1c48aSSascha Wildner {
636*21c1c48aSSascha Wildner 	c->fe_ll_request(c, DFUI_FE_MSG_ABORT, "");
637*21c1c48aSSascha Wildner 	return(DFUI_SUCCESS);
638*21c1c48aSSascha Wildner }
639