#include "system.h"
#ifdef HAS_TCP
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libaura/buffer.h>
#define NEEDS_DFUI_STRUCTURE_DEFINITIONS
#include "dfui.h"
#undef NEEDS_DFUI_STRUCTURE_DEFINITIONS
#include "encoding.h"
#include "conn_tcp.h"
#include "dump.h"
dfui_err_t
dfui_tcp_be_start(struct dfui_connection *c)
{
struct sockaddr_in servaddr;
int server_port;
int tru = 1;
server_port = atoi(c->rendezvous);
errno = 0;
if ((T_TCP(c)->listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return(DFUI_FAILURE);
dfui_debug("LISTEN_SOCKET<<%d>>\n", T_TCP(c)->listen_sd);
if (setsockopt(T_TCP(c)->listen_sd, SOL_SOCKET, SO_REUSEADDR,
&tru, sizeof(tru)) == -1) {
return(DFUI_FAILURE);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(server_port);
switch(inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr)) {
case 0:
warnx("inet_pton(): address not parseable");
return(DFUI_FAILURE);
case 1:
break;
default:
warn("inet_pton()");
return(DFUI_FAILURE);
}
if (bind(T_TCP(c)->listen_sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
warn("bind()");
return(DFUI_FAILURE);
}
dfui_debug("BOUND_ON<<%d>>\n", T_TCP(c)->listen_sd);
if (listen(T_TCP(c)->listen_sd, 0) == -1)
return(DFUI_FAILURE);
dfui_debug("LISTENING_ON<<%d>>\n", T_TCP(c)->listen_sd);
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_be_stop(struct dfui_connection *c)
{
if (dfui_tcp_be_ll_exchange(c, DFUI_BE_MSG_STOP, "")) {
close(T_TCP(c)->listen_sd);
close(T_TCP(c)->connected_sd);
fclose(T_TCP(c)->stream);
return(DFUI_SUCCESS);
} else
return(DFUI_FAILURE);
}
dfui_err_t
dfui_tcp_be_ll_exchange(struct dfui_connection *c, char msgtype, const char *msg)
{
char *fmsg;
fmsg = malloc(strlen(msg) + 2);
fmsg[0] = msgtype;
strcpy(fmsg + 1, msg);
dfui_tcp_be_ll_receive(c);
if (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_ABORT) {
free(fmsg);
return(DFUI_FAILURE);
}
do {
dfui_tcp_be_ll_reply(c, fmsg);
dfui_tcp_be_ll_receive(c);
} while (aura_buffer_buf(c->ebuf)[0] == DFUI_FE_MSG_READY);
fmsg[0] = DFUI_BE_MSG_READY;
fmsg[1] = '\0';
dfui_tcp_be_ll_reply(c, fmsg);
free(fmsg);
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_be_ll_receive(struct dfui_connection *c)
{
int length;
char *buf;
top:
if (!T_TCP(c)->is_connected) {
dfui_debug("NOT_CONNECTED,ACCEPTING_ON<<%d>>\n", T_TCP(c)->listen_sd);
T_TCP(c)->connected_sd = accept(T_TCP(c)->listen_sd, NULL, NULL);
dfui_debug("ACCEPTED<<%d>>\n", T_TCP(c)->connected_sd);
T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+");
T_TCP(c)->is_connected = 1;
} else {
dfui_debug("ALREADY_CONNECTED<<>>\n");
}
dfui_debug("WAITING<<>>\n");
if (read_data(T_TCP(c)->stream, (char *)&length, sizeof(length)) == -1) {
dfui_debug("LOST_THEM<<>>\n");
fclose(T_TCP(c)->stream);
T_TCP(c)->is_connected = 0;
goto top;
}
buf = malloc(length + 1);
if (read_data(T_TCP(c)->stream, buf, length) == -1) {
dfui_debug("LOST_THEM<<>>\n");
fclose(T_TCP(c)->stream);
T_TCP(c)->is_connected = 0;
goto top;
}
aura_buffer_set(c->ebuf, buf, length);
free(buf);
dfui_debug("RECEIVED<<%s>>\n", aura_buffer_buf(c->ebuf));
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_be_ll_reply(struct dfui_connection *c, const char *fmsg)
{
int length;
dfui_debug("SEND<<%s>>\n", fmsg);
length = strlen(fmsg);
write_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
write_data(T_TCP(c)->stream, fmsg, length);
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_fe_connect(struct dfui_connection *c)
{
struct sockaddr_in servaddr;
int server_port;
int connected = 0;
server_port = atoi(c->rendezvous);
while (!connected) {
errno = 0;
if ((T_TCP(c)->connected_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
return(DFUI_FAILURE);
}
dfui_debug("CLIENT_SOCKET<<%d>>\n", T_TCP(c)->connected_sd);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(server_port);
inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
if (connect(T_TCP(c)->connected_sd, (struct sockaddr *)&servaddr,
sizeof(servaddr)) == 0) {
dfui_debug("CONNECTED<<>>\n");
connected = 1;
} else {
dfui_debug("NO_CONNECT<<>>\n");
close(T_TCP(c)->connected_sd);
sleep(1);
}
}
T_TCP(c)->stream = fdopen(T_TCP(c)->connected_sd, "r+");
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_fe_disconnect(struct dfui_connection *c)
{
close(T_TCP(c)->connected_sd);
return(DFUI_SUCCESS);
}
dfui_err_t
dfui_tcp_fe_ll_request(struct dfui_connection *c, char msgtype, const char *msg)
{
char *fmsg, *buf;
int length, result;
if (c == NULL || T_TCP(c)->connected_sd == -1)
return(DFUI_FAILURE);
fmsg = malloc(strlen(msg) + 2);
fmsg[0] = msgtype;
strcpy(fmsg + 1, msg);
dfui_debug("SEND<<%s>>\n", fmsg);
length = strlen(fmsg);
result = write_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
dfui_debug("result<<%d>>\n", result);
result = write_data(T_TCP(c)->stream, (char *)fmsg, length);
dfui_debug("result<<%d>>\n", result);
dfui_debug("WAITING<<>>\n");
result = read_data(T_TCP(c)->stream, (char *)&length, sizeof(length));
dfui_debug("result<<%d>>\n", result);
buf = malloc(length + 1);
result = read_data(T_TCP(c)->stream, buf, length);
dfui_debug("result<<%d>>\n", result);
aura_buffer_set(c->ebuf, buf, length);
free(buf);
dfui_debug("RECV<<%s>>\n", aura_buffer_buf(c->ebuf));
free(fmsg);
return(DFUI_SUCCESS);
}
int
read_data(FILE *f, char *buf, int n)
{
int bcount;
int br;
bcount = 0;
br = 0;
while (bcount < n) {
if ((br = fread(buf, 1, n - bcount, f)) > 0) {
dfui_debug("READ_BYTES<<%d>>\n", br);
bcount += br;
buf += br;
} else if (br <= 0) {
dfui_debug("read_data_error<<%d>>\n", br);
return(-1);
}
}
return(bcount);
}
int
write_data(FILE *f, const char *buf, int n)
{
int bcount;
int bw;
bcount = 0;
bw = 0;
while (bcount < n) {
if ((bw = fwrite(buf, 1, n - bcount, f)) > 0) {
dfui_debug("WROTE_BYTES<<%d>>\n", bw);
bcount += bw;
buf += bw;
} else if (bw <= 0) {
dfui_debug("write_data_error<<%d>>\n", bw);
return(-1);
}
}
return(bcount);
}
#endif