yy1717
2021-01-19 87156fa3adfa2e3232a6f6e612584aa8a4ebaea1
lib/src/main/cpp/common/net.cpp
@@ -13,19 +13,77 @@
#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;
@@ -68,7 +126,7 @@
    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);
@@ -76,7 +134,7 @@
    return !regex_match(target, pattern0);
}
static int socket_set_keepalive(int fd)
int CTcpPort::socket_set_keepalive(int fd)
{
    int alive, idle, cnt, intv;
@@ -133,7 +191,7 @@
    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;
@@ -259,51 +317,116 @@
    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;
    /*******************************************************
@@ -314,9 +437,9 @@
    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");
@@ -325,8 +448,8 @@
        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");
        }
@@ -337,148 +460,15 @@
    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;
}