Annotation of embedaddon/miniupnpc/connecthostport.c, revision 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>