mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-02-05 10:25:40 +00:00
359 lines
9.7 KiB
C
359 lines
9.7 KiB
C
/*
|
|
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
|
*/
|
|
|
|
#include "../new_common.h"
|
|
#include "../logging/logging.h"
|
|
#include "utils_net.h"
|
|
#include "errno.h"
|
|
#include "lwip/sockets.h"
|
|
#include "lwip/netdb.h"
|
|
#include "utils_timer.h"
|
|
|
|
uintptr_t HAL_TCP_Establish(const char *host, uint16_t port)
|
|
{
|
|
struct addrinfo hints;
|
|
struct addrinfo *addrInfoList = NULL;
|
|
struct addrinfo *cur = NULL;
|
|
int fd = 0;
|
|
int rc = 0;
|
|
char service[6];
|
|
|
|
os_memset(&hints, 0, sizeof(hints));
|
|
hints.ai_family = AF_INET; //only IPv4
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
hints.ai_protocol = IPPROTO_TCP;
|
|
sprintf(service, "%u", port);
|
|
|
|
if ((rc = getaddrinfo(host, service, &hints, &addrInfoList)) != 0) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"getaddrinfo error");
|
|
return 0;
|
|
}
|
|
|
|
for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) {
|
|
if (cur->ai_family != AF_INET) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"socket type error");
|
|
rc = 0;
|
|
continue;
|
|
}
|
|
|
|
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
|
|
if (fd < 0) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"create socket error %i",fd);
|
|
rc = 0;
|
|
continue;
|
|
}
|
|
ADDLOG_INFO(LOG_FEATURE_HTTP_CLIENT, "HAL_TCP_Establish: created socket %i\n\r",(int)fd);
|
|
|
|
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
|
|
rc = fd;
|
|
break;
|
|
}
|
|
|
|
lwip_close(fd);
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"connect error");
|
|
rc = 0;
|
|
}
|
|
|
|
if (0 == rc){
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"fail to establish tcp");
|
|
} else {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"success to establish tcp, fd=%d", rc);
|
|
}
|
|
freeaddrinfo(addrInfoList);
|
|
|
|
return (uintptr_t)rc;
|
|
}
|
|
|
|
|
|
int32_t HAL_TCP_Destroy(uintptr_t fd)
|
|
{
|
|
int rc;
|
|
///int att;
|
|
|
|
//Shutdown both send and receive operations.
|
|
rc = shutdown((int) fd, 2);
|
|
if (0 != rc) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"shutdown error %i",rc);
|
|
return -1;
|
|
}
|
|
#if 0
|
|
for(att = 0; att < 10; att++) {
|
|
rc = lwip_close((int) fd);
|
|
if (0 != rc) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"closesocket(%i) error %i at attemtp %i",((int)fd),rc,att);
|
|
delay_ms(500);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
#elif 1
|
|
rc = lwip_close((int) fd);
|
|
if (0 != rc) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"closesocket(%i) error %i",((int)fd),rc);
|
|
// same as above but without SOCK_DEINIT_SYNC check
|
|
// There is a bug in our htttp client and this is a temporary work around for that
|
|
// Otherwise, it leaves sockets unfried and they adds up to 38 and block all networking
|
|
lwip_close_force((int) fd);
|
|
return -1;
|
|
}
|
|
#else
|
|
rc = lwip_close((int) fd);
|
|
if (0 != rc) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"closesocket(%i) error %i",((int)fd),rc);
|
|
return -1;
|
|
}
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
int ret, err_code;
|
|
uint32_t len_sent;
|
|
uint64_t t_end, t_left;
|
|
fd_set sets;
|
|
|
|
t_end = utils_time_get_ms() + timeout_ms;
|
|
len_sent = 0;
|
|
err_code = 0;
|
|
ret = 1; //send one time if timeout_ms is value 0
|
|
|
|
do {
|
|
t_left = utils_time_left(t_end, utils_time_get_ms());
|
|
|
|
if (0 != t_left) {
|
|
struct timeval timeout;
|
|
|
|
FD_ZERO( &sets );
|
|
FD_SET(fd, &sets);
|
|
|
|
timeout.tv_sec = t_left / 1000;
|
|
timeout.tv_usec = (t_left % 1000) * 1000;
|
|
|
|
ret = select(fd + 1, NULL, &sets, NULL, &timeout);
|
|
if (ret > 0) {
|
|
if (0 == FD_ISSET(fd, &sets)) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"Should NOT arrive");
|
|
//If timeout in next loop, it will not sent any data
|
|
ret = 0;
|
|
continue;
|
|
}
|
|
} else if (0 == ret) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"select-write timeout %lu", fd);
|
|
break;
|
|
} else {
|
|
if (EINTR == errno) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"EINTR be caught");
|
|
continue;
|
|
}
|
|
|
|
err_code = -1;
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"select-write fail");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ret > 0) {
|
|
ret = send(fd, buf + len_sent, len - len_sent, 0);
|
|
if (ret > 0) {
|
|
len_sent += ret;
|
|
} else if (0 == ret) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"No data be sent");
|
|
} else {
|
|
if (EINTR == errno) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"EINTR be caught");
|
|
continue;
|
|
}
|
|
|
|
err_code = -1;
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"send fail");
|
|
break;
|
|
}
|
|
}
|
|
} while((len_sent < len) && (utils_time_left(t_end, utils_time_get_ms()) > 0));
|
|
|
|
return len_sent;
|
|
}
|
|
|
|
|
|
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
int ret, err_code,data_over;
|
|
uint32_t len_recv;
|
|
uint64_t t_end, t_left;
|
|
fd_set sets;
|
|
struct timeval timeout;
|
|
|
|
t_end = utils_time_get_ms( ) + timeout_ms ;
|
|
len_recv = 0;
|
|
err_code = 0;
|
|
|
|
data_over = 0;
|
|
|
|
do {
|
|
t_left = utils_time_left(t_end, utils_time_get_ms());
|
|
/* if (0 == t_left && bk_http_ptr->do_data == 0) {
|
|
break;
|
|
}*/
|
|
FD_ZERO( &sets );
|
|
FD_SET(fd, &sets);
|
|
|
|
timeout.tv_sec = t_left / 1000;
|
|
timeout.tv_usec = (t_left % 1000) * 1000;
|
|
|
|
ret = select(fd + 1, &sets, NULL, NULL, NULL);
|
|
if ( FD_ISSET( fd, &sets ) )
|
|
{
|
|
if (ret > 0) {
|
|
ret = recv(fd, buf, len, 0);
|
|
if (ret > 0) {
|
|
if(ret < len)
|
|
{
|
|
data_over = 1;
|
|
}
|
|
// if(bk_http_ptr->do_data == 1)
|
|
// {
|
|
// http_data_process(buf,ret);
|
|
// }
|
|
|
|
len_recv += ret;
|
|
} else if (0 == ret) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"connection is closed");
|
|
err_code = -1;
|
|
break;
|
|
} else {
|
|
if (EINTR == errno) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"EINTR be caught");
|
|
continue;
|
|
}
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"send fail");
|
|
err_code = -2;
|
|
break;
|
|
}
|
|
} else if (0 == ret) {
|
|
break;
|
|
} else {
|
|
if (EINTR == errno) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"EINTR be caught-------\r\n");
|
|
//continue;
|
|
}
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"select-recv fail");
|
|
err_code = -2;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}while(/*(bk_http_ptr->do_data == 1 && len_recv < bk_http_ptr->http_total) || */((len_recv < len) && (0 == data_over)));
|
|
|
|
//priority to return data bytes if any data be received from TCP connection.
|
|
//It will get error code on next calling
|
|
return (0 != len_recv) ? len_recv : err_code;
|
|
}
|
|
|
|
/*** TCP connection ***/
|
|
int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms);
|
|
}
|
|
|
|
|
|
static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms);
|
|
}
|
|
|
|
static int disconnect_tcp(utils_network_pt pNetwork)
|
|
{
|
|
if (0 == pNetwork->handle) {
|
|
return -1;
|
|
}
|
|
|
|
HAL_TCP_Destroy(pNetwork->handle);
|
|
pNetwork->handle = 0;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int connect_tcp(utils_network_pt pNetwork)
|
|
{
|
|
if (NULL == pNetwork) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"network is null");
|
|
return 1;
|
|
}
|
|
|
|
pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port);
|
|
if (0 == pNetwork->handle) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/****** network interface ******/
|
|
|
|
int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
if (NULL == pNetwork->ca_crt) { //TCP connection
|
|
return read_tcp(pNetwork, buffer, len, timeout_ms);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms)
|
|
{
|
|
if (NULL == pNetwork->ca_crt) { //TCP connection
|
|
return write_tcp(pNetwork, buffer, len, timeout_ms);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int iotx_net_disconnect(utils_network_pt pNetwork)
|
|
{
|
|
if (NULL == pNetwork->ca_crt) { //TCP connection
|
|
return disconnect_tcp(pNetwork);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int iotx_net_connect(utils_network_pt pNetwork)
|
|
{
|
|
if (NULL == pNetwork->ca_crt) { //TCP connection
|
|
return connect_tcp(pNetwork);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt)
|
|
{
|
|
if (!pNetwork || !host) {
|
|
ADDLOG_ERROR(LOG_FEATURE_HTTP_CLIENT,"parameter error! pNetwork=%p, host = %p", pNetwork, host);
|
|
return -1;
|
|
}
|
|
pNetwork->pHostAddress = host;
|
|
pNetwork->port = port;
|
|
pNetwork->ca_crt = ca_crt;
|
|
|
|
if (NULL == ca_crt) {
|
|
pNetwork->ca_crt_len = 0;
|
|
} else {
|
|
pNetwork->ca_crt_len = os_strlen(ca_crt);
|
|
}
|
|
|
|
pNetwork->handle = 0;
|
|
pNetwork->doRead = utils_net_read;
|
|
pNetwork->doWrite = utils_net_write;
|
|
pNetwork->doDisconnect = iotx_net_disconnect;
|
|
pNetwork->doConnect = iotx_net_connect;
|
|
|
|
return 0;
|
|
}
|