422 lines
8.9 KiB
C
422 lines
8.9 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <stdint.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "dataserver_client.h"
|
|
#include "dataserver_message.h"
|
|
|
|
#define ds_inf(_fmt_,...) printf("I %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
|
|
#define ds_err(_fmt_,...) printf("E %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
|
|
|
|
static char usage_msg[] ="\"help\" to check the available commands\n";
|
|
|
|
ds_conn_t *server = NULL;
|
|
|
|
static pthread_t read_thread;
|
|
static pthread_t write_thread;
|
|
static int read_active;
|
|
static int write_active;
|
|
|
|
|
|
/*simple hex dump, small data only, !NO BUF OVERFLOW CHECK!*/
|
|
static int d2s(char *s, int ls, uint8_t *buf, size_t size)
|
|
{
|
|
int i = 0;
|
|
char tmp[8];
|
|
int ret;
|
|
int off = 0;
|
|
|
|
s[0] = '\0';
|
|
|
|
/**
|
|
* format: [19 20 21 22/. !"]
|
|
*/
|
|
|
|
for (; i < size; i++) {
|
|
if ((i + 1) < size)
|
|
ret = snprintf(tmp, sizeof(tmp), "%.2x ", buf[i]);
|
|
else
|
|
ret = snprintf(tmp, sizeof(tmp), "%.2x", buf[i]);
|
|
|
|
if ((off + ret + 1) <= ls) {
|
|
memcpy(s + off, tmp, ret + 1);
|
|
off += ret;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < size; i++) {
|
|
uint8_t c = buf[i];
|
|
if (c < 0x20 || c >= 0x7f)
|
|
c = '.';
|
|
|
|
ret = snprintf(tmp, sizeof(tmp), "%c", c);
|
|
|
|
if ((off + ret + 1) <= ls) {
|
|
memcpy(s + off, tmp, ret + 1);
|
|
off += ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void *read_task(void *args)
|
|
{
|
|
ds_conn_t *server = (ds_conn_t *)args;
|
|
|
|
ds_inf("read task started");
|
|
|
|
uint8_t buf[1024];
|
|
|
|
int ret;
|
|
|
|
int last_ret = -100;//suppress the print
|
|
|
|
while (read_active) {
|
|
|
|
ret = dataserver_read_message(server, buf, sizeof(buf), 1000);
|
|
|
|
if (ret == -2) {
|
|
if (ret != last_ret) {
|
|
ds_inf("timeout");
|
|
}
|
|
last_ret = ret;
|
|
continue;
|
|
}
|
|
|
|
last_ret = ret;
|
|
|
|
if (ret == 0)
|
|
continue;
|
|
else if (ret == -1) {
|
|
ds_err("bad parameter");
|
|
continue;
|
|
}
|
|
else if (ret <= -3) {
|
|
ds_err("EOF");
|
|
break;
|
|
}
|
|
|
|
ds_msg_head_t *pmsg = (ds_msg_head_t *)buf;
|
|
|
|
ds_inf("new msg: type(%d) size(%d)", pmsg->type, pmsg->size);
|
|
|
|
{
|
|
/*new message*/
|
|
char chars[1024];
|
|
|
|
switch (pmsg->type) {
|
|
case DS_T_DATA:
|
|
d2s(chars, sizeof(chars), pmsg->body, 32);
|
|
ds_inf("DATA (%d)[%s] ...", pmsg->size, chars);
|
|
break;
|
|
case DS_T_RESP:
|
|
d2s(chars, sizeof(chars), pmsg->body, pmsg->size);
|
|
ds_inf("RESP: [%s]", chars);
|
|
if (pmsg->size > 3) {
|
|
ds_inf("RESP:\n%s", pmsg->body + 3);
|
|
}
|
|
break;
|
|
case DS_T_EVNT:
|
|
d2s(chars, sizeof(chars), pmsg->body, pmsg->size);
|
|
ds_inf("EVNT: [%s]", chars);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
read_active = 0;
|
|
|
|
ds_inf("read task exit");
|
|
return NULL;
|
|
}
|
|
|
|
static int send_cntl_load(ds_conn_t *server, const char *cmd)
|
|
{
|
|
/*
|
|
* The load procedure is:
|
|
*
|
|
* CNTL "load <plug> <size>";
|
|
* while (cnt < size) {
|
|
* DATA bsize;
|
|
* cnt += bsize;
|
|
* }
|
|
*
|
|
*/
|
|
uint8_t buf[1024];
|
|
|
|
ds_msg_head_t *pmsg = (ds_msg_head_t *)buf;
|
|
|
|
char plugin[256];
|
|
|
|
if (sscanf(cmd, "debug_load %s", plugin) != 1) {
|
|
ds_err("bad parameter");
|
|
return -1;
|
|
}
|
|
|
|
int fd = open(plugin, O_RDONLY);
|
|
if (fd < 0) {
|
|
ds_err("file open fail");
|
|
return -1;
|
|
}
|
|
|
|
off_t size = lseek(fd, 0, SEEK_END);
|
|
if (size < 0) {
|
|
ds_err("incorrect plug size");
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
pmsg->size = sprintf((char *)pmsg->body, "%s %ld", cmd, size) + 1;
|
|
pmsg->magic = DS_MAGIC;
|
|
pmsg->type = DS_T_CNTL;
|
|
|
|
int ret = dataserver_write_message(server,
|
|
buf, sizeof(ds_msg_head_t) + pmsg->size);
|
|
|
|
if (ret == 0)
|
|
;
|
|
else if (ret == -1) {
|
|
ds_err("bad parameter");
|
|
}
|
|
else if (ret == -2) {
|
|
ds_inf("timeout");
|
|
}
|
|
else if (ret <= -3) {
|
|
ds_err("FATAL");
|
|
}
|
|
|
|
/*upload the plugin data*/
|
|
pmsg->magic = DS_MAGIC;
|
|
pmsg->type = DS_T_DATA;
|
|
|
|
lseek(fd, 0, SEEK_SET);
|
|
while ((ret = read(fd, pmsg->body,
|
|
sizeof(buf) - sizeof(ds_msg_head_t))) > 0) {
|
|
|
|
pmsg->size = ret;
|
|
|
|
ret = dataserver_write_message(server,
|
|
buf, sizeof(ds_msg_head_t) + ret);
|
|
|
|
if (ret == 0)
|
|
;
|
|
else if (ret == -1) {
|
|
ds_err("bad parameter");
|
|
break;
|
|
}
|
|
else if (ret == -2) {
|
|
ds_inf("timeout");
|
|
}
|
|
else if (ret <= -3) {
|
|
ds_err("FATAL");
|
|
break;
|
|
}
|
|
}
|
|
|
|
close(fd);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int send_cntl(ds_conn_t *server, const char *cmd)
|
|
{
|
|
/*the load is a bit complex, deal separately*/
|
|
char *debug_load_prefix = "debug_load ";
|
|
if (strncmp(cmd, debug_load_prefix,
|
|
strlen(debug_load_prefix)) == 0)
|
|
return send_cntl_load(server, cmd);
|
|
|
|
uint8_t buf[1024];
|
|
|
|
ds_msg_head_t *pmsg = (ds_msg_head_t *)buf;
|
|
|
|
pmsg->magic = DS_MAGIC;
|
|
pmsg->type = DS_T_CNTL;
|
|
pmsg->size = strlen(cmd) + 1;
|
|
|
|
memcpy(pmsg->body, cmd, pmsg->size);
|
|
|
|
int ret = dataserver_write_message(server,
|
|
buf, sizeof(ds_msg_head_t) + pmsg->size);
|
|
|
|
if (ret == 0)
|
|
;
|
|
else if (ret == -1) {
|
|
ds_err("bad parameter");
|
|
}
|
|
else if (ret == -2) {
|
|
ds_inf("timeout");
|
|
}
|
|
else if (ret <= -3) {
|
|
ds_err("FATAL");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void *write_task(void *args)
|
|
{
|
|
ds_conn_t *server = (ds_conn_t *)args;
|
|
|
|
ds_inf("write task started");
|
|
|
|
char buf[512] = {0}, last[512] = {0};
|
|
char *cmd = NULL;
|
|
|
|
while (write_active) {
|
|
ds_inf("%s", usage_msg);
|
|
retry:
|
|
cmd = fgets(buf, sizeof(buf), stdin);
|
|
if (!cmd)
|
|
goto retry;
|
|
|
|
if (!write_active)
|
|
break;
|
|
|
|
if (cmd[0] == '\n' && cmd[1] == '\0' && cmd[0] != last[0])
|
|
cmd = last;
|
|
else
|
|
memcpy(last, cmd, sizeof(last));
|
|
|
|
/*remove the "\n\r"*/
|
|
int len = strlen(cmd);
|
|
|
|
if (len) {
|
|
if (cmd[len - 1] == '\n' || cmd[len - 1] == '\r')
|
|
cmd[len - 1] = '\0';
|
|
if (len > 1) {
|
|
if (cmd[len - 2] == '\n' || cmd[len - 2] == '\r')
|
|
cmd[len - 2] = '\0';
|
|
}
|
|
}
|
|
|
|
ds_inf("send cmd: %s", cmd);
|
|
|
|
int ret = send_cntl(server, cmd);
|
|
|
|
if (ret <= -3)
|
|
break;
|
|
}
|
|
|
|
write_active = 0;
|
|
|
|
ds_inf("write task exit");
|
|
return NULL;
|
|
}
|
|
|
|
static void try_terminate(void)
|
|
{
|
|
int join_read = 0;
|
|
int join_write = 0;
|
|
|
|
if (read_active) {
|
|
read_active = 0;
|
|
join_read = 1;
|
|
}
|
|
|
|
if (write_active) {
|
|
write_active = 0;
|
|
join_write = 1;
|
|
}
|
|
|
|
if (VALID_DS_CONN(server)) {
|
|
dataserver_disconnect(server);
|
|
}
|
|
|
|
if (join_read) {
|
|
ds_inf("read thread join");
|
|
pthread_join(read_thread, NULL);
|
|
ds_inf("read thread joined");
|
|
}
|
|
|
|
if (join_write) {
|
|
ds_inf("write thread join");
|
|
pthread_join(write_thread, NULL);
|
|
ds_inf("write thread joined");
|
|
}
|
|
|
|
if (VALID_DS_CONN(server)) {
|
|
dataserver_destroy(server);
|
|
server = NULL;
|
|
}
|
|
}
|
|
|
|
static void sig_handler(int signo)
|
|
{
|
|
(void)signo;
|
|
|
|
try_terminate();
|
|
exit(0);
|
|
}
|
|
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct in_addr addr;
|
|
uint32_t port;
|
|
int sig = 0;
|
|
|
|
if (argc > 1) {
|
|
if (inet_aton(argv[1], &addr) != 0
|
|
&& sscanf(argv[2], "%i", &port) == 1)
|
|
server = dataserver_connect_ip(addr.s_addr, port);
|
|
} else {
|
|
server = dataserver_connect();
|
|
}
|
|
|
|
if (strstr(argv[0], "sig"))
|
|
sig = 1;
|
|
|
|
if (!VALID_DS_CONN(server)) {
|
|
ds_err("connect to dataserver failed.");
|
|
return -1;
|
|
}
|
|
|
|
if (sig) {
|
|
signal(SIGINT, sig_handler);
|
|
signal(SIGTERM, sig_handler);
|
|
}
|
|
|
|
read_active = 1;
|
|
write_active = 1;
|
|
|
|
pthread_create(&read_thread, NULL, read_task, server);
|
|
pthread_create(&write_thread, NULL, write_task, server);
|
|
|
|
while (1) {
|
|
if (!read_active) {
|
|
ds_inf("read thread join");
|
|
pthread_join(read_thread, NULL);
|
|
ds_inf("read thread joined");
|
|
}
|
|
|
|
if (!write_active) {
|
|
ds_inf("write thread join");
|
|
pthread_join(write_thread, NULL);
|
|
ds_inf("write thread joined");
|
|
}
|
|
|
|
if (!read_active || !write_active) {
|
|
try_terminate();
|
|
break;
|
|
}
|
|
|
|
sleep(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|