Files
2026-08-24 10:03:24 +08:00

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;
}