| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <unistd.h> |
| #include <arpa/inet.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <signal.h> |
| #include <string.h> |
| #include <log/log.h> |
| #include <pthread.h> |
| #include <errno.h> |
| #include "liblog/lynq_deflog.h" |
| #include "include/lib_at/lynq_at.h" |
| |
| #define LYNQ_AT_SERVICE_PORT 8087 |
| #define OUT_MAX_SIZE 1024 |
| #define USER_LOG_TAG "LYNQ_AT" |
| #define AT_EXTERSION_SOCKET_NAME "/dev/socket/lynq_atsvc_socket_1" |
| #define LINE __LINE__ |
| #define FUNC __FUNCTION__ |
| static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER; |
| typedef enum |
| { |
| A_SUCCESS = 0, |
| A_ERROR = -1 |
| }LYNQ_AT_E; |
| |
| /*lei add : maybe sento/revc error*/ |
| int result = A_SUCCESS; |
| /*lei add : maybe sento/revc error*/ |
| int sockfd = 0; |
| char *output = NULL; |
| char buffer_at[OUT_MAX_SIZE] = {0}; |
| struct sockaddr_in addr_serv; |
| struct sockaddr_un addr_server; |
| |
| |
| socklen_t len; |
| LYNQ_AT_CALLBACK tmp = NULL; |
| bool connect_state = false; |
| #define SOCKET_ZERO 0 |
| #define SOCKET_SUCC 1 |
| #define SOCKET_FAIL -1 |
| |
| /** |
| * @brief Catch exceptions and free malloc's memory |
| * |
| * @param signum Type:[IN] signal |
| */ |
| static void signal_handler(int signum) |
| { |
| switch(signum) |
| { |
| case SIGABRT: |
| LYDBGLOG("recv SIGABRT\n"); |
| break; |
| case SIGBUS: |
| LYDBGLOG("recv SIGBUS\n"); |
| break; |
| case SIGFPE: |
| LYDBGLOG("recv SIGFPE\n"); |
| break; |
| case SIGILL: |
| LYDBGLOG("recv SIGILL\n"); |
| break; |
| case SIGSEGV: |
| LYDBGLOG("recv SIGSEGV\n"); |
| break; |
| default: |
| LYDBGLOG("recv unknown signal\n"); |
| break; |
| } |
| if(NULL != output) |
| { |
| free(output); |
| output = NULL; |
| } |
| } |
| |
| |
| int socket_local_client (char* name) { |
| //struct sockaddr_un server; |
| //int fd = 0; |
| LYINFLOG("[%d][%s] enter",LINE,FUNC); |
| sockfd = socket(AF_UNIX, SOCK_STREAM, 0); |
| if (sockfd < 0) |
| { |
| LYDBGLOG("Can't open stream socket (%s)", name); |
| return -1; |
| } |
| addr_server.sun_family = AF_UNIX; |
| memset(addr_server.sun_path, '\0', sizeof(addr_server.sun_path)); |
| strncpy(addr_server.sun_path, name, sizeof(addr_server.sun_path) - 1); |
| if (connect(sockfd, (struct sockaddr *) &addr_server, sizeof(struct sockaddr_un)) < 0) |
| { |
| close(sockfd); |
| LYDBGLOG("Can't connect to server side, path: %s, %s", name, strerror(errno)); |
| return -1; |
| } |
| LYINFLOG("[%d][%s] connect %s success",LINE,FUNC,name); |
| return sockfd; |
| } |
| bool send_msg_to_service(int fd,char *msg,int size) |
| { |
| LYDBGLOG("[%d][%s] enter",LINE,FUNC); |
| if (fd < 0) |
| { |
| LYDBGLOG("fd invalid when send to atci service. errno = %d", errno); |
| return false; |
| } |
| if(NULL == msg) |
| { |
| LYDBGLOG("atcmd is null."); |
| return false; |
| } |
| int sendLen = send(fd, msg, size, 0); |
| if (sendLen != size) |
| { |
| LYDBGLOG("lose data when send to atci service. errno = %d", errno); |
| return false; |
| } |
| LYDBGLOG("client send to app demo: %s", msg); |
| return true; |
| } |
| |
| int atsvc_cmd_recv(int fd, char *buf, int len) |
| { |
| LYINFLOG("[%d][%s] enter",LINE,FUNC); |
| int ret = 0; |
| // fd_set rfds; |
| // //FD_CLR(fd, &rfds); |
| // FD_SET(fd, &rfds); |
| // ret = select(fd + 1, &rfds, NULL, NULL, NULL); |
| // if (ret <= 0) |
| // { |
| // LYDBGLOG("acti_cmd_recv client select error, ret=%d, error=%s(%d),fd=%d", ret,strerror(errno), errno, fd); |
| // return SOCKET_FAIL; |
| // } |
| // if (FD_ISSET(fd, &rfds)) |
| // { |
| LYDBGLOG("[%d][%s] recv before",LINE,FUNC); |
| ret = recv(fd, buf, len, 0); |
| LYDBGLOG("[%d][%s] recv after",LINE,FUNC); |
| if (ret < 0) |
| { |
| LYDBGLOG("acti_cmd_recv client select error, ret=%d, error=%s(%d),fd=%d", ret,strerror(errno), errno, fd); |
| return SOCKET_FAIL; |
| } |
| else if(ret == 0) |
| { |
| LYDBGLOG("acti_cmd_recv client recv error, ret=%d, error=%s(%d),fd=%d", ret,strerror(errno), errno, fd); |
| return SOCKET_ZERO; |
| } |
| // else |
| // { |
| // //buf[ret] = '\0'; |
| // } |
| // } |
| return SOCKET_SUCC; |
| } |
| /** |
| * @brief send third cmd to service and receive input,then send output to service |
| * |
| * @param parm |
| * @return void* |
| */ |
| void *thread_recv(void *parm) |
| { |
| //signal(SIGPIPE, signal_handler); |
| //signal(SIGABRT, signal_handler); |
| //signal(SIGBUS, signal_handler); |
| //signal(SIGFPE, signal_handler); |
| //signal(SIGILL, signal_handler); |
| //signal(SIGSEGV, signal_handler); |
| LYINFLOG("[%d][%s] enter",LINE,FUNC); |
| int recv = 0; |
| int send = 0; |
| char at_cmd[100] = {0}; |
| int fd = -1; |
| int ret = 0; |
| fd = socket_local_client(AT_EXTERSION_SOCKET_NAME); |
| if(fd <= 0) |
| { |
| LYDBGLOG("socket_local_client fail\n"); |
| connect_state = false; |
| pthread_mutex_unlock(&s_startupMutex); |
| return NULL; |
| } |
| int len_buf = strlen(buffer_at); |
| if(!send_msg_to_service(fd,buffer_at,len_buf)) |
| { |
| LYDBGLOG("send_msg_to_service fail\n"); |
| connect_state = false; |
| pthread_mutex_unlock(&s_startupMutex); |
| return NULL; |
| } |
| connect_state = true; |
| pthread_mutex_unlock(&s_startupMutex); |
| char *input = NULL; |
| output = (char *)malloc(sizeof(char)*OUT_MAX_SIZE); |
| if(NULL == output) |
| { |
| LYDBGLOG("thread_recv malloc fail\n"); |
| return NULL; |
| } |
| TryNewLink: |
| if(connect_state == false) |
| { |
| if (connect(fd, (struct sockaddr *) &addr_server, sizeof(struct sockaddr_un)) < 0) |
| { |
| close(fd); |
| LYDBGLOG("Can't connect to server side, path: %s, errno:%d", AT_EXTERSION_SOCKET_NAME, errno); |
| return NULL; |
| } |
| connect_state = true; |
| } |
| while (1) |
| { |
| /*receive at cmd*/ |
| memset(at_cmd, 0, sizeof(at_cmd)); |
| ret = atsvc_cmd_recv(fd, at_cmd,sizeof(at_cmd)); |
| if (ret < 0) |
| { |
| LYDBGLOG("[%d][%s]receive CMD error",LINE,FUNC); |
| continue; |
| } |
| else if(ret == SOCKET_ZERO) |
| { |
| ALOGE("maybe client socket closed 1. retry new link!"); |
| connect_state = false; |
| goto TryNewLink; |
| } |
| input = at_cmd; |
| //begin deal with callback |
| tmp(input, output, OUT_MAX_SIZE); |
| LYDBGLOG("lynq_reg_third_at send output to service\n"); |
| if(!send_msg_to_service(fd,output, strlen(output))) |
| { |
| LYDBGLOG("thread_recv send fail\n"); |
| continue; |
| } |
| } |
| free(output); |
| output = NULL; |
| if(fd != 0) |
| { |
| close(fd); |
| } |
| return NULL; |
| } |
| |
| /** |
| * @brief Threads are created to communicate with the server |
| * |
| * @return int |
| */ |
| int lynq_connect_service_start(void) |
| { |
| LYINFLOG("[%d][%s] enter",LINE,FUNC); |
| pthread_t lynq_at_tid = -1; |
| int rt = pthread_create(&lynq_at_tid, NULL, thread_recv, NULL); |
| pthread_mutex_lock(&s_startupMutex); |
| LYINFLOG("[%d][%s] pthread mutex unlock",LINE,FUNC); |
| LYINFLOG(",rt:%d,connect state:%d\n",rt,connect_state); |
| if((connect_state != true) && rt < 0) |
| { |
| LYERRLOG("connect fail,rt:%d,connect state:%d\n",rt,connect_state); |
| return -1; |
| } |
| return 0; |
| } |
| |
| /** |
| * @brief Type:[IN] send third at cmd to service |
| * @param ext_at Type:[IN] input at cmd |
| * @param callback Type:[IN] |
| * @return int |
| */ |
| int lynq_reg_third_at(const char *ext_at, LYNQ_AT_CALLBACK callback) |
| { |
| if(NULL == ext_at || NULL == callback) |
| { |
| return A_ERROR; |
| } |
| memcpy(buffer_at, ext_at, strlen(ext_at)); |
| tmp = callback; |
| LYLOGSET(LOG_DEBUG); |
| LYLOGEINIT(USER_LOG_TAG); |
| LYDBGLOG("lynq_reg_third_at start\n"); |
| int ret = lynq_connect_service_start(); |
| |
| if(ret != 0) |
| { |
| LYDBGLOG("lynq_connect_service_start start failed\n"); |
| return A_ERROR; |
| } |
| LYDBGLOG("lynq_connect_service_start success ret:%d\n",ret); |
| return A_SUCCESS; |
| } |
| |