diff options
| author | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2011-07-20 05:02:08 -0700 | 
|---|---|---|
| committer | Pieter Noordhuis <pcnoordhuis@gmail.com> | 2011-07-20 05:02:08 -0700 | 
| commit | 7bc9f5413447af9c920b9aaba85fa39d9496fe1a (patch) | |
| tree | c731a30101ed8fad488feba9678889f4adb1e400 | |
| parent | 6bde974927ffce4f6d7acd8370c8a60b51454004 (diff) | |
| parent | c4ed06d90c2d25ccbb709b3d7c9c848aa732de66 (diff) | |
| download | hiredict-7bc9f5413447af9c920b9aaba85fa39d9496fe1a.tar.xz | |
Merge pull request #47 from geoffgarside/addrinfo
Use getaddrinfo
| -rw-r--r-- | net.c | 99 | 
1 files changed, 58 insertions, 41 deletions
| @@ -62,16 +62,24 @@ static void __redisSetErrorFromErrno(redisContext *c, int type, const char *pref      __redisSetError(c,type,buf);  } +static int redisSetReuseAddr(redisContext *c, int fd) { +    int on = 1; +    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { +        __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); +        close(fd); +        return REDIS_ERR; +    } +    return REDIS_OK; +} +  static int redisCreateSocket(redisContext *c, int type) { -    int s, on = 1; +    int s;      if ((s = socket(type, SOCK_STREAM, 0)) == -1) {          __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);          return REDIS_ERR;      }      if (type == AF_INET) { -        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { -            __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); -            close(s); +        if (redisSetReuseAddr(c,s) == REDIS_ERR) {              return REDIS_ERR;          }      } @@ -185,50 +193,59 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {  }  int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { -    int s; +    int s, rv; +    char _port[6];  /* strlen("65535"); */ +    struct addrinfo hints, *servinfo, *p;      int blocking = (c->flags & REDIS_BLOCK); -    struct sockaddr_in sa; -    if ((s = redisCreateSocket(c,AF_INET)) < 0) -        return REDIS_ERR; -    if (redisSetBlocking(c,s,0) != REDIS_OK) -        return REDIS_ERR; +    snprintf(_port, 6, "%d", port); +    memset(&hints,0,sizeof(hints)); +    hints.ai_family = AF_INET; +    hints.ai_socktype = SOCK_STREAM; -    sa.sin_family = AF_INET; -    sa.sin_port = htons(port); -    if (inet_aton(addr, &sa.sin_addr) == 0) { -        struct hostent *he; - -        he = gethostbyname(addr); -        if (he == NULL) { -            char buf[128]; -            snprintf(buf,sizeof(buf),"Can't resolve: %s", addr); -            __redisSetError(c,REDIS_ERR_OTHER,buf); -            close(s); -            return REDIS_ERR; -        } -        memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); +    if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { +        __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); +        return REDIS_ERR;      } - -    if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { -        if (errno == EINPROGRESS && !blocking) { -            /* This is ok. */ -        } else { -            if (redisContextWaitReady(c,s,timeout) != REDIS_OK) -                return REDIS_ERR; +    for (p = servinfo; p != NULL; p = p->ai_next) { +        if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) +            continue; + +        if (redisSetBlocking(c,s,0) != REDIS_OK) +            goto error; +        if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { +            if (errno == EHOSTUNREACH) { +                close(s); +                continue; +            } else if (errno == EINPROGRESS && !blocking) { +                /* This is ok. */ +            } else { +                if (redisContextWaitReady(c,s,timeout) != REDIS_OK) +                    goto error; +            }          } +        if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) +            goto error; +        if (redisSetTcpNoDelay(c,s) != REDIS_OK) +            goto error; + +        c->fd = s; +        c->flags |= REDIS_CONNECTED; +        rv = REDIS_OK; +        goto end; +    } +    if (p == NULL) { +        char buf[128]; +        snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); +        __redisSetError(c,REDIS_ERR_OTHER,buf); +        goto error;      } -    /* Reset socket to be blocking after connect(2). */ -    if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) -        return REDIS_ERR; - -    if (redisSetTcpNoDelay(c,s) != REDIS_OK) -        return REDIS_ERR; - -    c->fd = s; -    c->flags |= REDIS_CONNECTED; -    return REDIS_OK; +error: +    rv = REDIS_ERR; +end: +    freeaddrinfo(servinfo); +    return rv;  // Need to return REDIS_OK if alright  }  int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) { | 
