Annotation of embedaddon/miniupnpc/connecthostport.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* $Id: connecthostport.c,v 1.9 2012/06/26 00:00:27 nanard Exp $ */
1.1       misho       2: /* Project : miniupnp
                      3:  * Author : Thomas Bernard
1.1.1.2 ! misho       4:  * Copyright (c) 2010-2012 Thomas Bernard
1.1       misho       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>
1.1.1.2 ! misho      16: #ifdef _WIN32
1.1       misho      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
1.1.1.2 ! misho      24: #else /* #ifdef _WIN32 */
1.1       misho      25: #include <unistd.h>
                     26: #include <sys/param.h>
                     27: #include <errno.h>
                     28: #define closesocket close
                     29: #include <netdb.h>
1.1.1.2 ! misho      30: #include <netinet/in.h>
1.1       misho      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 */
1.1.1.2 ! misho      38: #endif /* #else _WIN32 */
1.1       misho      39: 
                     40: /* definition of PRINT_SOCKET_ERROR */
1.1.1.2 ! misho      41: #ifdef _WIN32
1.1       misho      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 */
1.1.1.2 ! misho      56: int connecthostport(const char * host, unsigned short port,
        !            57:                     unsigned int scope_id)
1.1       misho      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 */
1.1.1.2 ! misho      72: 
1.1       misho      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 */
1.1.1.2 ! misho     150:                int i, j;
        !           151:                for(i = 0, j = 1; host[j] && (host[j] != ']') && i < MAXHOSTNAMELEN; i++, j++)
1.1       misho     152:                {
1.1.1.2 ! misho     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" */
1.1       misho     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:        {
1.1.1.2 ! misho     167: #ifdef _WIN32
1.1       misho     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;
1.1.1.2 ! misho     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:                }
1.1       misho     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>