diff --git a/hiredis.c b/hiredis.c index 2506d51..629f43e 100644 --- a/hiredis.c +++ b/hiredis.c @@ -34,7 +34,6 @@ #include "fmacros.h" #include #include -#include #include #include #include @@ -605,8 +604,7 @@ static redisContext *redisContextInit(const redisOptions *options) { void redisFree(redisContext *c) { if (c == NULL) return; - if (c->fd > 0) - close(c->fd); + redisNetClose(c); sdsfree(c->obuf); redisReaderFree(c->reader); @@ -633,9 +631,7 @@ int redisReconnect(redisContext *c) { c->err = 0; memset(c->errstr, '\0', strlen(c->errstr)); - if (c->fd > 0) { - close(c->fd); - } + redisNetClose(c); sdsfree(c->obuf); redisReaderFree(c->reader); @@ -776,24 +772,6 @@ int redisEnableKeepAlive(redisContext *c) { return REDIS_OK; } -static int rawRead(redisContext *c, char *buf, size_t bufcap) { - int nread = read(c->fd, buf, bufcap); - if (nread == -1) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - return 0; - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } else if (nread == 0) { - __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); - return -1; - } else { - return nread; - } -} - /* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * @@ -808,7 +786,7 @@ int redisBufferRead(redisContext *c) { return REDIS_ERR; nread = c->flags & REDIS_SSL ? - redisSslRead(c, buf, sizeof(buf)) : rawRead(c, buf, sizeof(buf)); + redisSslRead(c, buf, sizeof(buf)) : redisNetRead(c, buf, sizeof(buf)); if (nread > 0) { if (redisReaderFeed(c->reader, buf, nread) != REDIS_OK) { __redisSetError(c, c->reader->err, c->reader->errstr); @@ -821,19 +799,6 @@ int redisBufferRead(redisContext *c) { return REDIS_OK; } -static int rawWrite(redisContext *c) { - int nwritten = write(c->fd, c->obuf, sdslen(c->obuf)); - if (nwritten < 0) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c, REDIS_ERR_IO, NULL); - return -1; - } - } - return nwritten; -} - /* Write the output buffer to the socket. * * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was @@ -850,7 +815,7 @@ int redisBufferWrite(redisContext *c, int *done) { return REDIS_ERR; if (sdslen(c->obuf) > 0) { - int nwritten = (c->flags & REDIS_SSL) ? redisSslWrite(c) : rawWrite(c); + int nwritten = (c->flags & REDIS_SSL) ? redisSslWrite(c) : redisNetWrite(c); if (nwritten < 0) { return REDIS_ERR; } else if (nwritten > 0) { diff --git a/net.c b/net.c index 3cd0402..a1913cd 100644 --- a/net.c +++ b/net.c @@ -57,13 +57,44 @@ /* Defined in hiredis.c */ void __redisSetError(redisContext *c, int type, const char *str); -static void redisContextCloseFd(redisContext *c) { +void redisNetClose(redisContext *c) { if (c && c->fd >= 0) { close(c->fd); c->fd = -1; } } +int redisNetRead(redisContext *c, char *buf, size_t bufcap) { + int nread = read(c->fd, buf, bufcap); + if (nread == -1) { + if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { + /* Try again later */ + return 0; + } else { + __redisSetError(c, REDIS_ERR_IO, NULL); + return -1; + } + } else if (nread == 0) { + __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); + return -1; + } else { + return nread; + } +} + +int redisNetWrite(redisContext *c) { + int nwritten = write(c->fd, c->obuf, sdslen(c->obuf)); + if (nwritten < 0) { + if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { + /* Try again later */ + } else { + __redisSetError(c, REDIS_ERR_IO, NULL); + return -1; + } + } + return nwritten; +} + static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { int errorno = errno; /* snprintf() may change errno */ char buf[128] = { 0 }; @@ -79,7 +110,7 @@ static int redisSetReuseAddr(redisContext *c) { int on = 1; if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } return REDIS_OK; @@ -108,7 +139,7 @@ static int redisSetBlocking(redisContext *c, int blocking) { * interrupted by a signal. */ if ((flags = fcntl(c->fd, F_GETFL)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -119,7 +150,7 @@ static int redisSetBlocking(redisContext *c, int blocking) { if (fcntl(c->fd, F_SETFL, flags) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } return REDIS_OK; @@ -170,7 +201,7 @@ static int redisSetTcpNoDelay(redisContext *c) { int yes = 1; if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } return REDIS_OK; @@ -212,12 +243,12 @@ static int redisContextWaitReady(redisContext *c, long msec) { if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -230,7 +261,7 @@ static int redisContextWaitReady(redisContext *c, long msec) { } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -410,7 +441,7 @@ addrretry: if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { if (errno == EHOSTUNREACH) { - redisContextCloseFd(c); + redisNetClose(c); continue; } else if (errno == EINPROGRESS) { if (blocking) { @@ -424,7 +455,7 @@ addrretry: if (++reuses >= REDIS_CONNECT_RETRIES) { goto error; } else { - redisContextCloseFd(c); + redisNetClose(c); goto addrretry; } } else { diff --git a/net.h b/net.h index a11594e..a4393c0 100644 --- a/net.h +++ b/net.h @@ -37,6 +37,10 @@ #include "hiredis.h" +void redisNetClose(redisContext *c); +int redisNetRead(redisContext *c, char *buf, size_t bufcap); +int redisNetWrite(redisContext *c); + int redisCheckSocketError(redisContext *c); int redisContextSetTimeout(redisContext *c, const struct timeval tv); int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);