1 /* $Id: connecthostport.c,v 1.2 2010/04/05 00:08:15 nanard Exp $ */
3 * Author : Thomas Bernard
4 * Copyright (c) 2010 Thomas Bernard
5 * This software is subject to the conditions detailed in the
6 * LICENCE file provided in this distribution. */
8 /* use getaddrinfo() or gethostbyname()
9 * uncomment the following line in order to use gethostbyname() */
10 /* #define USE_GETHOSTBYNAME */
18 #define snprintf _snprintf
21 #else /* #ifdef WIN32 */
24 #define closesocket close
26 /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
27 * during the connect() call */
28 #define MINIUPNPC_IGNORE_EINTR
29 #ifndef USE_GETHOSTBYNAME
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #endif /* #ifndef USE_GETHOSTBYNAME */
33 #endif /* #else WIN32 */
35 /* definition of PRINT_SOCKET_ERROR */
37 #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
39 #define PRINT_SOCKET_ERROR(x) perror(x)
42 #if defined(__amigaos__) || defined(__amigaos4__)
43 #define herror(A) printf("%s\n", A)
46 #include "connecthostport.h"
49 * return a socket connected (TCP) to the host and port
50 * or -1 in case of error */
51 int connecthostport(const char * host
, unsigned short port
)
54 #ifdef USE_GETHOSTBYNAME
55 struct sockaddr_in dest
;
57 #else /* #ifdef USE_GETHOSTBYNAME */
59 struct addrinfo
*ai
, *p
;
60 struct addrinfo hints
;
61 #endif /* #ifdef USE_GETHOSTBYNAME */
62 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
63 struct timeval timeout
;
64 #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
66 #ifdef USE_GETHOSTBYNAME
67 hp
= gethostbyname(host
);
73 memcpy(&dest
.sin_addr
, hp
->h_addr
, sizeof(dest
.sin_addr
));
74 memset(dest
.sin_zero
, 0, sizeof(dest
.sin_zero
));
75 s
= socket(PF_INET
, SOCK_STREAM
, 0);
78 PRINT_SOCKET_ERROR("socket");
81 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
82 /* setting a 3 seconds timeout for the connect() call */
85 if(setsockopt(s
, SOL_SOCKET
, SO_RCVTIMEO
, &timeout
, sizeof(struct timeval
)) < 0)
87 PRINT_SOCKET_ERROR("setsockopt");
91 if(setsockopt(s
, SOL_SOCKET
, SO_SNDTIMEO
, &timeout
, sizeof(struct timeval
)) < 0)
93 PRINT_SOCKET_ERROR("setsockopt");
95 #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
96 dest
.sin_family
= AF_INET
;
97 dest
.sin_port
= htons(port
);
98 n
= connect(s
, (struct sockaddr
*)&dest
, sizeof(struct sockaddr_in
));
99 #ifdef MINIUPNPC_IGNORE_EINTR
100 while(n
< 0 && errno
== EINTR
)
107 if((n
= select(s
+ 1, NULL
, &wset
, NULL
, NULL
)) == -1 && errno
== EINTR
)
110 /*n = getpeername(s, NULL, &len);*/
112 if(getsockopt(s
, SOL_SOCKET
, SO_ERROR
, &err
, &len
) < 0) {
113 PRINT_SOCKET_ERROR("getsockopt");
122 #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
125 PRINT_SOCKET_ERROR("connect");
129 #else /* #ifdef USE_GETHOSTBYNAME */
130 /* use getaddrinfo() instead of gethostbyname() */
131 memset(&hints
, 0, sizeof(hints
));
132 /* hints.ai_flags = AI_ADDRCONFIG; */
133 #ifdef AI_NUMERICSERV
134 hints
.ai_flags
= AI_NUMERICSERV
;
136 hints
.ai_socktype
= SOCK_STREAM
;
137 hints
.ai_family
= AF_UNSPEC
; /* AF_INET, AF_INET6 or AF_UNSPEC */
138 /* hints.ai_protocol = IPPROTO_TCP; */
139 snprintf(port_str
, sizeof(port_str
), "%hu", port
);
140 n
= getaddrinfo(host
, port_str
, &hints
, &ai
);
144 fprintf(stderr
, "getaddrinfo() error : %d\n", n
);
146 fprintf(stderr
, "getaddrinfo() error : %s\n", gai_strerror(n
));
151 for(p
= ai
; p
; p
= p
->ai_next
)
153 s
= socket(p
->ai_family
, p
->ai_socktype
, p
->ai_protocol
);
156 #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
157 /* setting a 3 seconds timeout for the connect() call */
160 if(setsockopt(s
, SOL_SOCKET
, SO_RCVTIMEO
, &timeout
, sizeof(struct timeval
)) < 0)
162 PRINT_SOCKET_ERROR("setsockopt");
166 if(setsockopt(s
, SOL_SOCKET
, SO_SNDTIMEO
, &timeout
, sizeof(struct timeval
)) < 0)
168 PRINT_SOCKET_ERROR("setsockopt");
170 #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
171 n
= connect(s
, p
->ai_addr
, p
->ai_addrlen
);
172 #ifdef MINIUPNPC_IGNORE_EINTR
173 while(n
< 0 && errno
== EINTR
)
180 if((n
= select(s
+ 1, NULL
, &wset
, NULL
, NULL
)) == -1 && errno
== EINTR
)
183 /*n = getpeername(s, NULL, &len);*/
185 if(getsockopt(s
, SOL_SOCKET
, SO_ERROR
, &err
, &len
) < 0) {
186 PRINT_SOCKET_ERROR("getsockopt");
196 #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
210 PRINT_SOCKET_ERROR("socket");
215 PRINT_SOCKET_ERROR("connect");
218 #endif /* #ifdef USE_GETHOSTBYNAME */