Annotation of embedaddon/miniupnpc/connecthostport.c, revision 1.1.1.1
1.1 misho 1: /* $Id: connecthostport.c,v 1.5 2011/04/09 08:49:50 nanard Exp $ */
2: /* Project : miniupnp
3: * Author : Thomas Bernard
4: * Copyright (c) 2010-2011 Thomas Bernard
5: * This software is subject to the conditions detailed in the
6: * LICENCE file provided in this distribution. */
7:
8: /* use getaddrinfo() or gethostbyname()
9: * uncomment the following line in order to use gethostbyname() */
10: #ifdef NO_GETADDRINFO
11: #define USE_GETHOSTBYNAME
12: #endif
13:
14: #include <string.h>
15: #include <stdio.h>
16: #ifdef WIN32
17: #include <winsock2.h>
18: #include <ws2tcpip.h>
19: #include <io.h>
20: #define MAXHOSTNAMELEN 64
21: #define snprintf _snprintf
22: #define herror
23: #define socklen_t int
24: #else /* #ifdef WIN32 */
25: #include <unistd.h>
26: #include <sys/param.h>
27: #include <errno.h>
28: #define closesocket close
29: #include <netdb.h>
30: /* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions
31: * during the connect() call */
32: #define MINIUPNPC_IGNORE_EINTR
33: #ifndef USE_GETHOSTBYNAME
34: #include <sys/types.h>
35: #include <sys/socket.h>
36: #endif /* #ifndef USE_GETHOSTBYNAME */
37: #endif /* #else WIN32 */
38:
39: /* definition of PRINT_SOCKET_ERROR */
40: #ifdef WIN32
41: #define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError());
42: #else
43: #define PRINT_SOCKET_ERROR(x) perror(x)
44: #endif
45:
46: #if defined(__amigaos__) || defined(__amigaos4__)
47: #define herror(A) printf("%s\n", A)
48: #endif
49:
50: #include "connecthostport.h"
51:
52: /* connecthostport()
53: * return a socket connected (TCP) to the host and port
54: * or -1 in case of error */
55: int connecthostport(const char * host, unsigned short port)
56: {
57: int s, n;
58: #ifdef USE_GETHOSTBYNAME
59: struct sockaddr_in dest;
60: struct hostent *hp;
61: #else /* #ifdef USE_GETHOSTBYNAME */
62: char tmp_host[MAXHOSTNAMELEN+1];
63: char port_str[8];
64: struct addrinfo *ai, *p;
65: struct addrinfo hints;
66: #endif /* #ifdef USE_GETHOSTBYNAME */
67: #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
68: struct timeval timeout;
69: #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
70:
71: #ifdef USE_GETHOSTBYNAME
72: hp = gethostbyname(host);
73: if(hp == NULL)
74: {
75: herror(host);
76: return -1;
77: }
78: memcpy(&dest.sin_addr, hp->h_addr, sizeof(dest.sin_addr));
79: memset(dest.sin_zero, 0, sizeof(dest.sin_zero));
80: s = socket(PF_INET, SOCK_STREAM, 0);
81: if(s < 0)
82: {
83: PRINT_SOCKET_ERROR("socket");
84: return -1;
85: }
86: #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
87: /* setting a 3 seconds timeout for the connect() call */
88: timeout.tv_sec = 3;
89: timeout.tv_usec = 0;
90: if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
91: {
92: PRINT_SOCKET_ERROR("setsockopt");
93: }
94: timeout.tv_sec = 3;
95: timeout.tv_usec = 0;
96: if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
97: {
98: PRINT_SOCKET_ERROR("setsockopt");
99: }
100: #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
101: dest.sin_family = AF_INET;
102: dest.sin_port = htons(port);
103: n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in));
104: #ifdef MINIUPNPC_IGNORE_EINTR
105: while(n < 0 && errno == EINTR)
106: {
107: socklen_t len;
108: fd_set wset;
109: int err;
110: FD_ZERO(&wset);
111: FD_SET(s, &wset);
112: if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
113: continue;
114: /*len = 0;*/
115: /*n = getpeername(s, NULL, &len);*/
116: len = sizeof(err);
117: if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
118: PRINT_SOCKET_ERROR("getsockopt");
119: closesocket(s);
120: return -1;
121: }
122: if(err != 0) {
123: errno = err;
124: n = -1;
125: }
126: }
127: #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
128: if(n<0)
129: {
130: PRINT_SOCKET_ERROR("connect");
131: closesocket(s);
132: return -1;
133: }
134: #else /* #ifdef USE_GETHOSTBYNAME */
135: /* use getaddrinfo() instead of gethostbyname() */
136: memset(&hints, 0, sizeof(hints));
137: /* hints.ai_flags = AI_ADDRCONFIG; */
138: #ifdef AI_NUMERICSERV
139: hints.ai_flags = AI_NUMERICSERV;
140: #endif
141: hints.ai_socktype = SOCK_STREAM;
142: hints.ai_family = AF_UNSPEC; /* AF_INET, AF_INET6 or AF_UNSPEC */
143: /* hints.ai_protocol = IPPROTO_TCP; */
144: snprintf(port_str, sizeof(port_str), "%hu", port);
145: if(host[0] == '[')
146: {
147: /* literal ip v6 address */
148: int i;
149: for(i = 0; host[i+1] && (host[i+1] != ']') && i < MAXHOSTNAMELEN; i++)
150: {
151: tmp_host[i] = host[i+1];
152: }
153: tmp_host[i] = '\0';
154: }
155: else
156: {
157: strncpy(tmp_host, host, MAXHOSTNAMELEN);
158: }
159: tmp_host[MAXHOSTNAMELEN] = '\0';
160: n = getaddrinfo(tmp_host, port_str, &hints, &ai);
161: if(n != 0)
162: {
163: #ifdef WIN32
164: fprintf(stderr, "getaddrinfo() error : %d\n", n);
165: #else
166: fprintf(stderr, "getaddrinfo() error : %s\n", gai_strerror(n));
167: #endif
168: return -1;
169: }
170: s = -1;
171: for(p = ai; p; p = p->ai_next)
172: {
173: s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
174: if(s < 0)
175: continue;
176: #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
177: /* setting a 3 seconds timeout for the connect() call */
178: timeout.tv_sec = 3;
179: timeout.tv_usec = 0;
180: if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)) < 0)
181: {
182: PRINT_SOCKET_ERROR("setsockopt");
183: }
184: timeout.tv_sec = 3;
185: timeout.tv_usec = 0;
186: if(setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)) < 0)
187: {
188: PRINT_SOCKET_ERROR("setsockopt");
189: }
190: #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
191: n = connect(s, p->ai_addr, p->ai_addrlen);
192: #ifdef MINIUPNPC_IGNORE_EINTR
193: while(n < 0 && errno == EINTR)
194: {
195: socklen_t len;
196: fd_set wset;
197: int err;
198: FD_ZERO(&wset);
199: FD_SET(s, &wset);
200: if((n = select(s + 1, NULL, &wset, NULL, NULL)) == -1 && errno == EINTR)
201: continue;
202: /*len = 0;*/
203: /*n = getpeername(s, NULL, &len);*/
204: len = sizeof(err);
205: if(getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
206: PRINT_SOCKET_ERROR("getsockopt");
207: closesocket(s);
208: freeaddrinfo(ai);
209: return -1;
210: }
211: if(err != 0) {
212: errno = err;
213: n = -1;
214: }
215: }
216: #endif /* #ifdef MINIUPNPC_IGNORE_EINTR */
217: if(n < 0)
218: {
219: closesocket(s);
220: continue;
221: }
222: else
223: {
224: break;
225: }
226: }
227: freeaddrinfo(ai);
228: if(s < 0)
229: {
230: PRINT_SOCKET_ERROR("socket");
231: return -1;
232: }
233: if(n < 0)
234: {
235: PRINT_SOCKET_ERROR("connect");
236: return -1;
237: }
238: #endif /* #ifdef USE_GETHOSTBYNAME */
239: return s;
240: }
241:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>