#include #include #include #include #include #include #include #include #include #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 "; * 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 #include #include 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; }