#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <libaura/mem.h>
#include <libaura/buffer.h>
#include "system.h"
#define NEEDS_DFUI_STRUCTURE_DEFINITIONS
#include "dfui.h"
#undef NEEDS_DFUI_STRUCTURE_DEFINITIONS
#include "encoding.h"
#include "dump.h"
#include "conn_npipe.h"
#include "conn_tcp.h"
struct dfui_connection *
dfui_connection_new(int transport, const char *rendezvous)
{
struct dfui_connection *c = NULL;
if (
#ifdef HAS_NPIPE
transport == DFUI_TRANSPORT_NPIPE ||
#endif
#ifdef HAS_TCP
transport == DFUI_TRANSPORT_TCP ||
#endif
0) {
} else {
return(NULL);
}
if (dfui_debug_file == NULL) {
dfui_debug_file = stderr;
} else {
setvbuf(dfui_debug_file, NULL, _IOLBF, 0);
}
AURA_MALLOC(c, dfui_connection);
c->rendezvous = aura_strdup(rendezvous);
c->transport = transport;
c->ebuf = aura_buffer_new(16384);
c->is_connected = 0;
c->t_data = NULL;
switch (transport) {
#ifdef HAS_NPIPE
case DFUI_TRANSPORT_NPIPE:
AURA_MALLOC(c->t_data, dfui_conn_npipe);
T_NPIPE(c)->in_pipename = NULL;
T_NPIPE(c)->out_pipename = NULL;
T_NPIPE(c)->in = NULL;
T_NPIPE(c)->out = NULL;
c->be_start = dfui_npipe_be_start;
c->be_stop = dfui_npipe_be_stop;
c->be_ll_exchange = dfui_npipe_be_ll_exchange;
c->fe_connect = dfui_npipe_fe_connect;
c->fe_disconnect = dfui_npipe_fe_disconnect;
c->fe_ll_request = dfui_npipe_fe_ll_request;
break;
#endif
#ifdef HAS_TCP
case DFUI_TRANSPORT_TCP:
AURA_MALLOC(c->t_data, dfui_conn_tcp);
T_TCP(c)->listen_sd = -1;
T_TCP(c)->connected_sd = -1;
T_TCP(c)->is_connected = 0;
c->be_start = dfui_tcp_be_start;
c->be_stop = dfui_tcp_be_stop;
c->be_ll_exchange = dfui_tcp_be_ll_exchange;
c->fe_connect = dfui_tcp_fe_connect;
c->fe_disconnect = dfui_tcp_fe_disconnect;
c->fe_ll_request = dfui_tcp_fe_ll_request;
break;
#endif
}
return(c);
}
void
dfui_connection_free(struct dfui_connection *c)
{
if (c == NULL)
return;
switch (c->transport) {
#ifdef HAS_NPIPE
case DFUI_TRANSPORT_NPIPE:
if (T_NPIPE(c) != NULL) {
if (T_NPIPE(c)->in_pipename != NULL)
aura_free(T_NPIPE(c)->in_pipename, "pipename");
if (T_NPIPE(c)->out_pipename != NULL)
aura_free(T_NPIPE(c)->out_pipename, "pipename");
if (T_NPIPE(c)->in != NULL)
fclose(T_NPIPE(c)->in);
if (T_NPIPE(c)->out != NULL)
fclose(T_NPIPE(c)->out);
AURA_FREE(T_NPIPE(c), dfui_conn_npipe);
}
break;
#endif
#ifdef HAS_TCP
case DFUI_TRANSPORT_TCP:
if (T_TCP(c) != NULL) {
AURA_FREE(T_NPIPE(c), dfui_conn_tcp);
}
break;
#endif
}
if (c->rendezvous != NULL)
free(c->rendezvous);
AURA_FREE(c, dfui_connection);
}
int
dfui_be_present_dialog(struct dfui_connection *c, const char *title,
const char *actions, const char *fmt, ...)
{
struct dfui_form *f;
struct dfui_response *r;
va_list args;
char *message;
char action_id[256], action_name[256];
size_t start, end, counter, i;
va_start(args, fmt);
vasprintf(&message, fmt, args);
va_end(args);
f = dfui_form_create("dialog", title, message, "", NULL);
free(message);
start = end = 0;
while (actions[end] != '\0') {
end = start;
while (actions[end] != '|' && actions[end] != '\0')
end++;
if ((end - start) >= 256)
break;
strncpy(action_name, &actions[start], end - start);
action_name[end - start] = '\0';
strcpy(action_id, action_name);
for(i = 0; action_id[i] != '\0'; i++) {
if (action_id[i] == ' ')
action_id[i] = '_';
}
dfui_form_action_add(f, action_id,
dfui_info_new(action_name, "", ""));
start = end + 1;
}
if (!dfui_be_present(c, f, &r)) {
dfui_form_free(f);
dfui_response_free(r);
return(-1);
}
strlcpy(action_name, dfui_response_get_action_id(r), 256);
for(i = 0; action_name[i] != '\0'; i++) {
if (action_name[i] == '_')
action_name[i] = ' ';
}
start = end = 0;
counter = 1;
while (actions[end] != '\0') {
end = start;
while (actions[end] != '|' && actions[end] != '\0')
end++;
if ((end - start) >= 256)
break;
if (strlen(action_name) == (end - start) &&
strncmp(action_name, &actions[start], end - start) == 0) {
break;
}
counter++;
start = end + 1;
}
dfui_form_free(f);
dfui_response_free(r);
return(counter);
}
dfui_err_t
dfui_be_start(struct dfui_connection *c)
{
if (c->is_connected) {
return(DFUI_FAILURE);
} else if (c->be_start(c)) {
c->is_connected = 1;
return(DFUI_SUCCESS);
} else {
return(DFUI_FAILURE);
}
}
dfui_err_t
dfui_be_stop(struct dfui_connection *c)
{
if (!c->is_connected) {
return(DFUI_SUCCESS);
} else if (c->be_stop(c)) {
c->is_connected = 0;
return(DFUI_SUCCESS);
} else {
return(DFUI_FAILURE);
}
}
static struct aura_buffer *
dfui_be_handle_field_changed(struct dfui_connection *c,
struct dfui_form *f)
{
struct aura_buffer *e;
char *field_id, *new_value;
int ret;
e = aura_buffer_new(1024);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
field_id = dfui_decode_string(e);
new_value = dfui_decode_string(e);
aura_buffer_free(e);
dfui_debug("handle changed field: id=`%s', new_value=`%s'\n",
field_id, new_value);
ret = dfui_form_trigger_callbacks(f, field_id, new_value);
free(field_id);
free(new_value);
e = aura_buffer_new(16384);
if (ret == 0) {
dfui_encode_datasets(e, f->dataset_head);
} else {
}
return(e);
}
dfui_err_t
dfui_be_present(struct dfui_connection *c,
struct dfui_form *f, struct dfui_response **r)
{
struct aura_buffer *e;
char msgtype;
e = aura_buffer_new(16384);
dfui_encode_form(e, f);
c->be_ll_exchange(c, DFUI_BE_MSG_PRESENT, aura_buffer_buf(e));
aura_buffer_free(e);
while (1) {
msgtype = aura_buffer_buf(c->ebuf)[0];
if (msgtype == DFUI_FE_MSG_ABORT)
return(DFUI_FAILURE);
if (msgtype == DFUI_FE_MSG_FIELD_CHANGED) {
e = dfui_be_handle_field_changed(c, f);
c->be_ll_exchange(c, DFUI_BE_MSG_FIELD_CHANGED_ACK, aura_buffer_buf(e));
aura_buffer_free(e);
continue;
}
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1,
aura_buffer_len(c->ebuf) - 1);
*r = dfui_decode_response(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
}
}
dfui_err_t
dfui_be_progress_begin(struct dfui_connection *c, struct dfui_progress *pr)
{
struct aura_buffer *e;
e = aura_buffer_new(16384);
dfui_encode_progress(e, pr);
c->be_ll_exchange(c, DFUI_BE_MSG_PROG_BEGIN, aura_buffer_buf(e));
aura_buffer_free(e);
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
return(DFUI_FAILURE);
} else {
return(DFUI_SUCCESS);
}
}
dfui_err_t
dfui_be_progress_update(struct dfui_connection *c,
struct dfui_progress *pr, int *cancelled)
{
struct aura_buffer *e;
e = aura_buffer_new(16384);
dfui_encode_progress(e, pr);
c->be_ll_exchange(c, DFUI_BE_MSG_PROG_UPDATE, aura_buffer_buf(e));
aura_buffer_free(e);
*cancelled = 0;
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_CANCEL) {
*cancelled = 1;
}
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
return(DFUI_FAILURE);
} else {
return(DFUI_SUCCESS);
}
}
dfui_err_t
dfui_be_progress_end(struct dfui_connection *c)
{
c->be_ll_exchange(c, DFUI_BE_MSG_PROG_END, "");
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
return(DFUI_FAILURE);
} else {
return(DFUI_SUCCESS);
}
}
dfui_err_t
dfui_be_set_global_setting(struct dfui_connection *c,
const char *key, const char *value,
int *cancelled)
{
struct aura_buffer *e;
struct dfui_property *p;
e = aura_buffer_new(16384);
p = dfui_property_new(key, value);
dfui_encode_property(e, p);
c->be_ll_exchange(c, DFUI_BE_MSG_SET_GLOBAL, aura_buffer_buf(e));
aura_buffer_free(e);
dfui_property_free(p);
*cancelled = 0;
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_CANCEL) {
*cancelled = 1;
}
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
return(DFUI_FAILURE);
} else {
return(DFUI_SUCCESS);
}
}
dfui_err_t
dfui_fe_connect(struct dfui_connection *c)
{
return(c->fe_connect(c));
}
dfui_err_t
dfui_fe_disconnect(struct dfui_connection *c)
{
dfui_debug("DISCONNECTING<<>>\n");
return(c->fe_disconnect(c));
}
dfui_err_t
dfui_fe_receive(struct dfui_connection *c, char *msgtype, void **payload)
{
struct aura_buffer *e;
c->fe_ll_request(c, DFUI_FE_MSG_READY, "");
*msgtype = aura_buffer_buf(c->ebuf)[0];
switch (*msgtype) {
case DFUI_BE_MSG_PRESENT:
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
*payload = dfui_decode_form(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
case DFUI_BE_MSG_PROG_BEGIN:
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
*payload = dfui_decode_progress(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
case DFUI_BE_MSG_PROG_UPDATE:
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
*payload = dfui_decode_progress(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
case DFUI_BE_MSG_PROG_END:
*payload = NULL;
return(DFUI_SUCCESS);
case DFUI_BE_MSG_SET_GLOBAL:
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
*payload = dfui_decode_property(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
case DFUI_BE_MSG_FIELD_CHANGED_ACK:
e = aura_buffer_new(16384);
aura_buffer_set(e, aura_buffer_buf(c->ebuf) + 1, aura_buffer_len(c->ebuf) - 1);
*payload = dfui_decode_datasets(e);
aura_buffer_free(e);
return(DFUI_SUCCESS);
case DFUI_BE_MSG_STOP:
*payload = NULL;
return(DFUI_SUCCESS);
default:
return(DFUI_FAILURE);
}
}
struct dfui_payload *
dfui_fe_receive_payload(struct dfui_connection *c)
{
char msgtype;
void *v;
struct dfui_payload *payload;
if (!dfui_fe_receive(c, &msgtype, &v)) {
return(NULL);
}
AURA_MALLOC(payload, dfui_payload);
payload->msgtype = msgtype;
payload->form = NULL;
payload->progress = NULL;
switch (msgtype) {
case DFUI_BE_MSG_PRESENT:
payload->form = v;
break;
case DFUI_BE_MSG_PROG_BEGIN:
case DFUI_BE_MSG_PROG_UPDATE:
payload->progress = v;
break;
case DFUI_BE_MSG_SET_GLOBAL:
payload->global_setting = v;
break;
case DFUI_BE_MSG_FIELD_CHANGED_ACK:
payload->datasets = v;
break;
case DFUI_BE_MSG_PROG_END:
case DFUI_BE_MSG_STOP:
break;
}
return(payload);
}
char
dfui_payload_get_msg_type(const struct dfui_payload *p)
{
if (p == NULL)
return(' ');
return(p->msgtype);
}
struct dfui_form *
dfui_payload_get_form(const struct dfui_payload *p)
{
if (p == NULL)
return(NULL);
return(p->form);
}
struct dfui_progress *
dfui_payload_get_progress(const struct dfui_payload *p)
{
if (p == NULL)
return(NULL);
return(p->progress);
}
struct dfui_dataset *
dfui_payload_get_datasets(const struct dfui_payload *p)
{
if (p == NULL)
return(NULL);
return(p->datasets);
}
void
dfui_payload_free(struct dfui_payload *p)
{
if (p == NULL)
return;
if (p->form != NULL)
dfui_form_free(p->form);
if (p->progress != NULL)
dfui_progress_free(p->progress);
if (p->datasets != NULL)
dfui_datasets_free(p->datasets);
AURA_FREE(p, dfui_payload);
}
dfui_err_t
dfui_fe_send(struct dfui_connection *c, char msgtype, struct aura_buffer *e)
{
c->fe_ll_request(c, msgtype, aura_buffer_buf(e));
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_submit(struct dfui_connection *c, struct dfui_response *r)
{
struct aura_buffer *e;
dfui_err_t request_error;
e = aura_buffer_new(16384);
dfui_encode_response(e, r);
dfui_debug("ENCODE<<%s>>\n", aura_buffer_buf(e));
request_error = c->fe_ll_request(c, DFUI_FE_MSG_SUBMIT,
aura_buffer_buf(e));
aura_buffer_free(e);
return(request_error);
}
dfui_err_t
dfui_fe_progress_continue(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_progress_cancel(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_CANCEL, "");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_confirm_set_global(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_cancel_set_global(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_CANCEL, "");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_confirm_stop(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_CONTINUE, "");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_fe_abort(struct dfui_connection *c)
{
c->fe_ll_request(c, DFUI_FE_MSG_ABORT, "");
return(DFUI_SUCCESS);
}