2020-12-04 08:06:26 +09:00
|
|
|
#include <signal.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
2020-12-04 13:39:58 +09:00
|
|
|
#include <poll.h>
|
2020-12-04 15:56:21 +09:00
|
|
|
#include <netdb.h>
|
|
|
|
#include <string.h>
|
2020-12-04 08:06:26 +09:00
|
|
|
#include "socket_wrapper.h"
|
|
|
|
|
|
|
|
int getBufferSizeFrom(int sock){
|
|
|
|
int buffer_sz;
|
|
|
|
socklen_t len = sizeof(buffer_sz);
|
2020-12-04 14:25:10 +09:00
|
|
|
//getsockopt is thread-safe
|
2020-12-04 08:06:26 +09:00
|
|
|
if(getsockopt(sock,SOL_SOCKET,SO_SNDBUF,&buffer_sz,&len) < 0){
|
|
|
|
perror("failed to get sock buffer size: getsockopt");
|
|
|
|
buffer_sz = DEFAULT_BUF_SIZE;/*set to default*/
|
|
|
|
}
|
|
|
|
if(buffer_sz < MINIMUM_BUF_SIZE)
|
|
|
|
buffer_sz = MINIMUM_BUF_SIZE;
|
|
|
|
return buffer_sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t timeout_recv(int fd,void * buf,size_t n,int timeout)
|
|
|
|
{
|
2020-12-04 19:10:48 +09:00
|
|
|
ssize_t ret = 0;
|
2020-12-04 13:39:58 +09:00
|
|
|
int poll_ret;
|
2020-12-05 10:25:54 +09:00
|
|
|
int try = 0;
|
2020-12-04 13:39:58 +09:00
|
|
|
struct pollfd fd_single;
|
2020-12-05 10:25:54 +09:00
|
|
|
timeout = timeout * 1000;
|
|
|
|
if (n == 0) return 0;
|
|
|
|
for(;;){
|
|
|
|
fd_single.fd = fd;
|
|
|
|
fd_single.events = POLL_IN;
|
|
|
|
poll_ret = (poll(&fd_single,1,timeout));
|
|
|
|
if (poll_ret < 0){ fprintf(stderr,"timeout %d\n",timeout); return -1;}
|
|
|
|
else if(poll_ret == 0) return -2;
|
|
|
|
if (fd_single.revents & POLLHUP) //We'll treat hangups state like timeouts state.
|
|
|
|
return -2;
|
|
|
|
if ((fd_single.revents & POLLERR) || (fd_single.revents & POLLNVAL))
|
|
|
|
return -1;
|
|
|
|
if (fd_single.revents & POLL_IN){
|
|
|
|
ret = recv(fd,buf,n,0);
|
|
|
|
if(ret != 0) return ret;
|
|
|
|
//try 3 times
|
|
|
|
if (try < 3){
|
|
|
|
try++;
|
|
|
|
timeout /= 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
}
|
2020-12-04 14:25:10 +09:00
|
|
|
assert(0 && "unreachable");
|
2020-12-04 08:06:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t recv_until_byte(int fd,void * buf, size_t n,int timeout){
|
|
|
|
ssize_t cur = 0;
|
|
|
|
uint8_t * b = buf;
|
|
|
|
while (cur < n)
|
|
|
|
{
|
|
|
|
ssize_t r = timeout_recv(fd,&b[cur],n-cur,timeout);
|
|
|
|
if (r < 0){
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
cur += r;
|
|
|
|
}
|
|
|
|
assert(cur == n);
|
|
|
|
return cur;
|
2020-12-04 15:56:21 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
int getsockaddrbyname(int domain,int type, int protocol, const char * hostname_str, struct sockaddr * retaddr){
|
|
|
|
struct addrinfo hints;
|
|
|
|
struct addrinfo * result, *entry;
|
|
|
|
int ret, i;
|
|
|
|
memset(&hints,0,sizeof(hints));
|
|
|
|
hints.ai_family = domain;
|
|
|
|
hints.ai_socktype = type;
|
|
|
|
hints.ai_flags = 0;
|
|
|
|
hints.ai_protocol = protocol;
|
|
|
|
|
|
|
|
//try 5 times
|
2020-12-04 16:48:03 +09:00
|
|
|
for (i = 0; i < 5; i++)
|
2020-12-04 15:56:21 +09:00
|
|
|
{
|
2020-12-04 16:48:03 +09:00
|
|
|
ret = getaddrinfo(hostname_str,NULL,&hints,&result);
|
2020-12-04 15:56:21 +09:00
|
|
|
if(ret == EAI_AGAIN) continue;
|
|
|
|
else if (ret != 0) return ret;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ret != 0) return ret; //maybe name server doesn't work properly.
|
|
|
|
|
|
|
|
for (entry = result; entry != NULL; entry = entry->ai_next){
|
|
|
|
memcpy(retaddr,entry->ai_addr,sizeof(*retaddr));
|
|
|
|
}
|
|
|
|
freeaddrinfo(result);
|
|
|
|
return ret;
|
2020-12-04 08:06:26 +09:00
|
|
|
}
|