From e125b2f2b30c56b358e049f2b556fc1dfb4e743d Mon Sep 17 00:00:00 2001 From: SchumyHao Date: Tue, 25 Aug 2015 23:04:00 +0800 Subject: [PATCH 1/3] want to use thread pool to handle client, use epoll to accept client. --- wrtnode/uixo_console/src/main.c | 72 +++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git a/wrtnode/uixo_console/src/main.c b/wrtnode/uixo_console/src/main.c index e14095b..6dc3b1b 100644 --- a/wrtnode/uixo_console/src/main.c +++ b/wrtnode/uixo_console/src/main.c @@ -21,6 +21,7 @@ Data :2015.08.13 #include #include #include +#include #include "list.h" #include "uixo_console.h" @@ -37,6 +38,7 @@ long uixo_console_calloc_count = 0; struct uixo_client { struct list_head list; int fd; + pid_t pid; }; /* @@ -75,7 +77,6 @@ static int uixo_console_create_socket(void) serveraddr.sin_family=AF_INET; serveraddr.sin_port=htons(PORT); serveraddr.sin_addr.s_addr=htonl(INADDR_ANY); - /*用在多播的时候,也经常使用SO_REUSEADDR,也是为了防止机器出现意外,导致端口没有释放,而使重启后的绑定失败*/ setsockopt(ss, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); ret = bind(ss, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)); if(ret < 0) { @@ -87,21 +88,14 @@ static int uixo_console_create_socket(void) return ss; } -static int uixo_console_select_fds(fd_set* pfds) +static int uixo_console_host_select(void) { + fd_set sreadfds; int max_sockfds = socketfd; - struct uixo_client* tmp_client = NULL; - FD_ZERO(pfds); - FD_SET(socketfd, pfds); - list_for_each_entry(tmp_client, &uixo_client_head, list) { - if(0 != tmp_client->fd) { - FD_SET(tmp_client->fd, pfds); - max_sockfds = MAX(max_sockfds, tmp_client->fd); - PR_DEBUG("%s: Add fd = %d to select, max_sockfds = %d.\n", __func__, tmp_client->fd, max_sockfds); - } - } - return select(max_sockfds+1, pfds, NULL, NULL, NULL); + FD_ZERO(&sreadfds); + FD_SET(socketfd, &sreadfds); + return select(max_sockfds+1, &sreadfds, NULL, NULL, NULL); } static int uixo_console_client_remove(const int fd) @@ -139,6 +133,7 @@ static int uixo_console_handle_host(void) { int sc = 0; struct uixo_client* client = NULL; + pid_t pid; if(connct_num == BACKLOG) { printf("%s: max connetction arrive, bye\n", __func__); @@ -159,7 +154,46 @@ static int uixo_console_handle_host(void) client->fd = sc; list_add_tail(&client->list, &uixo_client_head); connct_num++; - return 0; + + pid = fork(); + if(pid < 0) { + printf("%s: host fork client(%d) handler error.\n", __func__, sc); + return -1; + } + else if(pid > 0) { /* host(parent) */ + client->pid = pid; + PR_DEBUG("%s: client(%d) handler forked.\n", __func__, sc); + return 0; + } + else { /* client(child) */ + if(uixo_console_handle_client(sc) < 0) { + printf("%s: client handle failed.\n", __func__); + return -1; + } + exit(0); + } +} + +static void handle_client_exit(void) +{ + int client_ret; + pid_t client_pid; + + client_pid = wait(&client_ret); + if(0 != client_ret) { + printf("%s: client handler(%d) exit with error %d.\n", __func__, (int)client_pid, client_ret); + } + else { + struct uixo_client* tmp_client; + + list_for_each_entry(tmp_client, &uixo_client_head, list) { + if(client_pid == tmp_client->pid) { + PR_DEBUG("%s: client(%d) removing.\n", __func__, tmp_client->fd) + uixo_console_client_remove(tmp_client->fd); + } + } + printf("%s: cannot find client in list. client handle pid=%d.\n", __func__, (int)client_pid); + } } /* @@ -173,11 +207,11 @@ int main(int argc, char* argv[]) return -1; } + signal(SIGCHLD, handle_client_exit); + while(1) { - fd_set sreadfds; int ret = 0; - - ret = uixo_console_select_fds(&sreadfds); + ret = uixo_console_host_select(); if(ret < 0) { /* select error */ printf("%s: select fail\n", __func__); break; @@ -187,6 +221,7 @@ int main(int argc, char* argv[]) continue; } else { /* can read */ +#if 0 struct uixo_client* tmp_client = NULL; struct uixo_client* tmp_client_next = NULL; @@ -200,12 +235,15 @@ int main(int argc, char* argv[]) } } if(FD_ISSET(socketfd, &sreadfds)) { +#endif PR_DEBUG("%s: host got data.\n", __func__); if(uixo_console_handle_host() < 0) { printf("%s: hose handle failed.\n", __func__); continue; } +#if 0 } +#endif } } uixo_console_port_close(); From 2c2d1c2abb3cd8d6258c2f77097d68067a8f4aac Mon Sep 17 00:00:00 2001 From: SchumyHao Date: Thu, 27 Aug 2015 00:04:33 +0800 Subject: [PATCH 2/3] can work in 7.8s for 1000 times. --- wrtnode/uixo_client/src/client_console.c | 18 +- wrtnode/uixo_console/src/HandleMsg.c | 167 ++----- wrtnode/uixo_console/src/HandlePort.c | 236 +++++----- wrtnode/uixo_console/src/Makefile | 2 +- wrtnode/uixo_console/src/main.c | 132 +++--- wrtnode/uixo_console/src/thpool.c | 557 +++++++++++++++++++++++ wrtnode/uixo_console/src/thpool.h | 164 +++++++ wrtnode/uixo_console/src/uixo_console.h | 15 +- 8 files changed, 974 insertions(+), 317 deletions(-) create mode 100644 wrtnode/uixo_console/src/thpool.c create mode 100644 wrtnode/uixo_console/src/thpool.h diff --git a/wrtnode/uixo_client/src/client_console.c b/wrtnode/uixo_client/src/client_console.c index dc5b6ad..869b29d 100644 --- a/wrtnode/uixo_client/src/client_console.c +++ b/wrtnode/uixo_client/src/client_console.c @@ -28,7 +28,7 @@ static int socketfd; static void quit_signal_handler(int a) { - send(socketfd, "exit", sizeof("exit"), 0); +// send(socketfd, "exit", sizeof("exit"), 0); close(socketfd); exit(0); } @@ -78,16 +78,16 @@ int main(int argc,char *argv[]) if(string_len > MAX_UIXO_MSG_LEN) { printf("%s: input string too long. len=%d.\n", __func__, string_len); } - sprintf(msg.head, "%04d", string_len); - if(send(socketfd, (char*)&msg, string_len+UIXO_HEAD_LEN, 0) < 0) { - printf("%s: send %s error\n", __func__, msg.head); +// sprintf(msg.head, "%04d", string_len); + if(send(socketfd, msg.data, string_len, 0) < 0) { + printf("%s: send %s error\n", __func__, msg.data); } } { if(rttimes == 0){ - if(send(socketfd, "exit", sizeof("exit"), 0) < 0) { - printf("send error\n"); - } +// if(send(socketfd, "exit", sizeof("exit"), 0) < 0) { +// printf("send error\n"); +// } close(socketfd); } else { @@ -110,8 +110,8 @@ int main(int argc,char *argv[]) printf("%s",buff); } - send(socketfd, "exit", sizeof("exit"), 0); - close(socketfd); +// send(socketfd, "exit", sizeof("exit"), 0); + close(socketfd); } } diff --git a/wrtnode/uixo_console/src/HandleMsg.c b/wrtnode/uixo_console/src/HandleMsg.c index a27242f..6c7078d 100644 --- a/wrtnode/uixo_console/src/HandleMsg.c +++ b/wrtnode/uixo_console/src/HandleMsg.c @@ -43,7 +43,7 @@ int handle_msg_del_msglist(struct list_head* msg_head) return 0; } -static int handle_msg_format_data(char* dest, const char* src) +int handle_msg_format_data(char* dest, const char* src) { int len = 0; if((NULL == dest) || (NULL == src)) { @@ -97,27 +97,13 @@ static int handle_msg_format_data(char* dest, const char* src) return len; } -int handle_msg_transmit_data(uixo_port_t* port, uixo_message_t* msg) +int handle_msg_transmit_data(uixo_port_t* port, const char* data, int len) { - char tx_data[msg->len+1]; - int data_len = 0; - - if((NULL == port) || (NULL == port->port) || (NULL == msg)) { - printf("%s: input data is NULL\n", __func__); - return -1; - } - data_len = handle_msg_format_data(tx_data, msg->data); - if(data_len <= 0) { - printf("%s: data len = %d\n", __func__, data_len); - return -1; - } - PR_DEBUG("%s: TX=%s, LEN=%d\n", __func__, tx_data, data_len); - if(strncmp(port->name, "/dev/spiS", strlen("/dev/spiS")) == 0) { struct spi_mt7688* sm = (struct spi_mt7688*)(port->port); int writen = 0; - PR_DEBUG("%s: send to port data = %s and len = %d\n", __func__, tx_data, data_len); - writen = sm->write(sm, tx_data, data_len); + PR_DEBUG("%s: send to port data = %s and len = %d\n", __func__, data, len); + writen = sm->write(sm, data, len); if(writen < 0) { printf("%s: send message failed\n", __func__); return -1; @@ -126,8 +112,8 @@ int handle_msg_transmit_data(uixo_port_t* port, uixo_message_t* msg) else { struct posix_serial* ps = (struct posix_serial*)port->port; int writen = 0; - PR_DEBUG("%s: send to port data = %s and len = %d\n", __func__, tx_data, data_len); - writen = ps->write(ps, tx_data, data_len); + PR_DEBUG("%s: send to port data = %s and len = %d\n", __func__, data, len); + writen = ps->write(ps, data, len); if(writen < 0) { printf("%s: send message failed\n", __func__); return -1; @@ -136,78 +122,41 @@ int handle_msg_transmit_data(uixo_port_t* port, uixo_message_t* msg) return 0; } -static void* _handle_msg_receive_data_thread(void* arg) +int handle_msg_receive_data(uixo_port_t* port, uixo_message_t* msg) { - uixo_port_t* port = (uixo_port_t*)arg; - uixo_message_t* msg = NULL; - - pthread_mutex_lock(&port->port_mutex); - PR_DEBUG("%s: take port lock.\n", __func__); - port->rx_thread_is_run = 1; - pthread_mutex_unlock(&port->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - PR_DEBUG("%s: thread(%d) running.\n", __func__, (int)port->rx_msg_thread); - PR_DEBUG("%s: got port(%s) in receive thread.\n", __func__, port->name); - - while(!(pthread_mutex_lock(&port->port_mutex) || - list_empty(&port->msghead))) { - PR_DEBUG("%s: take port lock.\n", __func__); - msg = list_first_entry(&port->msghead, typeof(*msg), list); - list_del(&msg->list); - pthread_mutex_unlock(&port->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - char rx_data[MAX_UIXO_MSG_LEN]; - - PR_DEBUG("%s: got a message from list, rttimes=%d\n", __func__, msg->rttimes); - if(UIXO_MSG_ALWAYS_WAIT_MSG == msg->rttimes) { - while(1) { - int len = 0; - len = handle_port_read_line(port, rx_data, MAX_UIXO_MSG_LEN*sizeof(*rx_data)); - if(0 != len) { - PR_DEBUG("%s", rx_data); - if(send(msg->socketfd, rx_data, len, 0) < 0) { - printf("%s: send to client error.\n", __func__); - } - PR_DEBUG("%s: send %s to client(fd=%d).\n", __func__, rx_data, msg->socketfd); + char rx_data[MAX_UIXO_MSG_LEN]; + + if(UIXO_MSG_ALWAYS_WAIT_MSG == msg->rttimes) { + while(1) { + int len = 0; + len = handle_port_read_line(port, rx_data, MAX_UIXO_MSG_LEN*sizeof(*rx_data)); + if(0 != len) { + PR_DEBUG("%s", rx_data); + if(send(msg->socketfd, rx_data, len, 0) < 0) { + printf("%s: send to client error.\n", __func__); + return -1; } + PR_DEBUG("%s: send %s to client(fd=%d) in always wait.\n", __func__, rx_data, msg->socketfd); } } - else if (0 < msg->rttimes) { - while(msg->rttimes--) { - int len = 0; - len = handle_port_read_line(port, rx_data, MAX_UIXO_MSG_LEN*sizeof(*rx_data)); - if(0 != len) { - PR_DEBUG("%s", rx_data); - if(send(msg->socketfd, rx_data, len, 0) < 0) { - printf("%s: send to client error.\n", __func__); - } + } + else if (0 < msg->rttimes) { + while(msg->rttimes--) { + int len = 0; + len = handle_port_read_line(port, rx_data, MAX_UIXO_MSG_LEN*sizeof(*rx_data)); + if(0 != len) { + PR_DEBUG("%s", rx_data); + if(send(msg->socketfd, rx_data, len, 0) < 0) { + printf("%s: send to client error.\n", __func__); + return -1; } + PR_DEBUG("%s: send %s to client(fd=%d).\n", __func__, rx_data, msg->socketfd); } - handle_msg_free_msg(msg); - } - else { - printf("%s: WARNING: got rttimes=0 in rx thread. port(%s), client(%d)\n", - __func__, port->name, msg->socketfd); - handle_msg_free_msg(msg); } } - if(list_empty(&port->msghead)) { - port->rx_thread_is_run = 0; - pthread_mutex_unlock(&port->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - PR_DEBUG("%s: WARNING: port(%s) message list is empty.\n", __func__, port->name); - } else { - printf("%s: take port(%s) lock error.\n", __func__, port->name); - } - return 0; -} - -int handle_msg_receive_data(uixo_port_t* port) -{ - if(pthread_create(&port->rx_msg_thread, NULL, _handle_msg_receive_data_thread, port) < 0) { - printf("%s: create port(%s) rx message thread failed.\n", __func__, port->name); - return -1; + printf("%s: WARNING: got rttimes=0 in rx thread. port(%s), client(%d)\n", + __func__, port->name, msg->socketfd); } return 0; } @@ -274,11 +223,12 @@ static int handle_msg_parse_msg(const char* data, const ssize_t len, uixo_messag { char* word = NULL; char* sep = ":"; + char* last = NULL; ret = 0; - for(word = strtok(valid_data, sep); + for(word = strtok_r(valid_data, sep, &last); word; - word = strtok(NULL, sep)) { + word = strtok_r(NULL, sep, &last)) { PR_DEBUG("%s: strtok word = %s\n", __func__, word); switch(ret) { case 0: ret += sscanf(word, "%ld", &msg->time); break; @@ -313,49 +263,28 @@ static int handle_msg_parse_msg(const char* data, const ssize_t len, uixo_messag int handle_msg_resolve_msg(const int fd) { uixo_message_t msg; - char head[UIXO_HEAD_LEN] = {0}; + char read_buf[MAX_UIXO_MSG_LEN]; ssize_t readn = 0; - int ret = 0; PR_DEBUG("%s: client(fd = %d) send data in.\n", __func__, fd); msg.socketfd = fd; - readn = read(fd, head, UIXO_HEAD_LEN); - PR_DEBUG("%s: got message head = %s, len = %ld.\n", __func__, head, readn); - if(readn != UIXO_HEAD_LEN) { - printf("%s: read client head error. data = %s return = %ld\n", __func__, head, readn); + readn = read(fd, read_buf, MAX_UIXO_MSG_LEN); + if(readn < 0) { + printf("%s: read client fd error. return = %ld\n", __func__, readn); return -1; } + read_buf[readn] = '\0'; + PR_DEBUG("%s: read data = %s, length = %ld\n", __func__, read_buf, readn); - if(0 == strcmp(head, "exit")) { - PR_DEBUG("%s: read client exit message.\n", __func__); - return UIXO_MSG_CLIENT_EXIT_MSG; + if(handle_msg_parse_msg(read_buf, readn, &msg) != UIXO_ERR_OK) { + printf("%s: uixo message parse err.\n", __func__); + return -1; } - else { - int buf_len = atoi(head); - char read_buf[buf_len+1]; - - if(0 == buf_len) { - printf("%s: client send data length is 0.\n", __func__); - return -1; - } - readn = read(fd, read_buf, buf_len); - if((readn != buf_len)||(readn == -1)) { - printf("%s: read client fd error. return = %ld\n", __func__, readn); - return -1; - } - read_buf[readn] = '\0'; - PR_DEBUG("%s: read data = %s, length = %ld\n", __func__, read_buf, readn); - - if(handle_msg_parse_msg(read_buf, readn, &msg) != UIXO_ERR_OK) { - printf("%s: uixo message parse err.\n", __func__); - return -1; - } - if(handle_port_fun_types(&msg) < 0) { - printf("%s: parse message error.\n", __func__); - return -1; - } + if(handle_port_fun_types(&msg) < 0) { + printf("%s: parse message error.\n", __func__); + return -1; } - return ret; + return 0; } diff --git a/wrtnode/uixo_console/src/HandlePort.c b/wrtnode/uixo_console/src/HandlePort.c index 0e6c6cb..116ba38 100644 --- a/wrtnode/uixo_console/src/HandlePort.c +++ b/wrtnode/uixo_console/src/HandlePort.c @@ -21,7 +21,12 @@ Data :2015.06.03 #include "spi_mt7688.h" #include "uixo_console.h" -static LIST_HEAD(uixo_ports_head); +struct uixo_port_list_head { + struct list_head head; + pthread_rwlock_t rwlock; + unsigned int port_num; +}; +static struct uixo_port_list_head uixo_ports_head; /* default set serial */ static void handle_port_uixo_default_set(uixo_port_t* port, const char* port_name, const int baudrate) @@ -113,18 +118,39 @@ static int handle_port_uixo_port_open(uixo_port_t* port) return ret; } -/* create a port */ -uixo_port_t* handle_port_mkport(const char* port_name, const int baudrate) +static uixo_port_t* find_port_on_list(const char* port_name) { - uixo_port_t* port = NULL; uixo_port_t* tmp_p = NULL; - list_for_each_entry(tmp_p, &uixo_ports_head, list) { - PR_DEBUG("%s: find port(%s) on port list.\n", __func__, tmp_p->name); + PR_DEBUG("%s: take port read lock.\n", __func__); + pthread_rwlock_rdlock(&uixo_ports_head.rwlock); + list_for_each_entry(tmp_p, &uixo_ports_head.head, list) { + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port read lock.\n", __func__); if(strcmp(tmp_p->name, port_name) == 0) { - printf("%s: Port(%s) already exists\n", __func__, port_name); - return NULL; + return tmp_p; } + PR_DEBUG("%s: take port read lock.\n", __func__); + pthread_rwlock_rdlock(&uixo_ports_head.rwlock); + } + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port read lock.\n", __func__); + + return NULL; +} + +static inline int is_port_on_list(const char* port_name) +{ + return (NULL==find_port_on_list(port_name))? 0: 1; +} + +/* create a port */ +uixo_port_t* handle_port_mkport(const char* port_name, const int baudrate) +{ + uixo_port_t* port = NULL; + + if(is_port_on_list(port_name)) { + printf("%s: Port(%s) already exists\n", __func__, port_name); } port = (uixo_port_t*)uixo_console_calloc(1, sizeof(uixo_port_t)); @@ -133,125 +159,91 @@ uixo_port_t* handle_port_mkport(const char* port_name, const int baudrate) printf("%s: Failed to calloc uixo_port_t!\n", __func__); } handle_port_uixo_default_set(port, port_name, baudrate); - INIT_LIST_HEAD(&port->msghead); - pthread_mutex_init(&port->port_mutex, NULL); + pthread_mutex_init(&port->mutex, NULL); if(handle_port_uixo_port_open(port) < 0) { printf("%s: open port error\n", __func__); return NULL; } - list_add_tail(&port->list, &uixo_ports_head); + + PR_DEBUG("%s: take port write lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_ports_head.rwlock); + list_add_tail(&port->list, &uixo_ports_head.head); + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port write lock.\n", __func__); return port; } /* delete a port */ int handle_port_delport(const char* port_name) { - int has_port = 0; - uixo_port_t* tmp_p = NULL; uixo_message_t* msg = NULL; + uixo_port_t* tmp_p = NULL; - list_for_each_entry(tmp_p, &uixo_ports_head, list) { - if(strcmp(tmp_p->name, port_name) == 0) { - has_port = 1; - break; - } + if((tmp_p=find_port_on_list(port_name)) == NULL) { + printf("%s: no port(%s) on list. delport error.\n", __func__, port_name); + return -1; } - if(has_port) { - PR_DEBUG("%s: start to delete port = %s.\n", __func__, tmp_p->name); - list_del(&tmp_p->list); - if(0 == strncmp(tmp_p->name, "/dev/tty", strlen("/dev/tty"))) { - struct posix_serial* ps = tmp_p->port; - ps->close(ps); - uixo_console_free(tmp_p->baudrate); - uixo_console_free(tmp_p->name); - PR_DEBUG("%s: finished delete port = %s.\n", __func__, port_name); - } - else if(0 == strncmp(tmp_p->name, "/dev/spiS", strlen("/dev/spiS"))) { - struct spi_mt7688* sm = NULL; + PR_DEBUG("%s: start to delete port = %s.\n", __func__, tmp_p->name); + PR_DEBUG("%s: take port write lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_ports_head.rwlock); + list_del(&tmp_p->list); + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port write lock.\n", __func__); + if(0 == strncmp(tmp_p->name, "/dev/tty", strlen("/dev/tty"))) { + struct posix_serial* ps = tmp_p->port; - sm->close(sm); - uixo_console_free(tmp_p->baudrate); - uixo_console_free(tmp_p->name); - PR_DEBUG("%s: finished delete port = %s.\n", __func__, port_name); - } - pthread_mutex_lock(&tmp_p->port_mutex); - PR_DEBUG("%s: take port lock.\n", __func__); - if((0 != tmp_p->rx_msg_thread) && (0 == pthread_kill(tmp_p->rx_msg_thread, 0))) { - pthread_cancel(tmp_p->rx_msg_thread); - PR_DEBUG("%s: send cancel to rx thread(%d)\n", __func__, (int)tmp_p->rx_msg_thread); - pthread_join(tmp_p->rx_msg_thread, NULL); - PR_DEBUG("%s: rx thread(%d) exited.\n", __func__, (int)tmp_p->rx_msg_thread); - } - handle_msg_del_msglist(&tmp_p->msghead); - pthread_mutex_unlock(&tmp_p->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - pthread_mutex_destroy(&tmp_p->port_mutex); - uixo_console_free(tmp_p); - return 0; + ps->close(ps); + uixo_console_free(tmp_p->baudrate); + uixo_console_free(tmp_p->name); + PR_DEBUG("%s: finished delete port = %s.\n", __func__, port_name); } - else { - printf("%s: no port(%s) on list. delport error.\n", __func__, port_name); - return -1; + else if(0 == strncmp(tmp_p->name, "/dev/spiS", strlen("/dev/spiS"))) { + struct spi_mt7688* sm = NULL; + + sm->close(sm); + uixo_console_free(tmp_p->baudrate); + uixo_console_free(tmp_p->name); + PR_DEBUG("%s: finished delete port = %s.\n", __func__, port_name); } + pthread_mutex_destroy(&tmp_p->mutex); + uixo_console_free(tmp_p); + return 0; } int handle_port_hlport(uixo_message_t* msg) { uixo_port_t* port = NULL; - list_for_each_entry(port, &uixo_ports_head, list) { - if(strcmp(port->name, msg->port_name) == 0) { - PR_DEBUG("%s: find port = %s.\n", __func__, msg->port_name); - if(msg->rttimes <= UIXO_MSG_DELET_MSG) { - PR_DEBUG("%s: del msg\n", __func__); - if(handle_msg_del_msg(msg) < 0) { - printf("%s: port(%s) delet message error\n", __func__, port->name); - return -1; - } - return 0; - } - else { - if(handle_msg_transmit_data(port, msg) < 0) { - printf("%s: port(%s) transmit data fail.\n", __func__, port->name); - return -1; - } - if(msg->rttimes != 0) { - uixo_message_t* msg_bak = NULL; - msg_bak = (uixo_message_t*)uixo_console_malloc(sizeof(uixo_message_t)); - if(NULL == msg_bak) { - printf("%s: rttimes>0, but calloc copy message error.\n", __func__); - return -1; - } - memcpy(msg_bak, msg, sizeof(uixo_message_t)); - PR_DEBUG("%s: need to receive data, add to message list\n", __func__); - pthread_mutex_lock(&port->port_mutex); - PR_DEBUG("%s: take port lock.\n", __func__); - list_add_tail(&msg_bak->list, &port->msghead); - if(!port->rx_thread_is_run) { - pthread_mutex_unlock(&port->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - if(0 != port->rx_msg_thread) { - pthread_join(port->rx_msg_thread, NULL); - PR_DEBUG("%s: thread(%d) exit.\n", __func__, (int)port->rx_msg_thread); - } - if(handle_msg_receive_data(port) < 0) { - printf("%s: port(%s) receive data fail.\n", __func__, port->name); - return -1; - } - PR_DEBUG("%s: client(%d) open a rx thread for port(%s).\n", - __func__, msg_bak->socketfd, port->name); - } - else { - pthread_mutex_unlock(&port->port_mutex); - PR_DEBUG("%s: release port lock.\n", __func__); - } - } - return 0; - } + char tx_data[msg->len+1]; + int data_len = 0; + + if((port=find_port_on_list(msg->port_name)) == NULL) { + printf("%s: no port(%s) on list. hlport error.\n", __func__, port->name); + return -1; + } + + data_len = handle_msg_format_data(tx_data, msg->data); + if(data_len <= 0) { + printf("%s: data len = %d\n", __func__, data_len); + return -1; + } + PR_DEBUG("%s: TX=%s, LEN=%d\n", __func__, tx_data, data_len); + + PR_DEBUG("%s: take port(%s) mutex.\n", __func__, port->name); + pthread_mutex_lock(&port->mutex); + if(handle_msg_transmit_data(port, tx_data, data_len) < 0) { + printf("%s: port(%s) transmit data fail.\n", __func__, port->name); + return -1; + } + if(msg->rttimes != 0) { + if(handle_msg_receive_data(port, msg) < 0) { + printf("%s: port(%s) receive data fail.\n", __func__, port->name); + return -1; } } - printf("%s: the port(%s) does not exist\n", __func__, msg->port_name); - return -1; + pthread_mutex_unlock(&port->mutex); + PR_DEBUG("%s: release port(%s) mutex.\n", __func__, port->name); + return 0; } int handle_port_read_line(uixo_port_t* port, char* rx_data, const int len) @@ -259,6 +251,12 @@ int handle_port_read_line(uixo_port_t* port, char* rx_data, const int len) int readn = 0; char* ptr = rx_data; + struct posix_serial* ps = port->port; + readn = ps->read(ps, rx_data, 4); + ps->flush_input(ps); + return readn; + + if((NULL == port) || (NULL == rx_data)) { printf("%s: input NULL.\n", __func__); return 0; @@ -279,6 +277,7 @@ int handle_port_read_line(uixo_port_t* port, char* rx_data, const int len) ptr++; readn++; if('\n' == ch) { + *ptr = '\0'; return readn; } } @@ -302,6 +301,7 @@ int handle_port_read_line(uixo_port_t* port, char* rx_data, const int len) ptr++; readn++; if('\n' == ch) { + *ptr = '\0'; return readn; } } @@ -324,7 +324,11 @@ void handle_port_remove_port_list(void) { uixo_port_t* tmp_p = NULL; - list_for_each_entry(tmp_p, &uixo_ports_head, list) { + PR_DEBUG("%s: take port write lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_ports_head.rwlock); + list_for_each_entry(tmp_p, &uixo_ports_head.head, list) { + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port write lock.\n", __func__); PR_DEBUG("%s: start to delete port = %s.\n", __func__, tmp_p->name); list_del(&tmp_p->list); if(0 == strncmp(tmp_p->name, "/dev/tty", strlen("/dev/tty"))) { @@ -341,20 +345,23 @@ void handle_port_remove_port_list(void) uixo_console_free(tmp_p->baudrate); uixo_console_free(tmp_p->name); } - handle_msg_del_msglist(&tmp_p->msghead); uixo_console_free(tmp_p); + PR_DEBUG("%s: take port write lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_ports_head.rwlock); } + pthread_rwlock_unlock(&uixo_ports_head.rwlock); + PR_DEBUG("%s: release port write lock.\n", __func__); } int handle_port_fun_types(uixo_message_t* msg) { - /*create a port*/ - if(strcmp(msg->fn_name, "mkport") == 0) { - PR_DEBUG("%s: mkport, name=%s, baudrate = %d\n", __func__, msg->port_name, msg->port_baudrate); - if(NULL == handle_port_mkport(msg->port_name, msg->port_baudrate)) { - printf("%s: mkport error.\n", __func__); + /*create a port*/ + if(strcmp(msg->fn_name, "mkport") == 0) { + PR_DEBUG("%s: mkport, name=%s, baudrate = %d\n", __func__, msg->port_name, msg->port_baudrate); + if(NULL == handle_port_mkport(msg->port_name, msg->port_baudrate)) { + printf("%s: mkport error.\n", __func__); return -1; - } + } return 0; } /* delete a port */ @@ -379,3 +386,10 @@ int handle_port_fun_types(uixo_message_t* msg) return -1; } } + +void handle_port_init_port_list_head(void) +{ + INIT_LIST_HEAD(&uixo_ports_head.head); + pthread_rwlock_init(&uixo_ports_head.rwlock, NULL); + uixo_ports_head.port_num = 0; +} diff --git a/wrtnode/uixo_console/src/Makefile b/wrtnode/uixo_console/src/Makefile index 1d89b7b..44355ef 100644 --- a/wrtnode/uixo_console/src/Makefile +++ b/wrtnode/uixo_console/src/Makefile @@ -1,6 +1,6 @@ PROGS = uixo_console -OBJS = main.o serial.o serial_posix.o HandlePort.o HandleMsg.o spi.o spi_mt7688.o +OBJS = main.o serial.o serial_posix.o HandlePort.o HandleMsg.o spi.o spi_mt7688.o thpool.o LDFLAGS += -lpthread all: $(PROGS) $(PROGS): $(OBJS) diff --git a/wrtnode/uixo_console/src/main.c b/wrtnode/uixo_console/src/main.c index 6dc3b1b..0e4e80d 100644 --- a/wrtnode/uixo_console/src/main.c +++ b/wrtnode/uixo_console/src/main.c @@ -25,11 +25,13 @@ Data :2015.08.13 #include "list.h" #include "uixo_console.h" +#include "thpool.h" #define MAX(a,b) (((a) > (b))? (a): (b)) #define MIN(x,y) (((x) < (y))? (x): (y)) #define PORT (8000) #define BACKLOG (2000) +#define THREAD_POOL_NUM (10) #if DugPrintg long uixo_console_calloc_count = 0; @@ -38,15 +40,19 @@ long uixo_console_calloc_count = 0; struct uixo_client { struct list_head list; int fd; - pid_t pid; +}; + +struct uixo_client_list_head { + struct list_head head; + pthread_rwlock_t rwlock; + unsigned int connct_num; }; /* static variables */ -static LIST_HEAD(uixo_client_head); +static struct uixo_client_list_head uixo_client_head; static int socketfd; -static int connct_num; /* static functions @@ -98,47 +104,50 @@ static int uixo_console_host_select(void) return select(max_sockfds+1, &sreadfds, NULL, NULL, NULL); } -static int uixo_console_client_remove(const int fd) +static int uixo_console_client_remove(struct uixo_client* client) { - struct uixo_client* tmp_client = NULL; - list_for_each_entry(tmp_client, &uixo_client_head, list) { - if(fd == tmp_client->fd) { - list_del(&tmp_client->list); - close(tmp_client->fd); - uixo_console_free(tmp_client); - connct_num--; - PR_DEBUG("%s: client removed.\n", __func__); - return 0; - } - } - printf("%s: no client(%d) in client list, removed failed.\n", __func__, fd); - return -1; + PR_DEBUG("%s: take client head lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_client_head.rwlock); + list_del(&client->list); + uixo_client_head.connct_num--; + pthread_rwlock_unlock(&uixo_client_head.rwlock); + PR_DEBUG("%s: release client head lock.\n", __func__); + close(client->fd); + uixo_console_free(client); + PR_DEBUG("%s: client removed.\n", __func__); + return 0; } -static int uixo_console_handle_client(const int fd) +static void uixo_console_handle_client(void* arg) { + struct uixo_client* client = (struct uixo_client*)arg; int ret = 0; - ret = handle_msg_resolve_msg(fd); + printf("TIME: client(%d) start handling %d.\n", client->fd, (int)clock()); + ret = handle_msg_resolve_msg(client->fd); if(ret < 0) { - if(UIXO_MSG_CLIENT_EXIT_MSG == ret) { - return uixo_console_client_remove(fd); - } printf("%s: read invalid message.\n", __func__); - return -1; } - return 0; + PR_DEBUG("%s: removing client(%d).\n", __func__, client->fd); + printf("TIME: client(%d) handled %d.\n", client->fd, (int)clock()); + uixo_console_client_remove(client); } -static int uixo_console_handle_host(void) +static int uixo_console_handle_host(threadpool pool) { int sc = 0; struct uixo_client* client = NULL; pid_t pid; - if(connct_num == BACKLOG) { + PR_DEBUG("%s: take client head lock.\n", __func__); + pthread_rwlock_rdlock(&uixo_client_head.rwlock); + if(uixo_client_head.connct_num == BACKLOG) { + pthread_rwlock_unlock(&uixo_client_head.rwlock); + PR_DEBUG("%s: release client head lock.\n", __func__); printf("%s: max connetction arrive, bye\n", __func__); return -1; } + pthread_rwlock_unlock(&uixo_client_head.rwlock); + PR_DEBUG("%s: release client head lock.\n", __func__); sc = accept(socketfd, NULL, NULL); if(sc < 0) { @@ -146,54 +155,24 @@ static int uixo_console_handle_host(void) return -1; } PR_DEBUG("%s: client accept\n", __func__); + printf("TIME: got client(%d) %d.\n", sc, (int)clock()); client = (struct uixo_client*)uixo_console_malloc(sizeof(*client)); if(NULL == client) { printf("%s: client calloc error.\n", __func__); } INIT_LIST_HEAD(&client->list); client->fd = sc; - list_add_tail(&client->list, &uixo_client_head); - connct_num++; + PR_DEBUG("%s: take client head write lock.\n", __func__); + pthread_rwlock_wrlock(&uixo_client_head.rwlock); + list_add_tail(&client->list, &uixo_client_head.head); + uixo_client_head.connct_num++; + pthread_rwlock_unlock(&uixo_client_head.rwlock); + PR_DEBUG("%s: release client head lock.\n", __func__); - pid = fork(); - if(pid < 0) { - printf("%s: host fork client(%d) handler error.\n", __func__, sc); - return -1; - } - else if(pid > 0) { /* host(parent) */ - client->pid = pid; - PR_DEBUG("%s: client(%d) handler forked.\n", __func__, sc); - return 0; - } - else { /* client(child) */ - if(uixo_console_handle_client(sc) < 0) { - printf("%s: client handle failed.\n", __func__); - return -1; - } - exit(0); - } -} + thpool_add_work(pool, (void*)uixo_console_handle_client, client); + PR_DEBUG("%s: add client(%d) to work queue.\n", __func__, sc); -static void handle_client_exit(void) -{ - int client_ret; - pid_t client_pid; - - client_pid = wait(&client_ret); - if(0 != client_ret) { - printf("%s: client handler(%d) exit with error %d.\n", __func__, (int)client_pid, client_ret); - } - else { - struct uixo_client* tmp_client; - - list_for_each_entry(tmp_client, &uixo_client_head, list) { - if(client_pid == tmp_client->pid) { - PR_DEBUG("%s: client(%d) removing.\n", __func__, tmp_client->fd) - uixo_console_client_remove(tmp_client->fd); - } - } - printf("%s: cannot find client in list. client handle pid=%d.\n", __func__, (int)client_pid); - } + return 0; } /* @@ -201,14 +180,26 @@ static void handle_client_exit(void) */ int main(int argc, char* argv[]) { + threadpool pool; + + if(3 == argc) { + pool = thpool_init(atoi(argv[2])); + } + else { + pool = thpool_init(THREAD_POOL_NUM); + } + + INIT_LIST_HEAD(&uixo_client_head.head); + pthread_rwlock_init(&uixo_client_head.rwlock, NULL); + uixo_client_head.connct_num = 0; + handle_port_init_port_list_head(); + socketfd = uixo_console_create_socket(); if(socketfd < 0) { printf("%s: Bcreate socket failed.\n", __func__); return -1; } - signal(SIGCHLD, handle_client_exit); - while(1) { int ret = 0; ret = uixo_console_host_select(); @@ -237,7 +228,7 @@ int main(int argc, char* argv[]) if(FD_ISSET(socketfd, &sreadfds)) { #endif PR_DEBUG("%s: host got data.\n", __func__); - if(uixo_console_handle_host() < 0) { + if(uixo_console_handle_host(pool) < 0) { printf("%s: hose handle failed.\n", __func__); continue; } @@ -247,5 +238,8 @@ int main(int argc, char* argv[]) } } uixo_console_port_close(); + thpool_wait(pool); + thpool_destroy(pool); + return 0; } diff --git a/wrtnode/uixo_console/src/thpool.c b/wrtnode/uixo_console/src/thpool.c new file mode 100644 index 0000000..f85e947 --- /dev/null +++ b/wrtnode/uixo_console/src/thpool.c @@ -0,0 +1,557 @@ +/* ******************************** + * Author: Johan Hanssen Seferidis + * License: MIT + * Description: Library providing a threading pool where you can add + * work. For usage, check the thpool.h file or README.md + * + *//** @file thpool.h *//* + * + ********************************/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "thpool.h" + +#ifdef THPOOL_DEBUG +#define THPOOL_DEBUG 1 +#else +#define THPOOL_DEBUG 0 +#endif + +#define MAX_NANOSEC 999999999 +#define CEIL(X) ((X-(int)(X)) > 0 ? (int)(X+1) : (int)(X)) + +static volatile int threads_keepalive; +static volatile int threads_on_hold; + + + + + +/* ========================== STRUCTURES ============================ */ + + +/* Binary semaphore */ +typedef struct bsem { + pthread_mutex_t mutex; + pthread_cond_t cond; + int v; +} bsem; + + +/* Job */ +typedef struct job{ + struct job* prev; /* pointer to previous job */ + void* (*function)(void* arg); /* function pointer */ + void* arg; /* function's argument */ +} job; + + +/* Job queue */ +typedef struct jobqueue{ + pthread_mutex_t rwmutex; /* used for queue r/w access */ + job *front; /* pointer to front of queue */ + job *rear; /* pointer to rear of queue */ + bsem *has_jobs; /* flag as binary semaphore */ + int len; /* number of jobs in queue */ +} jobqueue; + + +/* Thread */ +typedef struct thread{ + int id; /* friendly id */ + pthread_t pthread; /* pointer to actual thread */ + struct thpool_* thpool_p; /* access to thpool */ +} thread; + + +/* Threadpool */ +typedef struct thpool_{ + thread** threads; /* pointer to threads */ + volatile int num_threads_alive; /* threads currently alive */ + volatile int num_threads_working; /* threads currently working */ + pthread_mutex_t thcount_lock; /* used for thread count etc */ + jobqueue* jobqueue_p; /* pointer to the job queue */ +} thpool_; + + + + + +/* ========================== PROTOTYPES ============================ */ + + +static void thread_init(thpool_* thpool_p, struct thread** thread_p, int id); +static void* thread_do(struct thread* thread_p); +static void thread_hold(); +static void thread_destroy(struct thread* thread_p); + +static int jobqueue_init(thpool_* thpool_p); +static void jobqueue_clear(thpool_* thpool_p); +static void jobqueue_push(thpool_* thpool_p, struct job* newjob_p); +static struct job* jobqueue_pull(thpool_* thpool_p); +static void jobqueue_destroy(thpool_* thpool_p); + +static void bsem_init(struct bsem *bsem_p, int value); +static void bsem_reset(struct bsem *bsem_p); +static void bsem_post(struct bsem *bsem_p); +static void bsem_post_all(struct bsem *bsem_p); +static void bsem_wait(struct bsem *bsem_p); + + + + + +/* ========================== THREADPOOL ============================ */ + + +/* Initialise thread pool */ +struct thpool_* thpool_init(int num_threads){ + + threads_on_hold = 0; + threads_keepalive = 1; + + if ( num_threads < 0){ + num_threads = 0; + } + + /* Make new thread pool */ + thpool_* thpool_p; + thpool_p = (struct thpool_*)malloc(sizeof(struct thpool_)); + if (thpool_p == NULL){ + fprintf(stderr, "thpool_init(): Could not allocate memory for thread pool\n"); + return NULL; + } + thpool_p->num_threads_alive = 0; + thpool_p->num_threads_working = 0; + + /* Initialise the job queue */ + if (jobqueue_init(thpool_p) == -1){ + fprintf(stderr, "thpool_init(): Could not allocate memory for job queue\n"); + free(thpool_p); + return NULL; + } + + /* Make threads in pool */ + thpool_p->threads = (struct thread**)malloc(num_threads * sizeof(struct thread)); + if (thpool_p->threads == NULL){ + fprintf(stderr, "thpool_init(): Could not allocate memory for threads\n"); + jobqueue_destroy(thpool_p); + free(thpool_p->jobqueue_p); + free(thpool_p); + return NULL; + } + + pthread_mutex_init(&(thpool_p->thcount_lock), NULL); + + /* Thread init */ + int n; + for (n=0; nthreads[n], n); + if (THPOOL_DEBUG) + printf("THPOOL_DEBUG: Created thread %d in pool \n", n); + } + + /* Wait for threads to initialize */ + while (thpool_p->num_threads_alive != num_threads) {} + + return thpool_p; +} + + +/* Add work to the thread pool */ +int thpool_add_work(thpool_* thpool_p, void *(*function_p)(void*), void* arg_p){ + job* newjob; + + newjob=(struct job*)malloc(sizeof(struct job)); + if (newjob==NULL){ + fprintf(stderr, "thpool_add_work(): Could not allocate memory for new job\n"); + return -1; + } + + /* add function and argument */ + newjob->function=function_p; + newjob->arg=arg_p; + + /* add job to queue */ + pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex); + jobqueue_push(thpool_p, newjob); + pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex); + + return 0; +} + + +/* Wait until all jobs have finished */ +void thpool_wait(thpool_* thpool_p){ + + /* Continuous polling */ + double timeout = 1.0; + time_t start, end; + double tpassed = 0.0; + time (&start); + while (tpassed < timeout && + (thpool_p->jobqueue_p->len || thpool_p->num_threads_working)) + { + time (&end); + tpassed = difftime(end,start); + } + + /* Exponential polling */ + long init_nano = 1; /* MUST be above 0 */ + long new_nano; + double multiplier = 1.01; + int max_secs = 20; + + struct timespec polling_interval; + polling_interval.tv_sec = 0; + polling_interval.tv_nsec = init_nano; + + while (thpool_p->jobqueue_p->len || thpool_p->num_threads_working) + { + nanosleep(&polling_interval, NULL); + if ( polling_interval.tv_sec < max_secs ){ + new_nano = CEIL(polling_interval.tv_nsec * multiplier); + polling_interval.tv_nsec = new_nano % MAX_NANOSEC; + if ( new_nano > MAX_NANOSEC ) { + polling_interval.tv_sec ++; + } + } + else break; + } + + /* Fall back to max polling */ + while (thpool_p->jobqueue_p->len || thpool_p->num_threads_working){ + sleep(max_secs); + } +} + + +/* Destroy the threadpool */ +void thpool_destroy(thpool_* thpool_p){ + + volatile int threads_total = thpool_p->num_threads_alive; + + /* End each thread 's infinite loop */ + threads_keepalive = 0; + + /* Give one second to kill idle threads */ + double TIMEOUT = 1.0; + time_t start, end; + double tpassed = 0.0; + time (&start); + while (tpassed < TIMEOUT && thpool_p->num_threads_alive){ + bsem_post_all(thpool_p->jobqueue_p->has_jobs); + time (&end); + tpassed = difftime(end,start); + } + + /* Poll remaining threads */ + while (thpool_p->num_threads_alive){ + bsem_post_all(thpool_p->jobqueue_p->has_jobs); + sleep(1); + } + + /* Job queue cleanup */ + jobqueue_destroy(thpool_p); + free(thpool_p->jobqueue_p); + + /* Deallocs */ + int n; + for (n=0; n < threads_total; n++){ + thread_destroy(thpool_p->threads[n]); + } + free(thpool_p->threads); + free(thpool_p); +} + + +/* Pause all threads in threadpool */ +void thpool_pause(thpool_* thpool_p) { + int n; + for (n=0; n < thpool_p->num_threads_alive; n++){ + pthread_kill(thpool_p->threads[n]->pthread, SIGUSR1); + } +} + + +/* Resume all threads in threadpool */ +void thpool_resume(thpool_* thpool_p) { + threads_on_hold = 0; +} + + + + + +/* ============================ THREAD ============================== */ + + +/* Initialize a thread in the thread pool + * + * @param thread address to the pointer of the thread to be created + * @param id id to be given to the thread + * + */ +static void thread_init (thpool_* thpool_p, struct thread** thread_p, int id){ + + *thread_p = (struct thread*)malloc(sizeof(struct thread)); + if (thread_p == NULL){ + fprintf(stderr, "thpool_init(): Could not allocate memory for thread\n"); + exit(1); + } + + (*thread_p)->thpool_p = thpool_p; + (*thread_p)->id = id; + + pthread_create(&(*thread_p)->pthread, NULL, (void *)thread_do, (*thread_p)); + pthread_detach((*thread_p)->pthread); + +} + + +/* Sets the calling thread on hold */ +static void thread_hold () { + threads_on_hold = 1; + while (threads_on_hold){ + sleep(1); + } +} + + +/* What each thread is doing +* +* In principle this is an endless loop. The only time this loop gets interuppted is once +* thpool_destroy() is invoked or the program exits. +* +* @param thread thread that will run this function +* @return nothing +*/ +static void* thread_do(struct thread* thread_p){ + + /* Assure all threads have been created before starting serving */ + thpool_* thpool_p = thread_p->thpool_p; + + /* Register signal handler */ + struct sigaction act; + act.sa_handler = thread_hold; + if (sigaction(SIGUSR1, &act, NULL) == -1) { + fprintf(stderr, "thread_do(): cannot handle SIGUSR1"); + } + + /* Mark thread as alive (initialized) */ + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_alive += 1; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + while(threads_keepalive){ + + bsem_wait(thpool_p->jobqueue_p->has_jobs); + + if (threads_keepalive){ + + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_working++; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + /* Read job from queue and execute it */ + void*(*func_buff)(void* arg); + void* arg_buff; + job* job_p; + pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex); + job_p = jobqueue_pull(thpool_p); + pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex); + if (job_p) { + func_buff = job_p->function; + arg_buff = job_p->arg; + func_buff(arg_buff); + free(job_p); + } + + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_working--; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + } + } + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_alive --; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + return NULL; +} + + +/* Frees a thread */ +static void thread_destroy (thread* thread_p){ + free(thread_p); +} + + + + + +/* ============================ JOB QUEUE =========================== */ + + +/* Initialize queue */ +static int jobqueue_init(thpool_* thpool_p){ + + thpool_p->jobqueue_p = (struct jobqueue*)malloc(sizeof(struct jobqueue)); + if (thpool_p->jobqueue_p == NULL){ + return -1; + } + thpool_p->jobqueue_p->len = 0; + thpool_p->jobqueue_p->front = NULL; + thpool_p->jobqueue_p->rear = NULL; + + thpool_p->jobqueue_p->has_jobs = (struct bsem*)malloc(sizeof(struct bsem)); + if (thpool_p->jobqueue_p->has_jobs == NULL){ + return -1; + } + + pthread_mutex_init(&(thpool_p->jobqueue_p->rwmutex), NULL); + bsem_init(thpool_p->jobqueue_p->has_jobs, 0); + + return 0; +} + + +/* Clear the queue */ +static void jobqueue_clear(thpool_* thpool_p){ + + while(thpool_p->jobqueue_p->len){ + free(jobqueue_pull(thpool_p)); + } + + thpool_p->jobqueue_p->front = NULL; + thpool_p->jobqueue_p->rear = NULL; + bsem_reset(thpool_p->jobqueue_p->has_jobs); + thpool_p->jobqueue_p->len = 0; + +} + + +/* Add (allocated) job to queue + * + * Notice: Caller MUST hold a mutex + */ +static void jobqueue_push(thpool_* thpool_p, struct job* newjob){ + + newjob->prev = NULL; + + switch(thpool_p->jobqueue_p->len){ + + case 0: /* if no jobs in queue */ + thpool_p->jobqueue_p->front = newjob; + thpool_p->jobqueue_p->rear = newjob; + break; + + default: /* if jobs in queue */ + thpool_p->jobqueue_p->rear->prev = newjob; + thpool_p->jobqueue_p->rear = newjob; + + } + thpool_p->jobqueue_p->len++; + + bsem_post(thpool_p->jobqueue_p->has_jobs); +} + + +/* Get first job from queue(removes it from queue) + * + * Notice: Caller MUST hold a mutex + */ +static struct job* jobqueue_pull(thpool_* thpool_p){ + + job* job_p; + job_p = thpool_p->jobqueue_p->front; + + switch(thpool_p->jobqueue_p->len){ + + case 0: /* if no jobs in queue */ + break; + + case 1: /* if one job in queue */ + thpool_p->jobqueue_p->front = NULL; + thpool_p->jobqueue_p->rear = NULL; + thpool_p->jobqueue_p->len = 0; + break; + + default: /* if >1 jobs in queue */ + thpool_p->jobqueue_p->front = job_p->prev; + thpool_p->jobqueue_p->len--; + /* more than one job in queue -> post it */ + bsem_post(thpool_p->jobqueue_p->has_jobs); + + } + + return job_p; +} + + +/* Free all queue resources back to the system */ +static void jobqueue_destroy(thpool_* thpool_p){ + jobqueue_clear(thpool_p); + free(thpool_p->jobqueue_p->has_jobs); +} + + + + + +/* ======================== SYNCHRONISATION ========================= */ + + +/* Init semaphore to 1 or 0 */ +static void bsem_init(bsem *bsem_p, int value) { + if (value < 0 || value > 1) { + fprintf(stderr, "bsem_init(): Binary semaphore can take only values 1 or 0"); + exit(1); + } + pthread_mutex_init(&(bsem_p->mutex), NULL); + pthread_cond_init(&(bsem_p->cond), NULL); + bsem_p->v = value; +} + + +/* Reset semaphore to 0 */ +static void bsem_reset(bsem *bsem_p) { + bsem_init(bsem_p, 0); +} + + +/* Post to at least one thread */ +static void bsem_post(bsem *bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + bsem_p->v = 1; + pthread_cond_signal(&bsem_p->cond); + pthread_mutex_unlock(&bsem_p->mutex); +} + + +/* Post to all threads */ +static void bsem_post_all(bsem *bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + bsem_p->v = 1; + pthread_cond_broadcast(&bsem_p->cond); + pthread_mutex_unlock(&bsem_p->mutex); +} + + +/* Wait on semaphore until semaphore has value 0 */ +static void bsem_wait(bsem* bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + while (bsem_p->v != 1) { + pthread_cond_wait(&bsem_p->cond, &bsem_p->mutex); + } + bsem_p->v = 0; + pthread_mutex_unlock(&bsem_p->mutex); +} diff --git a/wrtnode/uixo_console/src/thpool.h b/wrtnode/uixo_console/src/thpool.h new file mode 100644 index 0000000..ab3063b --- /dev/null +++ b/wrtnode/uixo_console/src/thpool.h @@ -0,0 +1,164 @@ +/********************************** + * @author Johan Hanssen Seferidis + * License: MIT + * + **********************************/ + +#ifndef _THPOOL_ +#define _THPOOL_ + + + + + +/* =================================== API ======================================= */ + + +typedef struct thpool_* threadpool; + + +/** + * @brief Initialize threadpool + * + * Initializes a threadpool. This function will not return untill all + * threads have initialized successfully. + * + * @example + * + * .. + * threadpool thpool; //First we declare a threadpool + * thpool = thpool_init(4); //then we initialize it to 4 threads + * .. + * + * @param num_threads number of threads to be created in the threadpool + * @return threadpool created threadpool on success, + * NULL on error + */ +threadpool thpool_init(int num_threads); + + +/** + * @brief Add work to the job queue + * + * Takes an action and its argument and adds it to the threadpool's job queue. + * If you want to add to work a function with more than one arguments then + * a way to implement this is by passing a pointer to a structure. + * + * NOTICE: You have to cast both the function and argument to not get warnings. + * + * @example + * + * void print_num(int num){ + * printf("%d\n", num); + * } + * + * int main() { + * .. + * int a = 10; + * thpool_add_work(thpool, (void*)print_num, (void*)a); + * .. + * } + * + * @param threadpool threadpool to which the work will be added + * @param function_p pointer to function to add as work + * @param arg_p pointer to an argument + * @return nothing + */ +int thpool_add_work(threadpool, void *(*function_p)(void*), void* arg_p); + + +/** + * @brief Wait for all queued jobs to finish + * + * Will wait for all jobs - both queued and currently running to finish. + * Once the queue is empty and all work has completed, the calling thread + * (probably the main program) will continue. + * + * Smart polling is used in wait. The polling is initially 0 - meaning that + * there is virtually no polling at all. If after 1 seconds the threads + * haven't finished, the polling interval starts growing exponentially + * untill it reaches max_secs seconds. Then it jumps down to a maximum polling + * interval assuming that heavy processing is being used in the threadpool. + * + * @example + * + * .. + * threadpool thpool = thpool_init(4); + * .. + * // Add a bunch of work + * .. + * thpool_wait(thpool); + * puts("All added work has finished"); + * .. + * + * @param threadpool the threadpool to wait for + * @return nothing + */ +void thpool_wait(threadpool); + + +/** + * @brief Pauses all threads immediately + * + * The threads will be paused no matter if they are idle or working. + * The threads return to their previous states once thpool_resume + * is called. + * + * While the thread is being paused, new work can be added. + * + * @example + * + * threadpool thpool = thpool_init(4); + * thpool_pause(thpool); + * .. + * // Add a bunch of work + * .. + * thpool_resume(thpool); // Let the threads start their magic + * + * @param threadpool the threadpool where the threads should be paused + * @return nothing + */ +void thpool_pause(threadpool); + + +/** + * @brief Unpauses all threads if they are paused + * + * @example + * .. + * thpool_pause(thpool); + * sleep(10); // Delay execution 10 seconds + * thpool_resume(thpool); + * .. + * + * @param threadpool the threadpool where the threads should be unpaused + * @return nothing + */ +void thpool_resume(threadpool); + + +/** + * @brief Destroy the threadpool + * + * This will wait for the currently active threads to finish and then 'kill' + * the whole threadpool to free up memory. + * + * @example + * int main() { + * threadpool thpool1 = thpool_init(2); + * threadpool thpool2 = thpool_init(2); + * .. + * thpool_destroy(thpool1); + * .. + * return 0; + * } + * + * @param threadpool the threadpool to destroy + * @return nothing + */ +void thpool_destroy(threadpool); + + + + +#endif diff --git a/wrtnode/uixo_console/src/uixo_console.h b/wrtnode/uixo_console/src/uixo_console.h index 5089d29..d0688c2 100644 --- a/wrtnode/uixo_console/src/uixo_console.h +++ b/wrtnode/uixo_console/src/uixo_console.h @@ -19,7 +19,7 @@ /* const define */ -#define MAX_UIXO_MSG_LEN (4096) +#define MAX_UIXO_MSG_LEN (1024) #define UIXO_HEAD_LEN (5) /* @@ -72,11 +72,8 @@ typedef struct { } uixo_message_t; typedef struct { - struct list_head list; - struct list_head msghead; - pthread_t rx_msg_thread; - int rx_thread_is_run; - pthread_mutex_t port_mutex; + struct list_head list; + pthread_mutex_t mutex; /* uixo message head */ char* rx_head; @@ -164,10 +161,12 @@ int handle_port_hlport(uixo_message_t* msg); void handle_port_remove_port_list(void); int handle_port_read_line(uixo_port_t* port, char* rx_data, const int len); int handle_port_fun_types(uixo_message_t* msg); +void handle_port_init_port_list_head(void); int handle_msg_del_msg(uixo_message_t* msg); int handle_msg_del_msglist(struct list_head* msg_head); -int handle_msg_transmit_data(uixo_port_t* port, uixo_message_t* msg); -int handle_msg_receive_data(uixo_port_t* port); +int handle_msg_transmit_data(uixo_port_t* port, const char* data, int len); +int handle_msg_receive_data(uixo_port_t* port, uixo_message_t* msg); int handle_msg_resolve_msg(const int fd); +int handle_msg_format_data(char* dest, const char* src); #endif From 2910a7eae8ee499be1eb94a8fba6ee6e8f2b23af Mon Sep 17 00:00:00 2001 From: lijpsummer Date: Tue, 22 Sep 2015 12:04:16 +0000 Subject: [PATCH 3/3] Add WRTnode tools-box --- wrtnode/wrtbox/Makefile | 52 +++++ wrtnode/wrtbox/README.md | 12 ++ wrtnode/wrtbox/src/Config.h | 23 +++ wrtnode/wrtbox/src/Makefile | 24 +++ wrtnode/wrtbox/src/applets.c | 108 ++++++++++ wrtnode/wrtbox/src/applets.h | 23 +++ wrtnode/wrtbox/src/dnsclient.c | 314 ++++++++++++++++++++++++++++++ wrtnode/wrtbox/src/get_ip.c | 79 ++++++++ wrtnode/wrtbox/src/hellowrt.c | 18 ++ wrtnode/wrtbox/src/is_intf_up.c | 77 ++++++++ wrtnode/wrtbox/src/wait_intf_up.c | 98 ++++++++++ wrtnode/wrtbox/src/wrtbox.c | 87 +++++++++ wrtnode/wrtbox/src/wrtbox.h | 77 ++++++++ 13 files changed, 992 insertions(+) create mode 100644 wrtnode/wrtbox/Makefile create mode 100644 wrtnode/wrtbox/README.md create mode 100644 wrtnode/wrtbox/src/Config.h create mode 100644 wrtnode/wrtbox/src/Makefile create mode 100644 wrtnode/wrtbox/src/applets.c create mode 100644 wrtnode/wrtbox/src/applets.h create mode 100644 wrtnode/wrtbox/src/dnsclient.c create mode 100644 wrtnode/wrtbox/src/get_ip.c create mode 100644 wrtnode/wrtbox/src/hellowrt.c create mode 100644 wrtnode/wrtbox/src/is_intf_up.c create mode 100644 wrtnode/wrtbox/src/wait_intf_up.c create mode 100644 wrtnode/wrtbox/src/wrtbox.c create mode 100644 wrtnode/wrtbox/src/wrtbox.h diff --git a/wrtnode/wrtbox/Makefile b/wrtnode/wrtbox/Makefile new file mode 100644 index 0000000..dc8aa0d --- /dev/null +++ b/wrtnode/wrtbox/Makefile @@ -0,0 +1,52 @@ +############################################## +# wrtbox is a Swiss Army knife for WRTnode +# WRTnode's busybox +# This file is part of wrtbox. +# Author: 39514004@qq.com (huamanlou,alais name intel inside) +# +# This library is free software; under the terms of the GPL +# +############################################## +include $(TOPDIR)/rules.mk +# Nameand release number of this package + +PKG_NAME:=wrtbox +PKG_VERSION:=0.1 +PKG_RELEASE:=1 +PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME) +include $(INCLUDE_DIR)/package.mk +define Package/wrtbox + CATEGORY:=WRTnode + TITLE:=wrtbox-- The Swiss Army Knife of WRTnode +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Package/wrtbox/install + $(INSTALL_DIR) $(1)/bin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/wrtbox $(1)/bin/ + ln -fs wrtbox $(1)/bin/dnsclient + ln -fs wrtbox $(1)/bin/get_ip + ln -fs wrtbox $(1)/bin/is_intf_up + ln -fs wrtbox $(1)/bin/wait_intf_up + ln -fs wrtbox $(1)/bin/hellowrt +endef + +define Package/$(PKG_NAME)/postinst + #!/bin/sh + # check if we are on real system + if [ -z "$${IPKG_INSTROOT}" ]; then + echo "ln -fs command!" + ln -fs /bin/wrtbox /bin/dnsclient + ln -fs /bin/wrtbox /bin/get_ip + ln -fs /bin/wrtbox /bin/is_intf_up + ln -fs /bin/wrtbox /bin/wait_intf_up + ln -fs /bin/wrtbox /bin/hellowrt + fi + exit 0 +endef + +$(eval $(call BuildPackage,wrtbox)) diff --git a/wrtnode/wrtbox/README.md b/wrtnode/wrtbox/README.md new file mode 100644 index 0000000..990fa60 --- /dev/null +++ b/wrtnode/wrtbox/README.md @@ -0,0 +1,12 @@ +Introduction +=== +This is WRTnode tools-box. + +Tools include: +dnsclient +get_ip +is_intf_up +wait_intf_up +hellowrt + + diff --git a/wrtnode/wrtbox/src/Config.h b/wrtnode/wrtbox/src/Config.h new file mode 100644 index 0000000..09cb7ae --- /dev/null +++ b/wrtnode/wrtbox/src/Config.h @@ -0,0 +1,23 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Noties: + This file defines the feature set to be compiled into wrtbox. + When you turn things off here, they won't be compiled in at all. + This file is parsed by sed. You MUST use single line comments. + i.e., //#define BB_BLAH + +##############################################*/ + +// wrtbox Applications +#define BB_HELLOWRT +#define BB_DNSCLIENT +#define BB_GET_IP +#define BB_IS_INTF_UP +#define BB_WAIT_INTF_UP +// End of Applications List diff --git a/wrtnode/wrtbox/src/Makefile b/wrtnode/wrtbox/src/Makefile new file mode 100644 index 0000000..c5cb89e --- /dev/null +++ b/wrtnode/wrtbox/src/Makefile @@ -0,0 +1,24 @@ +############################################## +# wrtbox is a Swiss Army knife for WRTnode +# WRTnode's busybox +# This file is part of wrtbox. +# Author: 39514004@qq.com (huamanlou,alais name intel inside) +# +# This library is free software; under the terms of the GPL +# +############################################## + +CFLAGS=-Wall +EXTRALIB=-ldl -lm -lc +OBJS=applets.o hellowrt.o dnsclient.o get_ip.o is_intf_up.o wait_intf_up.o wrtbox.o +all:wrtbox + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +wrtbox: $(OBJS) + $(CC) -o $@ $(OBJS) $(LDFLAGS) $(EXTRALIB) + +clean: + rm -f rbcfg *.o + diff --git a/wrtnode/wrtbox/src/applets.c b/wrtnode/wrtbox/src/applets.c new file mode 100644 index 0000000..542015c --- /dev/null +++ b/wrtnode/wrtbox/src/applets.c @@ -0,0 +1,108 @@ +/*############################################## +# wrtbox is a Swiss Army knife for WRTnode +# WRTnode's busybox +# This file is part of wrtbox. +# Author: 39514004@qq.com (huamanlou,alais name intel inside) +# +# This library is free software; under the terms of the GPL +# +##############################################*/ + +#include +#include +#include +#include "wrtbox.h" + +#undef APPLET +#undef APPLET_NOUSAGE +#undef PROTOTYPES +#include "applets.h" + +struct BB_applet *applet_using; + +const struct BB_applet applets[] = { +#ifdef BB_DNSCLIENT + {"dnsclient", dnsclient_main, _BB_DIR_BIN}, +#endif +#ifdef BB_GET_IP + {"get_ip", get_ip_main, _BB_DIR_USR_BIN}, +#endif +#ifdef BB_HELLOWRT + {"hellowrt", hellowrt_main, _BB_DIR_BIN}, +#endif +#ifdef BB_IS_INTF_UP + {"is_intf_up", is_intf_up_main, _BB_DIR_BIN}, +#endif +#ifdef BB_WAIT_INTF_UP + {"wait_intf_up", wait_intf_up_main, _BB_DIR_BIN}, +#endif + {"wrtbox", wrtbox_main, _BB_DIR_BIN}, + { 0,NULL,0 } +}; + + +/* The -1 arises because of the {0,NULL,0,-1} entry above. */ +const size_t NUM_APPLETS = (sizeof (applets) / sizeof (struct BB_applet) - 1); + +extern void show_usage(void) +{ + const char *format_string; + const char *usage_string = ""; + int i; + + for (i = applet_using - applets; i > 0; ) { + if (!*usage_string++) { + --i; + } + } + format_string = "%s\n\nUsage: %s %s\n\n"; + if(*usage_string == 0) + format_string = "%s\n\nNo help available.\n\n"; + fprintf(stderr, format_string, + full_version, applet_using->name, usage_string); + exit(EXIT_FAILURE); +} + +static int applet_name_compare(const void *x, const void *y) +{ + const char *name = x; + const struct BB_applet *applet = y; + return strcmp(name, applet->name); +} + +extern const size_t NUM_APPLETS; + +struct BB_applet *find_applet_by_name(const char *name) +{ + return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet), + applet_name_compare); +} + +void run_applet_by_name(const char *name, int argc, char **argv) +{ + static int recurse_level = 0; + extern int been_there_done_that; + extern const char *applet_name; + recurse_level++; + if ((applet_using = find_applet_by_name(name)) != NULL) { + applet_name = applet_using->name; + if (argv[1] && strcmp(argv[1], "--help") == 0) { + if (strcmp(applet_using->name, "wrtbox")==0) { + if(argv[2]) + applet_using = find_applet_by_name(argv[2]); + else + applet_using = NULL; + } + if(applet_using) + show_usage(); + been_there_done_that=1; + wrtbox_main(0, NULL); + } + exit((*(applet_using->main)) (argc, argv)); + } + if (recurse_level == 1) { + run_applet_by_name("wrtbox", argc, argv); + } + recurse_level--; +} +/* END CODE */ diff --git a/wrtnode/wrtbox/src/applets.h b/wrtnode/wrtbox/src/applets.h new file mode 100644 index 0000000..668fefa --- /dev/null +++ b/wrtnode/wrtbox/src/applets.h @@ -0,0 +1,23 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Noties: + applets.h - a listing of all wrtbox applets. + If you write a new applet, you need to add an entry to this list to make + wrtbox aware of it. + ##############################################*/ + +extern int wrtbox_main(int argc, char **argv); +extern int wait_intf_up_main(int argc, char *argv[]); +extern int is_intf_up_main(int argc, char *argv[]); +extern int hellowrt_main(int argc, char *argv[]); +extern int get_ip_main(int argc, char *argv[]); +extern int dnsclient_main(int argc, char *argv[]); + + + diff --git a/wrtnode/wrtbox/src/dnsclient.c b/wrtnode/wrtbox/src/dnsclient.c new file mode 100644 index 0000000..75437de --- /dev/null +++ b/wrtnode/wrtbox/src/dnsclient.c @@ -0,0 +1,314 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Noties: + gcc -g -Wall -o DNSClient dns_client.c +##############################################*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void printmessage(unsigned char *buf); +static unsigned char *printnamestring(unsigned char *p,unsigned char *buf); + +#define GETWORD(__w,__p) do{__w=*(__p++)<<8;__w|=*(p++);}while(0) +#define GETLONG(__l,__p) do{__l=*(__p++)<<24;__l|=*(__p++)<<16;__l|=*(__p++)<<8;__l|=*(p++);}while(0) + +//* +static char * get_local_ip_addr(const char * if_name) +{ + int i=0; + int sockfd; + struct ifconf ifconf; + unsigned char buf[512]; + struct ifreq *ifreq; + ifconf.ifc_len = 512; + ifconf.ifc_buf = buf; + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0) + { + perror("socket" ); + return NULL; + } + ioctl(sockfd, SIOCGIFCONF, &ifconf); + close(sockfd); + ifreq = (struct ifreq*)buf; + for (i=(ifconf.ifc_len/sizeof (struct ifreq)); i>0; i--) + { + printf("%s\n",ifreq->ifr_name); + printf("%s\n",inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr)); + if (strcmp(ifreq->ifr_name, if_name) == 0) + return inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr); + ifreq++; + } + return NULL; +} + + +int dnsclient_main(int argc,char* argv[]) +{ + if(argc != 2) + { + printf("usage: dnsclient \n"); + return -1; + } + + time_t ident; + int fd; + int rc; + int serveraddrlent; + char *q; + unsigned char *p; + unsigned char *countp; + unsigned char reqBuf[512] = {0}; + unsigned char rplBuf[512] = {0}; + struct sockaddr_in serveraddr; + + //udp + fd = socket(AF_INET, SOCK_DGRAM, 0); + if(fd == -1) + { + perror("error create udp socket"); + return -1; + } + + time(&ident); + //copy + p = reqBuf; + //Transaction ID + *(p++) = ident; + *(p++) = ident>>8; + //Header section + //flag word = 0x0100 + *(p++) = 0x01; + *(p++) = 0x00; + //Questions = 0x0001 + //just one query + *(p++) = 0x00; + *(p++) = 0x01; + //Answer RRs = 0x0000 + //no answers in this message + *(p++) = 0x00; + *(p++) = 0x00; + //Authority RRs = 0x0000 + *(p++) = 0x00; + *(p++) = 0x00; + //Additional RRs = 0x0000 + *(p++) = 0x00; + *(p++) = 0x00; + //Query section + countp = p; + *(p++) = 0; + for(q=argv[1]; *q!=0; q++) + { + if(*q != '.') + { + (*countp)++; + *(p++) = *q; + } + else if(*countp != 0) + { + countp = p; + *(p++) = 0; + } + } + if(*countp != 0) + *(p++) = 0; + + //Type=1(A):host address + *(p++)=0; + *(p++)=1; + //Class=1(IN):internet + *(p++)=0; + *(p++)=1; + + printf("\nRequest:\n"); + printmessage(reqBuf); + + //fill + bzero(&serveraddr, sizeof(serveraddr)); + serveraddr.sin_family = AF_INET; + serveraddr.sin_port = htons(53); + + char * ip = get_local_ip_addr("br-lan"); + printf("%s\n",ip); + if (!ip) + serveraddr.sin_addr.s_addr = inet_addr(ip); + else + serveraddr.sin_addr.s_addr = inet_addr("8.8.8.8"); + + //send to DNS Serv + if(sendto(fd,reqBuf,p-reqBuf,0,(void *)&serveraddr,sizeof(serveraddr)) < 0) + { + perror("error sending request"); + close(fd); + + + return -1; + } + + fd_set set; + struct timeval tv = {10,0}; + int i = 0; + FD_ZERO(&set); + FD_SET(fd, &set); + select(fd + 1, &set, NULL, NULL, &tv); + { + printf("receive data\n"); + if (FD_ISSET(fd, &set)) + goto recev_reply; //len = read(cwc->fd, buf, MAXLINE); + else + goto exit_label; + } + + +recev_reply: + //recev the reply + bzero(&serveraddr,sizeof(serveraddr)); + serveraddrlent = sizeof(serveraddr); + rc = recvfrom(fd,&rplBuf,sizeof(rplBuf),0,(void *)&serveraddr,&serveraddrlent); + if(rc < 0) + { + perror("error receiving request\n"); + close(fd); + return -1; + } + + //print out results + printf("\nReply:\n"); + printmessage(rplBuf); + +exit_label: + //exit + printf("Program Exit\n"); + close(fd); + return 0; +} + +static void printmessage(unsigned char *buf) +{ + unsigned char *p; + unsigned int ident,flags,qdcount,ancount,nscount,arcount; + unsigned int i,j,type,class,ttl,rdlength; + + p = buf; + GETWORD(ident,p); + printf("ident=%#x\n",ident); + + GETWORD(flags,p); + printf("flags=%#x\n",flags); + //printf("qr=%u\n",(flags>>15)&1); + printf("qr=%u\n",flags>>15); + + printf("opcode=%u\n",(flags>>11)&15); + printf("aa=%u\n",(flags>>10)&1); + printf("tc=%u\n",(flags>>9)&1); + printf("rd=%u\n",(flags>>8)&1); + printf("ra=%u\n",(flags>>7)&1); + printf("z=%u\n",(flags>>4)&7); + printf("rcode=%u\n",flags&15); + + GETWORD(qdcount,p); + printf("qdcount=%u\n",qdcount); + + GETWORD(ancount,p); + printf("ancount=%u\n",ancount); + + GETWORD(nscount,p); + printf("nscount=%u\n",nscount); + + GETWORD(arcount,p); + printf("arcount=%u\n",arcount); + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//* +static char * get_local_ip_addr(const char * if_name) +{ + int i=0; + int sockfd; + struct ifconf ifconf; + unsigned char buf[512]; + struct ifreq *ifreq; + ifconf.ifc_len = 512; + ifconf.ifc_buf = buf; + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0) + { + perror("socket" ); + return NULL; + } + ioctl(sockfd, SIOCGIFCONF, &ifconf); + close(sockfd); + ifreq = (struct ifreq*)buf; + for (i=(ifconf.ifc_len/sizeof (struct ifreq)); i>0; i--) + { + if (strcmp(ifreq->ifr_name, if_name) == 0) + return inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr); + ifreq++; + } + return NULL; +} +// */ + +int get_ip_main(int argc,char* argv[]) +{ + if(argc != 2) + { + printf("usage: get_ip \n"); + printf("example: get_ip br-lan\n"); + return -1; + } + char * ip = get_local_ip_addr(argv[1]); + printf("%s\n",ip); + return 0; +} diff --git a/wrtnode/wrtbox/src/hellowrt.c b/wrtnode/wrtbox/src/hellowrt.c new file mode 100644 index 0000000..f10f064 --- /dev/null +++ b/wrtnode/wrtbox/src/hellowrt.c @@ -0,0 +1,18 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Notes: + for test + ##############################################*/ + +#include +int hellowrt_main(int argc, char *argv[]) +{ + printf("Hello, wrtbox!\n"); + return 0; +} diff --git a/wrtnode/wrtbox/src/is_intf_up.c b/wrtnode/wrtbox/src/is_intf_up.c new file mode 100644 index 0000000..06f4a62 --- /dev/null +++ b/wrtnode/wrtbox/src/is_intf_up.c @@ -0,0 +1,77 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + ##############################################*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 1 up +// 0 down +static int __is_intf_up(const char * ifname) +{ + struct ifreq ifr; + int sfd; + int ret = 0; + + if (!((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)) + { + strcpy(ifr.ifr_name, ifname); + if (!ioctl(sfd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP)) + ret = 1; + + close(sfd); + } + + return ret; +} + +int is_intf_up_main(int argc, char *argv[]) +{ + if(argc != 2) + { + printf("usage: is_intf_up \n"); + printf("example: is_intf_up br-lan\n"); + return -1; + } + + + int ret = __is_intf_up(argv[1]); + printf("%d\n",ret); + return 0; +} + + + + diff --git a/wrtnode/wrtbox/src/wait_intf_up.c b/wrtnode/wrtbox/src/wait_intf_up.c new file mode 100644 index 0000000..04df8df --- /dev/null +++ b/wrtnode/wrtbox/src/wait_intf_up.c @@ -0,0 +1,98 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Noties: + for /etc/init.d/dnsmasq restart when /etc/init.d/network restart fully completed! + ##############################################*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// 1 up +// 0 down +static int __is_intf_up(const char * ifname) +{ + struct ifreq ifr; + int sfd; + int ret = 0; + + if (!((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)) + { + strcpy(ifr.ifr_name, ifname); + if (!ioctl(sfd, SIOCGIFFLAGS, &ifr) && (ifr.ifr_flags & IFF_UP)) + ret = 1; + + close(sfd); + } + + return ret; +} + +static int select_time(int time) +{ + int rc = 0; + struct timeval tv; + tv.tv_sec = time; + tv.tv_usec = 0; + rc = select(0, NULL, NULL, NULL, &tv); + // printf("select = %d\n", rc); + return 0; +} + +static int select_time_ms(int ms) +{ + int rc = 0; + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = ms; + rc = select(0, NULL, NULL, NULL, &tv); + // printf("select = %d\n", rc); + return 0; +} + +int wait_intf_up_main(int argc, char *argv[]) +{ + if(argc != 2) + { + printf("usage: wait_intf_up \n"); + printf("example: wait_intf_up br-lan\n"); + return -1; + } + + while (!__is_intf_up(argv[1])) + select_time_ms(100); + printf("%s is up\n",argv[1]); + return 0; +} diff --git a/wrtnode/wrtbox/src/wrtbox.c b/wrtnode/wrtbox/src/wrtbox.c new file mode 100644 index 0000000..97755bf --- /dev/null +++ b/wrtnode/wrtbox/src/wrtbox.c @@ -0,0 +1,87 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + Noties: + ##############################################*/ + +#include +#include +#include +#include +#include +#include "wrtbox.h" + +int been_there_done_that = 0; /* Also used in applets.c */ +const char *applet_name; + +int main(int argc, char **argv) +{ + const char *s; + applet_name = argv[0]; + if (applet_name[0] == '-') + applet_name++; + + for (s = applet_name; *s != '\0';) { + if (*s++ == '/') + applet_name = s; + } + + //printf("applet is %s\n",applet_name); + run_applet_by_name(applet_name, argc, argv); + + printf("applet not found\n"); +} + +int wrtbox_main(int argc, char **argv) +{ + int col = 0, len, i; + argc--; + + /* If we've already been here once, exit now */ + if (been_there_done_that == 1 || argc < 1) { + const struct BB_applet *a = applets; + + fprintf(stderr, "%s\n\n" + "Usage: wrtbox [function] [arguments]...\n" + " or: [function] [arguments]...\n\n" + "\twrtbox is a multi-call binary that combines many common Unix\n" + "\tutilities into a single executable. Most people will create a\n" + "\tlink to wrtbox for each function they wish to use, and wrtbox\n" + "\twill act like whatever it was invoked as.\n" + "\nCurrently defined functions:\n", full_version); + + while (a->name != 0) { + col += + fprintf(stderr, "%s%s", ((col == 0) ? "\t" : ", "), + (a++)->name); + if (col > 60 && a->name != 0) { + fprintf(stderr, ",\n"); + col = 0; + } + } + fprintf(stderr, "\n\n"); + exit(0); + } + + /* Flag that we've been here already */ + been_there_done_that = 1; + + /* Move the command line down a notch */ + len = argv[argc] + strlen(argv[argc]) - argv[1]; + memmove(argv[0], argv[1], len); + memset(argv[0] + len, 0, argv[1] - argv[0]); + + /* Fix up the argv pointers */ + len = argv[1] - argv[0]; + memmove(argv, argv + 1, sizeof(char *) * (argc + 1)); + for (i = 0; i < argc; i++) + argv[i] -= len; + + return (main(argc, argv)); +} + diff --git a/wrtnode/wrtbox/src/wrtbox.h b/wrtnode/wrtbox/src/wrtbox.h new file mode 100644 index 0000000..21178af --- /dev/null +++ b/wrtnode/wrtbox/src/wrtbox.h @@ -0,0 +1,77 @@ +/*############################################## + wrtbox is a Swiss Army knife for WRTnode + WRTnode's busybox + This file is part of wrtbox. + Author: 39514004@qq.com (huamanlou,alais name intel inside) + + This library is free software; under the terms of the GPL + + ##############################################*/ + +#ifndef _BB_INTERNAL_H_ +#define _BB_INTERNAL_H_ 1 + +#include "Config.h" + +#include +#include +#include +#include + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +#include + +#define full_version "WrtBox 0.0.0.1!" + +enum Location { + _BB_DIR_ROOT = 0, + _BB_DIR_BIN, + _BB_DIR_SBIN, + _BB_DIR_USR_BIN, + _BB_DIR_USR_SBIN +}; + +struct BB_applet { + const char* name; + int (*main)(int argc, char** argv); + enum Location location; +}; +extern const struct BB_applet applets[]; +#define PROTOTYPES +#include "applets.h" +#undef PROTOTYPES +#ifdef BB_FEATURE_BUFFERS_GO_ON_STACK +#define RESERVE_BB_BUFFER(buffer,len) char buffer[len] +#define RESERVE_BB_UBUFFER(buffer,len) unsigned char buffer[len] +#define RELEASE_BB_BUFFER(buffer) ((void)0) +#else +#ifdef BB_FEATURE_BUFFERS_GO_IN_BSS +#define RESERVE_BB_BUFFER(buffer,len) static char buffer[len] +#define RESERVE_BB_UBUFFER(buffer,len) static unsigned char buffer[len] +#define RELEASE_BB_BUFFER(buffer) ((void)0) +#else +#define RESERVE_BB_BUFFER(buffer,len) char *buffer=xmalloc(len) +#define RESERVE_BB_UBUFFER(buffer,len) unsigned char *buffer=xmalloc(len) +#define RELEASE_BB_BUFFER(buffer) free (buffer) +#endif +#endif +#ifndef setbit +#define NBBY CHAR_BIT +#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) +#endif + +#ifndef RB_POWER_OFF +#define RB_POWER_OFF 0x4321fedc +#endif +#include +#include +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif +#endif /* _BB_INTERNAL_H_ */