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