blob: d52abdbfd232cd09693103d135f7ef269fd8be6e [file] [log] [blame]
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/select.h>
#include <signal.h>
#include <sys/time.h>
#include "mbtk_sock.h"
#include "mbtk_log.h"
int sock_net_open(mbtk_net_info_s *net_info, mbtk_addr_family_e addr_family)
{
return 0;
}
int sock_open(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, uint32 timeout, int *err)
{
if(net_info == NULL || sock_info == NULL) {
LOGE("ARG error.");
return -1;
}
int family = AF_INET;
if(sock_info->addr_family == MBTK_ADDR_IPV6) { // Only IPv6
family = AF_INET6;
}
if(sock_info->sock_type == MBTK_SOCK_UDP) { // UDP
// socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if((sock_info->fd = socket(family, SOCK_DGRAM, IPPROTO_UDP)) < 0){
LOGE("socket() fail.[%d]",errno);
goto result_fail;
}
} else if(sock_info->sock_type == MBTK_SOCK_TCP){ // TCP
if((sock_info->fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0){
LOGE("socket() fail.[%d]",errno);
goto result_fail;
}
} else {
LOGE("Unknown socket type:%d", sock_info->sock_type);
return -1;
}
#if 1
// Set O_NONBLOCK
int flags = fcntl(sock_info->fd, F_GETFL, 0);
if (flags < 0) {
LOGE("Get flags error:%d", errno);
goto result_fail_with_close;
}
flags |= O_NONBLOCK;
if (fcntl(sock_info->fd, F_SETFL, flags) < 0) {
LOGE("Set flags error:%d", errno);
goto result_fail_with_close;
}
#endif
// Connect
LOGD("Start conn:%s:%d",sock_info->host,sock_info->port);
if (strlen(sock_info->host) > 0 && sock_info->port > 0)
{
if(family == AF_INET6)
{
struct addrinfo hints;
struct addrinfo *answer, *curr;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6; /* Allow IPv4 or IPv6 */
hints.ai_socktype = sock_info->sock_type; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
int ret = getaddrinfo(sock_info->host, NULL, &hints, &answer);
if(ret < 0)
{
printf("\ngetaddrinfo error\n");
goto result_fail_with_close;
}
struct sockaddr_in6 *addr_in6=NULL;
struct sockaddr_in6 serverSockAddr;
bzero(&serverSockAddr, sizeof(struct sockaddr_in6));
serverSockAddr.sin6_family = AF_INET6;
serverSockAddr.sin6_port = htons(sock_info->port);
//memcpy(&serverSockAddr.sin6_addr, he->h_addr_list[0], sizeof(struct in6_addr));
//memcpy(&sock_info->addr.addr.dst_sock_addr6.sin6_addr, he->h_addr_list[0], sizeof(struct in_addr));
sock_info->addr.addr_len = sizeof(struct sockaddr_in6);
for (curr = answer; curr != NULL; curr = curr->ai_next)
{
addr_in6 = (struct sockaddr_in6 *)curr->ai_addr;
memcpy(&(serverSockAddr.sin6_addr), &(addr_in6->sin6_addr), sizeof(struct in6_addr));
}
if (connect(sock_info->fd, &serverSockAddr, sizeof(struct sockaddr_in6)) < 0)
{
if (EINPROGRESS != errno)
{
LOGE("connect() fail.[%d]", errno);
goto result_fail_with_close;
}
}
}
else
{
struct hostent *he = gethostbyname(sock_info->host);
if (he == NULL)
{
LOGE("gethostbyname() fail.[%d]", errno);
goto result_fail_with_close;
}
struct sockaddr_in serverSockAddr;
bzero(&serverSockAddr, sizeof(struct sockaddr_in));
serverSockAddr.sin_family = AF_INET;
serverSockAddr.sin_port = htons(sock_info->port);
memcpy(&serverSockAddr.sin_addr, he->h_addr_list[0], sizeof(struct in_addr));
log_hex("IPv4", he->h_addr_list[0], sizeof(struct in_addr));
memcpy(&sock_info->addr.addr.serverSockAddr.sin_addr, he->h_addr_list[0], sizeof(struct in_addr));
sock_info->addr.addr_len = sizeof(struct sockaddr_in);
if (connect(sock_info->fd, (struct sockaddr *) &serverSockAddr, sizeof(serverSockAddr)) < 0)
{
if (EINPROGRESS != errno)
{
LOGE("connect() fail.[%d]", errno);
goto result_fail_with_close;
}
}
}
fd_set rset, wset;
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(sock_info->fd, &rset);
FD_SET(sock_info->fd, &wset);
struct timeval time_out;
/*
time_out.tv_sec = timeout / 1000;
time_out.tv_usec = timeout % 1000 * 1000;
*/
time_out.tv_sec = 100;
time_out.tv_usec = 0;
int nready = select(sock_info->fd + 1, &rset, &wset, NULL, &time_out);
LOGD("nready = %d", nready);
if (nready == 0) // Timeout
{
LOGE("Timeout.");
goto result_fail_with_close;
}
else
{
if (FD_ISSET(sock_info->fd, &rset) && FD_ISSET(sock_info->fd, &wset))
{
int error = -1;
socklen_t len = sizeof(int);
LOGE("Can read and write.");
if (getsockopt(sock_info->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
{
LOGE("getsockopt fail.[%d]", errno);
goto result_fail_with_close;
}
else
{
LOGE("error = %d", error);
if (error != 0) // Fail
{
goto result_fail_with_close;
}
}
}
else if (FD_ISSET(sock_info->fd, &wset))
{
LOGI("Can write.");
}
else
{
LOGE("Can read(Impossible).");
goto result_fail_with_close;
}
}
}
else
{
LOGE("Can not conn.");
goto result_fail_with_close;
}
if (sock_info->is_ssl)
{
}
sock_info->read_buff.buffer = (char*)malloc(MBTK_BUFF_SIZE);
if(sock_info->read_buff.buffer) {
memset(sock_info->read_buff.buffer, 0x0, MBTK_BUFF_SIZE);
sock_info->read_buff.size = 0;
sock_info->read_buff.size_max = MBTK_BUFF_SIZE;
} else {
LOGE("malloc() fail.");
goto result_fail_with_close;
}
return sock_info->fd;
result_fail_with_close:
close(sock_info->fd);
sock_info->fd = -1;
result_fail:
LOGE("mbtk_sock_open() end:fail");
return -1;
}
int sock_addr_set(mbtk_net_info_s *net_info,mbtk_sock_info_s *sock_info,void *host, uint32 port)
{
if(sock_info->fd <= 0) {
LOGE("Socket not open.");
return -1;
}
sock_info->addr.addr.serverSockAddr.sin_family = AF_INET;
sock_info->addr.addr.serverSockAddr.sin_port = htons(port);
struct hostent *he = gethostbyname(host);
if (he == NULL)
{
LOGE("gethostbyname() fail.[%d]", errno);
return -1;
}
else
{
LOGD("Ip(len-%d)", he->h_length);
int i = 0;
for(;i < he->h_length;i++){
LOGD("Ip Addr[%d]:%.2x", i, 0x0FF & he->h_addr_list[0][i]);
}
}
memcpy(&sock_info->addr.addr.serverSockAddr.sin_addr, he->h_addr_list[0], sizeof(struct in_addr));
sock_info->addr.addr_len = sizeof(struct sockaddr_in);
return 0;
}
int sock_bind(int sockfd, bool is_ipv6, uint16 port)
{
int ret_val;
struct sockaddr *ds_sockaddr = NULL;
struct sockaddr_in localaddr;
uint16 addr_legth = 0;
memset((char *) &localaddr, 0, sizeof(struct sockaddr_in));
localaddr.sin_family = AF_INET;
localaddr.sin_addr.s_addr = INADDR_ANY;
localaddr.sin_port = htons(port);
addr_legth = sizeof(struct sockaddr_in);
ds_sockaddr = (struct sockaddr *)&localaddr;
ret_val = bind(sockfd,ds_sockaddr,addr_legth);
if (ret_val < 0){
LOGE("bind() sockfd= %d fail", sockfd);
return -1;
}
return 0;
}
int sock_read(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, void *buffer, uint32 buf_len, uint32 timeout, int *err)
{
unsigned int count = 0;
int len = 0;
int try_count = 0;
int times = timeout / 50;
memset(buffer, 0x0, buf_len);
while (count < buf_len)
{
try_count++;
if (sock_info->is_ssl)
{
}
else
{
len = read(sock_info->fd, (char*) buffer + count, buf_len - count);
}
if (len <= 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
{
if (count > 0) // Read data
break; // Read data end.
if (try_count >= times) // Timeout
{
count = -1;
if (times != 0)
{
*err = 10; // FTP_ERR_NET_TIMEOUT
}
LOGE("Not read enough data,return.[%d/%d]", count, buf_len);
break;
}
else
{
usleep(50000);
continue;
}
}
else
{
LOGD("read error.[%d]", errno);
if (errno == EINPROGRESS)
{
if (close(sock_info->fd) == 0) // Success
{
LOGD("Socket disconnected.Close it.");
sock_info->fd = -1;
}
if (count <= 0)
count = -1;
}
else
{
if (count <= 0)
count = 0;
}
break;
}
}
else
{
count += len;
}
}
LOGV("Read data[%d/%d].", count, buf_len);
return count;
}
int sock_read_async(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, void *buffer, uint32 buf_len, uint32 timeout, int *err)
{
int len = -1;
int try_count = 0;
int times = timeout / 50;
TCP_READ_AGAIN:
memset(buffer, 0x0, buf_len);
try_count++;
if (sock_info->is_ssl)
{
}
else
{
len = read(sock_info->fd, (char*) buffer, buf_len);
}
if (len < 0)
{
if (errno == EWOULDBLOCK)
{
if(try_count == times)
{
LOGD("read timeout");
return -1;
}
usleep(50000);
goto TCP_READ_AGAIN;
}
else
{
LOGE("read error.[%d]", errno);
return -1;
}
}
LOGV("Read data[%d/%d].", len, buf_len);
return len;
}
#if 0
int sock_readline(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, void *buffer, uint32 buf_len, uint32 timeout, int *err)
{
if (sock_info->fd > 0)
{
char *buf_ptr = (char*)buffer;
char read_buf[1];
int read_len = 0;
while (TRUE)
{
if (sock_read_async(net_info, sock_info, read_buf, 1, timeout, err) == 1)
{
*buf_ptr++ = read_buf[0];
read_len++;
if (read_buf[0] == '\n' || read_len >= buf_len)
{
return read_len;
}
}
else
{
return -1;
}
}
}
return -1;
}
#else
int sock_readline(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, void *buffer, uint32 buf_len, uint32 timeout, int *err)
{
if (sock_info->fd > 0)
{
memset(buffer,0,buf_len);
int read_len = 0;
char *buf_ptr = (char*)buffer;
char *temp_ptr = sock_info->read_buff.buffer;
LOGV("TEMP buffer[fd - %d, len-%d]:%s", sock_info->fd, sock_info->read_buff.size, sock_info->read_buff.buffer);
copy_angin:
while(sock_info->read_buff.size > 0 && *temp_ptr != '\n') {
*buf_ptr++ = *temp_ptr++;
sock_info->read_buff.size--;
read_len++;
}
LOGV("SIZE : %d,TEMP is \\n : %d", sock_info->read_buff.size, *temp_ptr == '\n');
if(sock_info->read_buff.size == 0) {
sock_info->read_buff.size = sock_read(net_info, sock_info, sock_info->read_buff.buffer,
sock_info->read_buff.size_max, timeout, err);
if(sock_info->read_buff.size <= 0) {
if(read_len == 0) { // No data.
LOGE("sock_read() fail.");
return -1;
} else {
return read_len;
}
}
temp_ptr = sock_info->read_buff.buffer;
goto copy_angin;
} else if(*temp_ptr == '\n') { // Read line.
*buf_ptr++ = '\n';
sock_info->read_buff.size--;
read_len++;
if(sock_info->read_buff.size > 0)
memcpy(sock_info->read_buff.buffer, temp_ptr + 1, sock_info->read_buff.size);
return read_len;
}
}
return -1;
}
#endif
int sock_write(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, const void *buffer, uint32 buf_len, uint32 timeout, int *err)
{
int len = 0;
uint32 try_count = 0;
uint32 times = timeout * 100;
unsigned int count = 0;
while (count < buf_len)
{
try_count++;
if (sock_info->is_ssl)
{
//printf(" try_count = %d timeout = %d sock_info->is_ssl = 1\n",try_count,timeout);
if(try_count >= times)
{
printf("over time \n");
break;
}
}
else
{
len = write(sock_info->fd, (const char*)buffer + count, buf_len - count);
}
if (len < 0)
{
if (errno == EWOULDBLOCK)
{
usleep(50000);
continue;
}
else
{
LOGE("write error.[%d]", errno);
if (count <= 0)
count = -1;
break;
}
}
else if (len == 0)
{
LOGE("write error(len == 0).[%d]", errno);
}
else
{
count += len;
}
}
if (count > 0)
{
LOGV("Write data[%d/%d] success.", count, buf_len);
}
else // Open session fail
{
LOGV("Write data[%d/%d] fail.", count, buf_len);
}
return count;
}
int sock_recv(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, void *buffer, uint32 buf_len, uint32 timeout)
{
unsigned int count = 0;
int len = 0;
int try_count = 0;
int times = timeout / 50; // ms
memset(buffer, 0x0, buf_len);
while (count < buf_len)
{
try_count++;
len = recvfrom(sock_info->fd, (char*) buffer + count, buf_len - count, 0,
(struct sockaddr *)&sock_info->addr.addr.serverSockAddr, (socklen_t *)&sock_info->addr.addr_len);
if (len <= 0)
{
if (errno == EWOULDBLOCK || errno == EAGAIN)
{
if (count > 0) // Read data
break; // Read data end.
if (try_count >= times) // Timeout
{
count = -1;
break;
}
else
{
usleep(50000);
continue;
}
}
else if (errno == EINPROGRESS)
{
if (close(sock_info->fd) == 0) // Success
{
LOGD("Socket disconnected.Close it.");
}
if (count <= 0)
count = -1;
break;
}
else
{
LOGE("recv error.[%d]", errno);
if (count <= 0)
count = -1;
break;
}
}
else
{
count += len;
}
}
LOGV("Read data[%d/%d].", count, buf_len);
return count;
}
int sock_sendto(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, const void *buffer, uint32 buf_len, uint32 timeout)
{
int len = 0;
unsigned int count = 0;
int try_count = 0;
int times = timeout / 50; // ms
while (count < buf_len)
{
try_count++;
len = sendto(sock_info->fd,(char*) buffer + count, buf_len - count, 0,
(struct sockaddr *)&sock_info->addr.addr.serverSockAddr, sock_info->addr.addr_len);
if (len < 0)
{
if (errno == EWOULDBLOCK)
{
if (count > 0) // Send part data
break;
if (try_count >= times) // Timeout
{
count = -1;
break;
}
else
{
usleep(50000);
continue;
}
}
else
{
LOGE("sendto error.[%d]", errno);
if (count <= 0)
count = -1;
break;
}
}
else if (len == 0)
{
LOGE("write error(len == 0).[%d]", errno);
}
else
{
count += len;
}
}
if (count == buf_len)
{
LOGV("Sendto data[%d/%d] success.", count, buf_len);
}
else
{
LOGV("Sendto data[%d/%d] fail.", count, buf_len);
}
return count;
}
int sock_close(mbtk_net_info_s *net_info, mbtk_sock_info_s *sock_info, uint32 timeout, int *err)
{
if(sock_info->fd > 0) {
if(close(sock_info->fd) < 0)
{
LOGE("Close socket fail[%d].", errno);
return -1;
}
sock_info->fd = -1;
}
if(sock_info->read_buff.buffer) {
free(sock_info->read_buff.buffer);
sock_info->read_buff.buffer = NULL;
}
return 0;
}
int sock_net_close(mbtk_net_info_s *net_info, uint32 timeout, int *err)
{
return 0;
}