File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpc / connecthostport.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:36:10 2013 UTC (10 years, 10 months ago) by misho
Branches: miniupnpc, elwix, MAIN
CVS tags: v1_8p0, v1_8, HEAD
1.8

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>