| | |
| | | #include <arpa/inet.h> |
| | | #include <regex> |
| | | #include <pthread.h> |
| | | #include <semaphore.h> |
| | | #include <string> |
| | | |
| | | #include "net.h" |
| | | #include "../jni_log.h" |
| | | |
| | | #define DEBUG(fmt, args...) LOGD("<net> <%s>: " fmt, __func__, ##args) |
| | | #define PARSE_BUFF_SIZE 4096 |
| | | |
| | | using namespace std; |
| | | |
| | | CTcpPort::CTcpPort() |
| | | { |
| | | m_iServiceType = TYPE_CLIENT; |
| | | m_sIp.clear(); |
| | | m_nPort = 0; |
| | | m_connected = false; |
| | | m_pClientSocket = 0; |
| | | m_pServerSocket = 0; |
| | | |
| | | event_func = NULL; |
| | | event_func_context = NULL; |
| | | receive_data_func = NULL; |
| | | receive_data_func_context = NULL; |
| | | } |
| | | |
| | | CTcpPort::~CTcpPort() |
| | | { |
| | | CloseTcpPort(); |
| | | } |
| | | |
| | | bool CTcpPort::IsOpen(void) |
| | | { |
| | | if (m_iServiceType == TYPE_SERVER) { |
| | | if (m_pServerSocket > 0) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } else { |
| | | if (m_pClientSocket > 0) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | bool CTcpPort::OpenTcpPort(const char *ip, int port) |
| | | { |
| | | if (IsOpen()) { |
| | | return true; |
| | | } |
| | | |
| | | m_sIp = ip; |
| | | m_nPort = port; |
| | | |
| | | pthread_t platform_pid; |
| | | pthread_attr_t attr; |
| | | pthread_attr_init(&attr); |
| | | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached |
| | | pthread_create(&platform_pid, &attr, TcpConnectThread, this); |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /************************************************************* |
| | | host_name:domain name |
| | | net_addr:return numbers-and-dots notation |
| | | */ |
| | | int GetHostIP(const char *host_name, char *net_addr) |
| | | int CTcpPort::GetHostIP(const char *host_name, char *net_addr) |
| | | { |
| | | struct hostent *hptr; |
| | | char **pptr; |
| | |
| | | return -2; |
| | | } |
| | | |
| | | static bool is_domain_name(const char *ip) |
| | | bool CTcpPort::is_domain_name(const char *ip) |
| | | { |
| | | regex pattern0("^((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}$"); |
| | | string target(ip); |
| | |
| | | return !regex_match(target, pattern0); |
| | | } |
| | | |
| | | static int socket_set_keepalive(int fd) |
| | | int CTcpPort::socket_set_keepalive(int fd) |
| | | { |
| | | int alive, idle, cnt, intv; |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | static int tcp_connect(char *ip, uint16_t port) |
| | | int CTcpPort::tcp_connect(char *ip, uint16_t port) |
| | | { |
| | | struct sockaddr_in server_sockaddr; |
| | | int soc; |
| | |
| | | return( -1 ); |
| | | } |
| | | |
| | | static int udp_connect(const char *ip, uint16_t port) { |
| | | struct sockaddr_in server_sockaddr; |
| | | int soc; |
| | | int opt; |
| | | int arg; |
| | | void *CTcpPort::TcpConnectThread(void *p) |
| | | { |
| | | CTcpPort *pCTcpPort = (CTcpPort *)p; |
| | | |
| | | if ((soc = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { |
| | | return -1; |
| | | char net_addr[32] = {0}; |
| | | |
| | | if (pCTcpPort->is_domain_name(pCTcpPort->m_sIp.c_str())) { |
| | | if (pCTcpPort->GetHostIP(pCTcpPort->m_sIp.c_str(), net_addr) != 0) { |
| | | goto CONNECT_END; |
| | | } |
| | | } else { |
| | | strcpy(net_addr, pCTcpPort->m_sIp.c_str()); |
| | | } |
| | | |
| | | /*Enable send broadcast packet*/ |
| | | opt = 1; |
| | | if (setsockopt(soc, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) != 0) { |
| | | perror("setsockopt"); |
| | | close(soc); |
| | | return -1; |
| | | pCTcpPort->m_pClientSocket = pCTcpPort->tcp_connect(net_addr, pCTcpPort->m_nPort); |
| | | |
| | | if (pCTcpPort->m_pClientSocket > 0) { |
| | | if (pCTcpPort->event_func != NULL) { |
| | | pCTcpPort->event_func(0, pCTcpPort, pCTcpPort->event_func_context); |
| | | } |
| | | |
| | | pthread_t platform_pid; |
| | | pthread_attr_t attr; |
| | | pthread_attr_init(&attr); |
| | | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//detached |
| | | pthread_create(&platform_pid, &attr, TcpListenThread, p); |
| | | } else { |
| | | if (pCTcpPort->event_func != NULL) { |
| | | pCTcpPort->event_func(-1, pCTcpPort, pCTcpPort->event_func_context); |
| | | } |
| | | } |
| | | |
| | | // Set non-blocking |
| | | if( (arg = fcntl(soc, F_GETFL, NULL)) < 0 ) { |
| | | close(soc); |
| | | return -1; |
| | | } |
| | | |
| | | if ( fcntl(soc, F_SETFL, arg | O_NONBLOCK) < 0 ) { |
| | | close(soc); |
| | | return -1; |
| | | } |
| | | |
| | | server_sockaddr.sin_family = AF_INET; |
| | | server_sockaddr.sin_addr.s_addr = inet_addr(ip);//htonl(INADDR_ANY); |
| | | server_sockaddr.sin_port = htons(port); |
| | | bzero(&server_sockaddr.sin_zero, 8); |
| | | |
| | | return soc; |
| | | CONNECT_END: |
| | | pthread_exit(NULL); |
| | | } |
| | | |
| | | int WriteTCP(int fd, const uint8_t * buf, uint32_t len) |
| | | void *CTcpPort::TcpListenThread(void *p) |
| | | { |
| | | int fds_ret; |
| | | struct timeval tv; |
| | | fd_set rdfds; |
| | | fd_set exfds; |
| | | uint8_t RxBuf[PARSE_BUFF_SIZE]; |
| | | |
| | | CTcpPort *pCTcpPort = (CTcpPort *)p; |
| | | |
| | | while (pCTcpPort->m_pClientSocket > 0) { |
| | | tv.tv_sec = 5; |
| | | tv.tv_usec = 0; |
| | | FD_ZERO(&rdfds); //clean |
| | | FD_SET(pCTcpPort->m_pClientSocket, &rdfds); //set |
| | | |
| | | fds_ret = select(pCTcpPort->m_pClientSocket + 1, &rdfds, NULL, NULL, &tv); |
| | | |
| | | if (fds_ret < 0) { |
| | | break; |
| | | } else if(fds_ret == 0) { |
| | | //Occur failure(such as line disconnect) |
| | | } else if(FD_ISSET(pCTcpPort->m_pClientSocket, &rdfds)) { |
| | | int recvLen = recv(pCTcpPort->m_pClientSocket, RxBuf, sizeof(RxBuf), 0); |
| | | |
| | | if (recvLen == 0) { |
| | | LOGW("tcp error TCP disconnected 0 errno = %d", errno); |
| | | break; |
| | | } else if (recvLen < 0) { |
| | | if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { |
| | | |
| | | } else { |
| | | LOGW("tcp error TCP disconnected errno = %d", errno);; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (recvLen > 0) { |
| | | if (pCTcpPort->receive_data_func != NULL) { |
| | | pCTcpPort->receive_data_func(RxBuf, recvLen, pCTcpPort, pCTcpPort->receive_data_func_context); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | pCTcpPort->CloseTcpPort(); |
| | | |
| | | if (pCTcpPort->event_func) { |
| | | pCTcpPort->event_func(-1, pCTcpPort, pCTcpPort->event_func_context); |
| | | } |
| | | |
| | | pthread_exit(NULL); |
| | | } |
| | | |
| | | void CTcpPort::set_event_callback(void (*callback)(int, void *, void *), void *context) |
| | | { |
| | | event_func = callback; |
| | | event_func_context = context; |
| | | } |
| | | |
| | | void CTcpPort::set_data_callback(void (*callback)(void *, int, void *, void *), void *context) |
| | | { |
| | | receive_data_func = callback; |
| | | receive_data_func_context = context; |
| | | } |
| | | |
| | | int CTcpPort::WriteTCP(const uint8_t * buf, uint32_t len) |
| | | { |
| | | int ret = 0; |
| | | int fds_ret; |
| | | struct timeval tv; |
| | | fd_set rdfds; |
| | | |
| | | if (fd < 0) |
| | | if (m_pClientSocket <= 0) |
| | | return -2; |
| | | |
| | | /******************************************************* |
| | |
| | | tv.tv_usec = 0; |
| | | |
| | | FD_ZERO(&rdfds); //clean |
| | | FD_SET(fd, &rdfds); //set |
| | | FD_SET(m_pClientSocket, &rdfds); //set |
| | | |
| | | fds_ret = select(fd + 1, NULL, &rdfds, NULL, &tv); |
| | | fds_ret = select(m_pClientSocket + 1, NULL, &rdfds, NULL, &tv); |
| | | |
| | | if (fds_ret < 0) { |
| | | DEBUG("tcp error send select error"); |
| | |
| | | DEBUG("tcp error Occur failure(such as line disconnect)"); |
| | | //Occur failure(such as line disconnect) |
| | | ret = -1; |
| | | } else if(FD_ISSET(fd, &rdfds)) { |
| | | ret = send(fd, buf, len, 0); |
| | | } else if(FD_ISSET(m_pClientSocket, &rdfds)) { |
| | | ret = send(m_pClientSocket, buf, len, 0); |
| | | if(ret == -1) { |
| | | DEBUG("tcp error TCP Send Error"); |
| | | } |
| | |
| | | return ret; |
| | | } |
| | | |
| | | int ReadTCP(int fd, uint8_t * buf, uint32_t len) |
| | | bool CTcpPort::CloseTcpPort(void) |
| | | { |
| | | if (fd < 0) { |
| | | return -2; |
| | | DEBUG("DisconnectTCP fd = %d", m_pClientSocket); |
| | | |
| | | if (m_pClientSocket > 0) { |
| | | shutdown(m_pClientSocket, SHUT_RDWR); |
| | | close(m_pClientSocket); |
| | | m_pClientSocket = 0; |
| | | return true; |
| | | } |
| | | |
| | | int recvLen = recv(fd, buf, len, 0); //read socket data from server |
| | | |
| | | if (recvLen == 0) { |
| | | LOGW("tcp error TCP disconnected 0 errno = %d", errno); |
| | | return -1; |
| | | } else if (recvLen < 0) { |
| | | if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { |
| | | return 0; |
| | | } else { |
| | | LOGW("tcp error TCP disconnected errno = %d", errno);; |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | return recvLen; |
| | | } |
| | | |
| | | int ConnectTCP(const char *ip, uint16_t port) |
| | | { |
| | | char net_addr[32] = {0}; |
| | | |
| | | if (is_domain_name(ip)) { |
| | | if (GetHostIP(ip, net_addr) != 0) { |
| | | return -3; |
| | | } |
| | | } else { |
| | | strcpy(net_addr, ip); |
| | | } |
| | | |
| | | return tcp_connect(net_addr, port); |
| | | } |
| | | |
| | | void DisconnectTCP(int fd) |
| | | { |
| | | DEBUG("DisconnectTCP fd = %d", fd); |
| | | if (fd >= 0) { |
| | | shutdown(fd, SHUT_RDWR); |
| | | close(fd); |
| | | } |
| | | } |
| | | |
| | | int EstablishUDP(const char *ip, uint16_t port) |
| | | { |
| | | char net_addr[32] = {0}; |
| | | |
| | | if (is_domain_name(ip)) { |
| | | if (GetHostIP(ip, net_addr) != 0) { |
| | | return -3; |
| | | } |
| | | } else { |
| | | strcpy(net_addr, ip); |
| | | } |
| | | |
| | | return udp_connect(net_addr, port); |
| | | } |
| | | |
| | | void RemoveUDP(int fd) |
| | | { |
| | | close(fd); |
| | | } |
| | | |
| | | int WriteUDP(int fd, char *ip, uint16_t port, const uint8_t * buf, uint32_t len) |
| | | { |
| | | int ret = 0; |
| | | int fds_ret; |
| | | struct timeval tv; |
| | | fd_set rdfds; |
| | | |
| | | if (fd < 0) |
| | | return -2; |
| | | |
| | | /******************************************************* |
| | | TCP send with nonblock, if occur failure(such as line disconnect...), |
| | | will send timeout, so terminate TCP. |
| | | */ |
| | | tv.tv_sec = 5; |
| | | tv.tv_usec = 0; |
| | | |
| | | FD_ZERO(&rdfds); //clean |
| | | FD_SET(fd, &rdfds); //set |
| | | |
| | | fds_ret = select(fd + 1, NULL, &rdfds, NULL, &tv); |
| | | |
| | | if (fds_ret < 0) |
| | | { |
| | | DEBUG("UDP send select error"); |
| | | return -1; |
| | | } |
| | | else if(fds_ret == 0) |
| | | { |
| | | DEBUG("Occur failure(such as line disconnect)"); |
| | | ret = -1; |
| | | } |
| | | else if(FD_ISSET(fd, &rdfds)) |
| | | { |
| | | struct sockaddr_in server_sockaddr; |
| | | |
| | | server_sockaddr.sin_family = AF_INET; |
| | | server_sockaddr.sin_addr.s_addr = inet_addr(ip);//htonl(INADDR_ANY); |
| | | server_sockaddr.sin_port = htons(port); |
| | | bzero(&server_sockaddr.sin_zero, 8); |
| | | |
| | | ret = sendto(fd, buf, len, 0, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr_in)); |
| | | |
| | | if(ret == -1) |
| | | { |
| | | DEBUG("UDP Send Error"); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | DEBUG("UDP send has error\n"); |
| | | } |
| | | |
| | | return ret; |
| | | } |
| | | |
| | | int ReadUDP(int fd, uint8_t * buf, uint32_t len) |
| | | { |
| | | struct sockaddr_in from_addr; |
| | | socklen_t from_len; |
| | | |
| | | int recvLen = recvfrom(fd, buf, len, 0, |
| | | (struct sockaddr *) &from_addr, |
| | | &from_len);//read socket data from server// |
| | | |
| | | if (recvLen == 0) { |
| | | return 0; |
| | | } else if (recvLen < 0) { |
| | | if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) { |
| | | return 0; |
| | | } else { |
| | | DEBUG("UDP ERROR!! = %d", errno); |
| | | return -1; |
| | | } |
| | | } |
| | | |
| | | return recvLen; |
| | | return false; |
| | | } |