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>