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, api_posix_struct_addrinfo** sai)
79 api_posix_struct_addrinfo hints;
85 memset((
void*) &hints, 0,
sizeof(hints));
87 hints.ai_flags = API_POSIX_AI_ADDRCONFIG;
89 hints.ai_socktype = API_POSIX_SOCK_STREAM;
90 hints.ai_protocol = 0;
91 rv = api_posix_getaddrinfo(host, service, &hints, sai);
95 #if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
97 api_posix_setlocale(API_POSIX_LC_MESSAGES,
"POSIX");
99 err_str = api_posix_gai_strerror(rv);
100 #if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
101 api_posix_setlocale(API_POSIX_LC_MESSAGES,
"");
106 len += strlen(err_str);
107 ebuf = (
char*) api_posix_malloc(++len);
111 strcat(ebuf, err_str);
114 api_posix_free((
void*) ebuf);
118 case API_POSIX_EAI_FAMILY: { res =
INET_ERR_AF;
break; }
119 case API_POSIX_EAI_NONAME: { res =
INET_ERR_HNR;
break; }
120 case API_POSIX_EAI_SERVICE: { res =
INET_ERR_SNR;
break; }
146 static int inet_socket_create(
int* sd,
int af)
151 if(API_POSIX_AF_INET != af
153 && API_POSIX_AF_INET6 != af
157 PRINT_ERROR(
"socket(): Address family not supported");
162 *sd = api_posix_socket(af, API_POSIX_SOCK_STREAM, 0);
174 rv = api_posix_fcntl(*sd, API_POSIX_F_SETFD, API_POSIX_FD_CLOEXEC);
176 while(-1 == rv && API_POSIX_EINTR == api_posix_errno);
190 #if CFG_USE_CONNECT_TIMEOUT
203 static int inet_socket_options(
int sd,
int action,
int opts)
210 do { rv = api_posix_fcntl(sd, API_POSIX_F_GETFL); }
211 while(-1 == rv && API_POSIX_EINTR == api_posix_errno);
222 else { opts_new = rv & ~opts; }
225 do { rv = api_posix_fcntl(sd, API_POSIX_F_SETFL, opts_new); }
226 while(-1 == rv && API_POSIX_EINTR == api_posix_errno);
265 int inet_connect(
int* sd,
int* af,
const char* host,
const char* service)
269 api_posix_struct_addrinfo* sai;
270 api_posix_struct_addrinfo* saie;
273 api_posix_struct_pollfd fds[1];
274 api_posix_socklen_t opt_len;
275 #if CFG_USE_CONNECT_TIMEOUT
276 api_posix_time_t ts1 = 0, ts2, ts_diff;
285 if(inet_force_ipv4) { *af = API_POSIX_AF_INET; }
288 res = inet_name_resolver(host, service, *af, &sai);
291 for(saie = sai; saie != NULL; saie = saie->ai_next)
294 family = saie->ai_family;
295 res = inet_socket_create(&socket, family);
296 #if CFG_USE_CONNECT_TIMEOUT
301 API_POSIX_O_NONBLOCK);
303 ts1 = api_posix_time(NULL);
304 if((api_posix_time_t) 0 > ts1) { ts1 = 0; }
312 rv = api_posix_connect(socket, saie->ai_addr, saie->ai_addrlen);
315 if(API_POSIX_ECONNREFUSED == api_posix_errno) { refused = 1; }
319 (API_POSIX_EINPROGRESS == api_posix_errno
320 || API_POSIX_EINTR == api_posix_errno))
329 #if CFG_USE_CONNECT_TIMEOUT
332 ts2 = api_posix_time(NULL);
333 if((api_posix_time_t) 0 > ts2) { ts2 = 0; }
335 if ((
float) CFG_USE_CONNECT_TIMEOUT < (
float) ts_diff)
342 fds[0].events = API_POSIX_POLLOUT;
344 rv = api_posix_poll(fds, 1, timeout);
347 (-1 == rv && API_POSIX_EINTR == api_posix_errno));
348 if(0 == rv) { timed_out = 1; }
352 opt_len =
sizeof(int);
353 rv = api_posix_getsockopt(socket, API_POSIX_SOL_SOCKET,
354 API_POSIX_SO_ERROR, &res, &opt_len);
359 #if CFG_USE_CONNECT_TIMEOUT
364 API_POSIX_O_NONBLOCK);
374 PRINT_ERROR(
"User defined TCP connection timeout");
383 if(API_POSIX_AF_INET == family)
386 "Using IPv4 protocol");
389 else if(API_POSIX_AF_INET6 == family)
392 "Using IPv6 protocol");
401 api_posix_freeaddrinfo(sai);
437 api_posix_struct_timeval rx;
443 rx.tv_sec = (api_posix_time_t) rx_to;
445 rv = api_posix_setsockopt(sd, API_POSIX_SOL_SOCKET,
446 API_POSIX_SO_RCVTIMEO, (
void*) &rx,
447 (api_posix_socklen_t)
448 sizeof(api_posix_struct_timeval));
453 if(API_POSIX_ENOPROTOOPT == api_posix_errno)
457 if(API_POSIX_EBADF != api_posix_errno
458 && API_POSIX_ENOTSOCK != errno)
500 api_posix_struct_timeval tx;
506 tx.tv_sec = (api_posix_time_t) tx_to;
508 rv = api_posix_setsockopt(sd, API_POSIX_SOL_SOCKET,
509 API_POSIX_SO_SNDTIMEO, (
void*) &tx,
510 (api_posix_socklen_t)
511 sizeof(api_posix_struct_timeval));
516 if(API_POSIX_ENOPROTOOPT == api_posix_errno)
520 if(API_POSIX_EBADF != api_posix_errno
521 && API_POSIX_ENOTSOCK != errno)
552 api_posix_close(*sd);