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