Move network I/O calls to net.c
This makes hiredis.c free from system calls related to socket I/O. This is also makes the treatment of raw socket connections more similar to the SSL backend.
This commit is contained in:
parent
1c43a3823f
commit
1788f41f16
43
hiredis.c
43
hiredis.c
@ -34,7 +34,6 @@
|
|||||||
#include "fmacros.h"
|
#include "fmacros.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -605,8 +604,7 @@ static redisContext *redisContextInit(const redisOptions *options) {
|
|||||||
void redisFree(redisContext *c) {
|
void redisFree(redisContext *c) {
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
return;
|
return;
|
||||||
if (c->fd > 0)
|
redisNetClose(c);
|
||||||
close(c->fd);
|
|
||||||
|
|
||||||
sdsfree(c->obuf);
|
sdsfree(c->obuf);
|
||||||
redisReaderFree(c->reader);
|
redisReaderFree(c->reader);
|
||||||
@ -633,9 +631,7 @@ int redisReconnect(redisContext *c) {
|
|||||||
c->err = 0;
|
c->err = 0;
|
||||||
memset(c->errstr, '\0', strlen(c->errstr));
|
memset(c->errstr, '\0', strlen(c->errstr));
|
||||||
|
|
||||||
if (c->fd > 0) {
|
redisNetClose(c);
|
||||||
close(c->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
sdsfree(c->obuf);
|
sdsfree(c->obuf);
|
||||||
redisReaderFree(c->reader);
|
redisReaderFree(c->reader);
|
||||||
@ -776,24 +772,6 @@ int redisEnableKeepAlive(redisContext *c) {
|
|||||||
return REDIS_OK;
|
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
|
/* 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.
|
* 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;
|
return REDIS_ERR;
|
||||||
|
|
||||||
nread = c->flags & REDIS_SSL ?
|
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 (nread > 0) {
|
||||||
if (redisReaderFeed(c->reader, buf, nread) != REDIS_OK) {
|
if (redisReaderFeed(c->reader, buf, nread) != REDIS_OK) {
|
||||||
__redisSetError(c, c->reader->err, c->reader->errstr);
|
__redisSetError(c, c->reader->err, c->reader->errstr);
|
||||||
@ -821,19 +799,6 @@ int redisBufferRead(redisContext *c) {
|
|||||||
return REDIS_OK;
|
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.
|
/* Write the output buffer to the socket.
|
||||||
*
|
*
|
||||||
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
|
* 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;
|
return REDIS_ERR;
|
||||||
|
|
||||||
if (sdslen(c->obuf) > 0) {
|
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) {
|
if (nwritten < 0) {
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
} else if (nwritten > 0) {
|
} else if (nwritten > 0) {
|
||||||
|
51
net.c
51
net.c
@ -57,13 +57,44 @@
|
|||||||
/* Defined in hiredis.c */
|
/* Defined in hiredis.c */
|
||||||
void __redisSetError(redisContext *c, int type, const char *str);
|
void __redisSetError(redisContext *c, int type, const char *str);
|
||||||
|
|
||||||
static void redisContextCloseFd(redisContext *c) {
|
void redisNetClose(redisContext *c) {
|
||||||
if (c && c->fd >= 0) {
|
if (c && c->fd >= 0) {
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
c->fd = -1;
|
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) {
|
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
||||||
int errorno = errno; /* snprintf() may change errno */
|
int errorno = errno; /* snprintf() may change errno */
|
||||||
char buf[128] = { 0 };
|
char buf[128] = { 0 };
|
||||||
@ -79,7 +110,7 @@ static int redisSetReuseAddr(redisContext *c) {
|
|||||||
int on = 1;
|
int on = 1;
|
||||||
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
@ -108,7 +139,7 @@ static int redisSetBlocking(redisContext *c, int blocking) {
|
|||||||
* interrupted by a signal. */
|
* interrupted by a signal. */
|
||||||
if ((flags = fcntl(c->fd, F_GETFL)) == -1) {
|
if ((flags = fcntl(c->fd, F_GETFL)) == -1) {
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +150,7 @@ static int redisSetBlocking(redisContext *c, int blocking) {
|
|||||||
|
|
||||||
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
@ -170,7 +201,7 @@ static int redisSetTcpNoDelay(redisContext *c) {
|
|||||||
int yes = 1;
|
int yes = 1;
|
||||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
@ -212,12 +243,12 @@ static int redisContextWaitReady(redisContext *c, long msec) {
|
|||||||
|
|
||||||
if ((res = poll(wfd, 1, msec)) == -1) {
|
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
} else if (res == 0) {
|
} else if (res == 0) {
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +261,7 @@ static int redisContextWaitReady(redisContext *c, long msec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +441,7 @@ addrretry:
|
|||||||
|
|
||||||
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
||||||
if (errno == EHOSTUNREACH) {
|
if (errno == EHOSTUNREACH) {
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
continue;
|
continue;
|
||||||
} else if (errno == EINPROGRESS) {
|
} else if (errno == EINPROGRESS) {
|
||||||
if (blocking) {
|
if (blocking) {
|
||||||
@ -424,7 +455,7 @@ addrretry:
|
|||||||
if (++reuses >= REDIS_CONNECT_RETRIES) {
|
if (++reuses >= REDIS_CONNECT_RETRIES) {
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
redisContextCloseFd(c);
|
redisNetClose(c);
|
||||||
goto addrretry;
|
goto addrretry;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
4
net.h
4
net.h
@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
#include "hiredis.h"
|
#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 redisCheckSocketError(redisContext *c);
|
||||||
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
int redisContextSetTimeout(redisContext *c, const struct timeval tv);
|
||||||
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout);
|
||||||
|
Loading…
Reference in New Issue
Block a user