| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| //#include <binder/Parcel.h> | |
| #include <sys/socket.h> | |
| #include <netinet/in.h> | |
| #include <arpa/inet.h> | |
| #include <errno.h> | |
| #include <stdbool.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| #include "lynq_urc_socket.h" | |
| #include "log/log.h" | |
| #include <list> | |
| static int lynq_urc_socket_fd = 0; | |
| static int registered_urc_socket_port = 0; | |
| static int registered_urc_socket_fd = 0; | |
| static pthread_mutex_t s_urc_broadcast_mtx = PTHREAD_MUTEX_INITIALIZER; | |
| static std::list<struct sockaddr*> s_urc_broadcast_clients; | |
| static pthread_mutex_t s_urc_register_mtx = PTHREAD_MUTEX_INITIALIZER; | |
| #define LYNQ_URC_SERVER_LISTEN_PORT 8086 | |
| #define LYNQ_URC_SERVER_LISTEN_ADDRESS "127.0.0.1" | |
| #define LYNQ_URC_CLIENT_PORT_START 7050 | |
| #define LYNQ_URC_CLIENT_PORT_END 7099 | |
| #define LYNQ_URC_CLIENT_LISTEN_ADDRESS "127.0.0.1" | |
| static void * receive_client_heartbeat(void *parm); | |
| static void find_all_client_to_notify_online(); | |
| int lynq_open_broadcast_urc_socket() | |
| { | |
| int ret = 0; | |
| int on = 1; | |
| pthread_mutex_lock(&s_urc_broadcast_mtx); | |
| struct sockaddr_in addr_serv; | |
| //Creating a Socket object | |
| lynq_urc_socket_fd=socket(AF_INET,SOCK_DGRAM,0); | |
| memset(&addr_serv, 0, sizeof(addr_serv)); | |
| addr_serv.sin_family =AF_INET; | |
| addr_serv.sin_port = htons(LYNQ_URC_SERVER_LISTEN_PORT); | |
| addr_serv.sin_addr.s_addr = inet_addr(LYNQ_URC_SERVER_LISTEN_ADDRESS); | |
| ret = setsockopt(lynq_urc_socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on); | |
| if (ret < 0){ | |
| goto open_socket_exit; | |
| } | |
| ret = bind(lynq_urc_socket_fd,(struct sockaddr*)&addr_serv,sizeof(addr_serv)); | |
| if (ret < 0){ | |
| goto open_socket_exit; | |
| } | |
| //receive registion and display on at port | |
| pthread_t thid; | |
| if(pthread_create(&thid, NULL, receive_client_heartbeat, NULL) != 0) { | |
| RLOGE("thread creation failed\n"); | |
| ret = -1; | |
| goto open_socket_exit; | |
| } | |
| find_all_client_to_notify_online(); | |
| open_socket_exit: | |
| pthread_mutex_unlock(&s_urc_broadcast_mtx); | |
| return ret == 0 ? lynq_urc_socket_fd: -1; | |
| } | |
| int lynq_broadcast_urc_msg(void * msg, int size) | |
| { | |
| int all_ok = 1; | |
| pthread_mutex_lock(&s_urc_broadcast_mtx); | |
| for(auto it=s_urc_broadcast_clients.begin(); it != s_urc_broadcast_clients.end(); ) | |
| { | |
| int len = sendto(lynq_urc_socket_fd, msg, size, 0, *it, sizeof(struct sockaddr_in)); | |
| if (len < 0) | |
| { | |
| struct sockaddr_in *addr_cli = (struct sockaddr_in *) *it; | |
| printf("remove client %d now\n", ntohs(addr_cli->sin_port)); | |
| it = s_urc_broadcast_clients.erase(it); | |
| free(addr_cli); | |
| all_ok = 0; | |
| continue; | |
| } | |
| it++; | |
| } | |
| pthread_mutex_unlock(&s_urc_broadcast_mtx); | |
| return all_ok; | |
| } | |
| int lynq_register_urc_socket() | |
| { | |
| int on = 0; | |
| int ret = 0; | |
| int len_s; | |
| struct sockaddr_in addr_serv; | |
| //Creating a Socket object | |
| pthread_mutex_lock(&s_urc_register_mtx); | |
| registered_urc_socket_fd=socket(AF_INET,SOCK_DGRAM,0); | |
| memset(&addr_serv, 0, sizeof(addr_serv)); | |
| addr_serv.sin_family =AF_INET; | |
| addr_serv.sin_addr.s_addr = inet_addr(LYNQ_URC_CLIENT_LISTEN_ADDRESS); | |
| if (registered_urc_socket_port > 0) { | |
| on = 1; | |
| ret = setsockopt(registered_urc_socket_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof on); | |
| addr_serv.sin_port = htons(registered_urc_socket_port); | |
| ret = bind(registered_urc_socket_fd,(struct sockaddr*)&addr_serv,sizeof(addr_serv)); | |
| if (ret < 0){ | |
| goto register_socket_exit; | |
| } | |
| } | |
| else | |
| { | |
| for(registered_urc_socket_port = LYNQ_URC_CLIENT_PORT_START; registered_urc_socket_port < LYNQ_URC_CLIENT_PORT_END; registered_urc_socket_port ++) | |
| { | |
| addr_serv.sin_port = htons(registered_urc_socket_port); | |
| ret = bind(registered_urc_socket_fd,(struct sockaddr*)&addr_serv,sizeof(addr_serv)); | |
| if (ret < 0){ | |
| printf("bind socket %d fail\n", registered_urc_socket_port); | |
| continue; | |
| } | |
| break; | |
| } | |
| } | |
| addr_serv.sin_port = htons(LYNQ_URC_SERVER_LISTEN_PORT); | |
| len_s = sendto(registered_urc_socket_fd, ®istered_urc_socket_port, sizeof(registered_urc_socket_port), 0, (struct sockaddr *)&addr_serv,sizeof(addr_serv)); | |
| printf("send result %d %d\n", len_s, errno); | |
| register_socket_exit: | |
| pthread_mutex_unlock(&s_urc_register_mtx); | |
| printf("init result %d\n", ret); | |
| return ret ==0 ? registered_urc_socket_fd : -1; | |
| } | |
| int lynq_recv_urc_msg(void * buffer, int size) | |
| { | |
| int ret = 0; | |
| struct sockaddr_in addr_serv; | |
| socklen_t len_addr_serv = sizeof(addr_serv); | |
| memset(&addr_serv, 0, sizeof(addr_serv)); | |
| printf("client %ul to recv now\n", pthread_self()); | |
| pthread_mutex_lock(&s_urc_register_mtx); | |
| if (registered_urc_socket_fd <= 0) { | |
| pthread_mutex_unlock(&s_urc_register_mtx); | |
| return -1; | |
| } | |
| while(1) | |
| { | |
| memset(buffer, 0, 4); | |
| ret = recvfrom(registered_urc_socket_fd, buffer, size,0,(struct sockaddr *)&addr_serv,(socklen_t*)&len_addr_serv); | |
| if (ret > 0 && LYNQ_URC_SERVER_LISTEN_PORT == ntohs(addr_serv.sin_port)) | |
| { | |
| if (ret == 4 && LYNQ_URC_SERVER_LISTEN_PORT == *((int*)buffer)) | |
| { | |
| sendto(registered_urc_socket_fd, ®istered_urc_socket_port, sizeof(registered_urc_socket_port), 0, (struct sockaddr *)&addr_serv,sizeof(addr_serv)); | |
| printf("to send ack of headbeat\n"); | |
| continue; | |
| } | |
| } | |
| else | |
| { | |
| printf("not a server packet\n"); | |
| continue; | |
| } | |
| break; | |
| } | |
| pthread_mutex_unlock(&s_urc_register_mtx); | |
| printf("client %ul recv %d\n", pthread_self(), ret); | |
| return ret; | |
| } | |
| static void *receive_client_heartbeat(void *parm) | |
| { | |
| RLOGE("receive_at thread start\n"); | |
| int recv = 0; | |
| char buffer[1024] = {0}; | |
| while(1) | |
| { | |
| RLOGE("receive third at cmd\n"); | |
| socklen_t len = sizeof(struct sockaddr_in); | |
| struct sockaddr* cli = (struct sockaddr*)malloc(len); | |
| bzero(cli, len); | |
| printf("to recv now\n"); | |
| recv = recvfrom(lynq_urc_socket_fd, buffer, 1024, 0, cli, &len); | |
| if(recv < 0) | |
| { | |
| RLOGE("recv fail\n"); | |
| printf("recv fail\n"); | |
| free(cli); | |
| continue; | |
| } | |
| printf("recv a packet %d \n", recv); | |
| struct sockaddr_in * register_socket = (struct sockaddr_in*)cli; | |
| int port = ntohs(register_socket->sin_port); | |
| if (recv == 4 && port == *((int*)buffer)) | |
| { | |
| printf("port is %d\n", port); | |
| pthread_mutex_lock(&s_urc_broadcast_mtx); | |
| s_urc_broadcast_clients.push_back(cli); | |
| pthread_mutex_unlock(&s_urc_broadcast_mtx); | |
| RLOGE("recvfrom from client\n"); | |
| } | |
| } | |
| return NULL; | |
| } | |
| static int exec_cmd(const char *str_cmd, char * str_cmd_ret, size_t max_len) | |
| { | |
| FILE *fp; | |
| //printf("to exec cmd:%s\n", str_cmd); | |
| if((fp=popen(str_cmd,"r"))==NULL) | |
| { | |
| perror("popen error!"); | |
| return -1; | |
| } | |
| if((fread(str_cmd_ret,max_len,1,fp))<0) | |
| { | |
| perror("fread fail!"); | |
| fclose(fp); | |
| return -1; | |
| } | |
| fclose(fp); | |
| return 0; | |
| } | |
| static int lynq_split(char * str, int len, char delimiter, char * results[]) { | |
| int ret = 0; | |
| char * end = str + len - 1; | |
| results[ret++] = str; | |
| while(str < end) { | |
| if (*str == delimiter) { | |
| *str++ = '\0'; | |
| results[ret++] = str; | |
| continue; | |
| } | |
| str++; | |
| } | |
| if (*str == delimiter) { | |
| *str = '\0'; | |
| } | |
| return ret; | |
| } | |
| static void find_all_client_to_notify_online() | |
| { | |
| char buffer[1024] = {0}; | |
| char * split_lines[128]= {0}; | |
| int count = 0; | |
| int port, len; | |
| int local_port = LYNQ_URC_SERVER_LISTEN_PORT; | |
| printf("find_all_client_to_notify_online\n"); | |
| if (exec_cmd("netstat -an | grep -e \"127\\.0\\.0\\.1:70[5-9][0-9]\" | awk '{print $4}' | awk -F \":\" '{print $2}'", buffer, 1024) == 0) | |
| { | |
| count = lynq_split(buffer, 1024, '\n', split_lines); | |
| for(int i=0; i < count;i++) | |
| { | |
| port = atoi(split_lines[i]); | |
| printf("got %s port:%d\n", split_lines[i], port); | |
| if (port < LYNQ_URC_CLIENT_PORT_START || port > LYNQ_URC_CLIENT_PORT_END) | |
| continue; | |
| struct sockaddr_in addr_serv; | |
| memset(&addr_serv, 0, sizeof(addr_serv)); | |
| addr_serv.sin_family =AF_INET; | |
| addr_serv.sin_addr.s_addr = inet_addr(LYNQ_URC_CLIENT_LISTEN_ADDRESS); | |
| addr_serv.sin_port = htons(port); | |
| len = sendto(lynq_urc_socket_fd, &local_port, sizeof(local_port), 0, (struct sockaddr *)&addr_serv,sizeof(addr_serv)); | |
| printf("send result %d %d\n", len, errno); | |
| } | |
| } | |
| else | |
| { | |
| printf("net stat fail\n"); | |
| } | |
| } |