36 #define MAIN_ERR_PREFIX "INET: "
40 #define INET_OPTS_CLEAR 0
41 #define INET_OPTS_SET 1
48 int inet_force_ipv4 = 0;
75 static int inet_name_resolver(
const char* host,
const char* service,
76 int af, struct_posix_addrinfo** sai)
79 struct_posix_addrinfo hints;
85 memset((
void*) &hints, 0,
sizeof(hints));
87 hints.ai_flags = POSIX_AI_ADDRCONFIG;
89 hints.ai_socktype = POSIX_SOCK_STREAM;
90 hints.ai_protocol = 0;
91 rv = posix_getaddrinfo(host, service, &hints, sai);
95 err_str = posix_gai_strerror(rv);
99 len += strlen(err_str);
100 ebuf = (
char*) posix_malloc(++len);
104 strcat(ebuf, err_str);
107 posix_free((
void*) ebuf);
111 case POSIX_EAI_FAMILY: { res =
INET_ERR_AF;
break; }
138 static int inet_socket_create(
int* sd,
int af)
143 if(POSIX_AF_INET != af
145 && POSIX_AF_INET6 != af
149 PRINT_ERROR(
"socket(): Address family not supported");
154 *sd = posix_socket(af, POSIX_SOCK_STREAM, 0);
164 do { rv = posix_fcntl(*sd, POSIX_F_SETFD, POSIX_FD_CLOEXEC); }
165 while(-1 == rv && POSIX_EINTR == posix_errno);
179 #if CFG_USE_CONNECT_TIMEOUT
192 static int inet_socket_options(
int sd,
int action,
int opts)
199 do { rv = posix_fcntl(sd, POSIX_F_GETFL); }
200 while(-1 == rv && POSIX_EINTR == posix_errno);
211 else { opts_new = rv & ~opts; }
214 do { rv = posix_fcntl(sd, POSIX_F_SETFL, opts_new); }
215 while(-1 == rv && POSIX_EINTR == posix_errno);
254 int inet_connect(
int* sd,
int* af,
const char* host,
const char* service)
258 struct_posix_addrinfo* sai;
259 struct_posix_addrinfo* saie;
262 struct_posix_pollfd fds[1];
263 posix_socklen_t opt_len;
264 #if CFG_USE_CONNECT_TIMEOUT
265 posix_time_t ts1, ts2, ts_diff;
274 if(inet_force_ipv4) { *af = POSIX_AF_INET; }
277 res = inet_name_resolver(host, service, *af, &sai);
280 for(saie = sai; saie != NULL; saie = saie->ai_next)
283 family = saie->ai_family;
284 res = inet_socket_create(&socket, family);
285 #if CFG_USE_CONNECT_TIMEOUT
289 res = inet_socket_options(socket,
INET_OPTS_SET, POSIX_O_NONBLOCK);
291 ts1 = posix_time(NULL);
292 if((posix_time_t) 0 > ts1) { ts1 = 0; }
300 rv = posix_connect(socket, saie->ai_addr, saie->ai_addrlen);
303 if(POSIX_ECONNREFUSED == posix_errno) { refused = 1; }
307 (POSIX_EINPROGRESS == posix_errno || POSIX_EINTR == posix_errno))
316 #if CFG_USE_CONNECT_TIMEOUT
319 ts2 = posix_time(NULL);
320 if((posix_time_t) 0 > ts2) { ts2 = 0; }
322 if ((
float) CFG_USE_CONNECT_TIMEOUT < (
float) ts_diff)
329 fds[0].events = POSIX_POLLOUT;
331 rv = posix_poll(fds, 1, timeout);
333 while(0 == rv || (-1 == rv && POSIX_EINTR == posix_errno));
334 if(0 == rv) { timed_out = 1; }
338 opt_len =
sizeof(int);
339 rv = posix_getsockopt(socket, POSIX_SOL_SOCKET,
340 POSIX_SO_ERROR, &res, &opt_len);
345 #if CFG_USE_CONNECT_TIMEOUT
360 PRINT_ERROR(
"User defined TCP connection timeout");
369 if(POSIX_AF_INET == family)
372 "Using IPv4 protocol");
375 else if(POSIX_AF_INET6 == family)
378 "Using IPv6 protocol");
387 posix_freeaddrinfo(sai);
423 struct_posix_timeval rx;
429 rx.tv_sec = (posix_time_t) rx_to;
431 rv = posix_setsockopt(sd, POSIX_SOL_SOCKET, POSIX_SO_RCVTIMEO,
433 (posix_socklen_t)
sizeof(struct_posix_timeval));
439 if(POSIX_EBADF != posix_errno && POSIX_ENOTSOCK != errno)
481 struct_posix_timeval tx;
487 tx.tv_sec = (posix_time_t) tx_to;
489 rv = posix_setsockopt(sd, POSIX_SOL_SOCKET, POSIX_SO_SNDTIMEO,
491 (posix_socklen_t)
sizeof(struct_posix_timeval));
497 if(POSIX_EBADF != posix_errno && POSIX_ENOTSOCK != errno)