File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpc / connecthostport.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:16:22 2012 UTC (12 years, 4 months ago) by misho
Branches: miniupnpc, elwix, MAIN
CVS tags: v1_6, HEAD
miniupnpc

    1: /* $Id: connecthostport.c,v 1.1.1.1 2012/02/21 23:16:22 misho 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>