summaryrefslogtreecommitdiff
path: root/hiredis.c
diff options
context:
space:
mode:
authorAlessio M <masariello@gmail.com>2020-09-04 09:31:47 +0100
committerAlessio M <masariello@gmail.com>2020-09-04 09:31:47 +0100
commitd7b1d21e807f8a90a086b2ef5cea9b707d4cc858 (patch)
tree748b00a48a8b625f1dca22ae4cc5721ab7de87c5 /hiredis.c
parent07c3618ffe7912c2ebc589ea45501c687a19cf2c (diff)
parentfb0e6c0dd9affd5728c6e0a6423f5dcb7b207947 (diff)
Merge branch 'master' of github.com:redis/hiredis
Diffstat (limited to 'hiredis.c')
-rw-r--r--hiredis.c79
1 files changed, 53 insertions, 26 deletions
diff --git a/hiredis.c b/hiredis.c
index e9761ec..a7fbf48 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -44,8 +44,11 @@
#include "async.h"
#include "win32.h"
+extern int redisContextUpdateConnectTimeout(redisContext *c, const struct timeval *timeout);
+extern int redisContextUpdateCommandTimeout(redisContext *c, const struct timeval *timeout);
+
static redisContextFuncs redisContextDefaultFuncs = {
- .free_privdata = NULL,
+ .free_privctx = NULL,
.async_read = redisAsyncRead,
.async_write = redisAsyncWrite,
.read = redisNetRead,
@@ -685,7 +688,7 @@ static void redisPushAutoFree(void *privdata, void *reply) {
freeReplyObject(reply);
}
-static redisContext *redisContextInit(const redisOptions *options) {
+static redisContext *redisContextInit(void) {
redisContext *c;
c = hi_calloc(1, sizeof(*c));
@@ -694,13 +697,6 @@ static redisContext *redisContextInit(const redisOptions *options) {
c->funcs = &redisContextDefaultFuncs;
- /* Set any user supplied RESP3 PUSH handler or use freeReplyObject
- * as a default unless specifically flagged that we don't want one. */
- if (options->push_cb != NULL)
- redisSetPushCallback(c, options->push_cb);
- else if (!(options->options & REDIS_OPT_NO_PUSH_AUTOFREE))
- redisSetPushCallback(c, redisPushAutoFree);
-
c->obuf = sdsempty();
c->reader = redisReaderCreate();
c->fd = REDIS_INVALID_FD;
@@ -709,7 +705,7 @@ static redisContext *redisContextInit(const redisOptions *options) {
redisFree(c);
return NULL;
}
- (void)options; /* options are used in other functions */
+
return c;
}
@@ -723,11 +719,16 @@ void redisFree(redisContext *c) {
hi_free(c->tcp.host);
hi_free(c->tcp.source_addr);
hi_free(c->unix_sock.path);
- hi_free(c->timeout);
+ hi_free(c->connect_timeout);
+ hi_free(c->command_timeout);
hi_free(c->saddr);
- if (c->funcs->free_privdata) {
- c->funcs->free_privdata(c->privdata);
- }
+
+ if (c->privdata && c->free_privdata)
+ c->free_privdata(c->privdata);
+
+ if (c->funcs->free_privctx)
+ c->funcs->free_privctx(c->privctx);
+
memset(c, 0xff, sizeof(*c));
hi_free(c);
}
@@ -743,9 +744,9 @@ int redisReconnect(redisContext *c) {
c->err = 0;
memset(c->errstr, '\0', strlen(c->errstr));
- if (c->privdata && c->funcs->free_privdata) {
- c->funcs->free_privdata(c->privdata);
- c->privdata = NULL;
+ if (c->privctx && c->funcs->free_privctx) {
+ c->funcs->free_privctx(c->privctx);
+ c->privctx = NULL;
}
redisNetClose(c);
@@ -761,22 +762,28 @@ int redisReconnect(redisContext *c) {
return REDIS_ERR;
}
+ int ret = REDIS_ERR;
if (c->connection_type == REDIS_CONN_TCP) {
- return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
- c->timeout, c->tcp.source_addr);
+ ret = redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
+ c->connect_timeout, c->tcp.source_addr);
} else if (c->connection_type == REDIS_CONN_UNIX) {
- return redisContextConnectUnix(c, c->unix_sock.path, c->timeout);
+ ret = redisContextConnectUnix(c, c->unix_sock.path, c->connect_timeout);
} else {
/* Something bad happened here and shouldn't have. There isn't
enough information in the context to reconnect. */
__redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect");
+ ret = REDIS_ERR;
}
- return REDIS_ERR;
+ if (c->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) {
+ redisContextSetTimeout(c, *c->command_timeout);
+ }
+
+ return ret;
}
redisContext *redisConnectWithOptions(const redisOptions *options) {
- redisContext *c = redisContextInit(options);
+ redisContext *c = redisContextInit();
if (c == NULL) {
return NULL;
}
@@ -790,13 +797,29 @@ redisContext *redisConnectWithOptions(const redisOptions *options) {
c->flags |= REDIS_NO_AUTO_FREE;
}
+ /* Set any user supplied RESP3 PUSH handler or use freeReplyObject
+ * as a default unless specifically flagged that we don't want one. */
+ if (options->push_cb != NULL)
+ redisSetPushCallback(c, options->push_cb);
+ else if (!(options->options & REDIS_OPT_NO_PUSH_AUTOFREE))
+ redisSetPushCallback(c, redisPushAutoFree);
+
+ c->privdata = options->privdata;
+ c->free_privdata = options->free_privdata;
+
+ if (redisContextUpdateConnectTimeout(c, options->connect_timeout) != REDIS_OK ||
+ redisContextUpdateCommandTimeout(c, options->command_timeout) != REDIS_OK) {
+ __redisSetError(c, REDIS_ERR_OOM, "Out of memory");
+ return c;
+ }
+
if (options->type == REDIS_CONN_TCP) {
redisContextConnectBindTcp(c, options->endpoint.tcp.ip,
- options->endpoint.tcp.port, options->timeout,
+ options->endpoint.tcp.port, options->connect_timeout,
options->endpoint.tcp.source_addr);
} else if (options->type == REDIS_CONN_UNIX) {
redisContextConnectUnix(c, options->endpoint.unix_socket,
- options->timeout);
+ options->connect_timeout);
} else if (options->type == REDIS_CONN_USERFD) {
c->fd = options->endpoint.fd;
c->flags |= REDIS_CONNECTED;
@@ -805,6 +828,10 @@ redisContext *redisConnectWithOptions(const redisOptions *options) {
return NULL;
}
+ if (options->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) {
+ redisContextSetTimeout(c, *options->command_timeout);
+ }
+
return c;
}
@@ -820,7 +847,7 @@ redisContext *redisConnect(const char *ip, int port) {
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {
redisOptions options = {0};
REDIS_OPTIONS_SET_TCP(&options, ip, port);
- options.timeout = &tv;
+ options.connect_timeout = &tv;
return redisConnectWithOptions(&options);
}
@@ -858,7 +885,7 @@ redisContext *redisConnectUnix(const char *path) {
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {
redisOptions options = {0};
REDIS_OPTIONS_SET_UNIX(&options, path);
- options.timeout = &tv;
+ options.connect_timeout = &tv;
return redisConnectWithOptions(&options);
}