hiredis 0.6.1 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/ext/hiredis_ext/connection.c +4 -3
- data/ext/hiredis_ext/reader.c +12 -6
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/Makefile +53 -34
- data/vendor/hiredis/async.c +40 -9
- data/vendor/hiredis/async.h +1 -0
- data/vendor/hiredis/dict.c +2 -2
- data/vendor/hiredis/fmacros.h +4 -13
- data/vendor/hiredis/hiredis.c +50 -23
- data/vendor/hiredis/hiredis.h +37 -27
- data/vendor/hiredis/net.c +99 -22
- data/vendor/hiredis/net.h +4 -6
- data/vendor/hiredis/read.c +119 -44
- data/vendor/hiredis/read.h +4 -9
- data/vendor/hiredis/sds.c +342 -165
- data/vendor/hiredis/sds.h +184 -13
- data/vendor/hiredis/sdsalloc.h +42 -0
- data/vendor/hiredis/test.c +187 -14
- data/vendor/hiredis/win32.h +42 -0
- metadata +5 -3
data/vendor/hiredis/hiredis.c
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
4
|
+
* Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
|
5
|
+
* Jan-Erik Rediger <janerik at fnordig dot com>
|
4
6
|
*
|
5
7
|
* All rights reserved.
|
6
8
|
*
|
@@ -82,16 +84,14 @@ void freeReplyObject(void *reply) {
|
|
82
84
|
case REDIS_REPLY_ARRAY:
|
83
85
|
if (r->element != NULL) {
|
84
86
|
for (j = 0; j < r->elements; j++)
|
85
|
-
|
86
|
-
freeReplyObject(r->element[j]);
|
87
|
+
freeReplyObject(r->element[j]);
|
87
88
|
free(r->element);
|
88
89
|
}
|
89
90
|
break;
|
90
91
|
case REDIS_REPLY_ERROR:
|
91
92
|
case REDIS_REPLY_STATUS:
|
92
93
|
case REDIS_REPLY_STRING:
|
93
|
-
|
94
|
-
free(r->str);
|
94
|
+
free(r->str);
|
95
95
|
break;
|
96
96
|
}
|
97
97
|
free(r);
|
@@ -430,11 +430,7 @@ cleanup:
|
|
430
430
|
}
|
431
431
|
|
432
432
|
sdsfree(curarg);
|
433
|
-
|
434
|
-
/* No need to check cmd since it is the last statement that can fail,
|
435
|
-
* but do it anyway to be as defensive as possible. */
|
436
|
-
if (cmd != NULL)
|
437
|
-
free(cmd);
|
433
|
+
free(cmd);
|
438
434
|
|
439
435
|
return error_type;
|
440
436
|
}
|
@@ -505,7 +501,7 @@ int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv,
|
|
505
501
|
cmd = sdscatfmt(cmd, "*%i\r\n", argc);
|
506
502
|
for (j=0; j < argc; j++) {
|
507
503
|
len = argvlen ? argvlen[j] : strlen(argv[j]);
|
508
|
-
cmd = sdscatfmt(cmd, "$%
|
504
|
+
cmd = sdscatfmt(cmd, "$%u\r\n", len);
|
509
505
|
cmd = sdscatlen(cmd, argv[j], len);
|
510
506
|
cmd = sdscatlen(cmd, "\r\n", sizeof("\r\n")-1);
|
511
507
|
}
|
@@ -579,7 +575,7 @@ void __redisSetError(redisContext *c, int type, const char *str) {
|
|
579
575
|
} else {
|
580
576
|
/* Only REDIS_ERR_IO may lack a description! */
|
581
577
|
assert(type == REDIS_ERR_IO);
|
582
|
-
|
578
|
+
strerror_r(errno, c->errstr, sizeof(c->errstr));
|
583
579
|
}
|
584
580
|
}
|
585
581
|
|
@@ -594,8 +590,6 @@ static redisContext *redisContextInit(void) {
|
|
594
590
|
if (c == NULL)
|
595
591
|
return NULL;
|
596
592
|
|
597
|
-
c->err = 0;
|
598
|
-
c->errstr[0] = '\0';
|
599
593
|
c->obuf = sdsempty();
|
600
594
|
c->reader = redisReaderCreate();
|
601
595
|
|
@@ -612,10 +606,12 @@ void redisFree(redisContext *c) {
|
|
612
606
|
return;
|
613
607
|
if (c->fd > 0)
|
614
608
|
close(c->fd);
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
609
|
+
sdsfree(c->obuf);
|
610
|
+
redisReaderFree(c->reader);
|
611
|
+
free(c->tcp.host);
|
612
|
+
free(c->tcp.source_addr);
|
613
|
+
free(c->unix_sock.path);
|
614
|
+
free(c->timeout);
|
619
615
|
free(c);
|
620
616
|
}
|
621
617
|
|
@@ -626,6 +622,34 @@ int redisFreeKeepFd(redisContext *c) {
|
|
626
622
|
return fd;
|
627
623
|
}
|
628
624
|
|
625
|
+
int redisReconnect(redisContext *c) {
|
626
|
+
c->err = 0;
|
627
|
+
memset(c->errstr, '\0', strlen(c->errstr));
|
628
|
+
|
629
|
+
if (c->fd > 0) {
|
630
|
+
close(c->fd);
|
631
|
+
}
|
632
|
+
|
633
|
+
sdsfree(c->obuf);
|
634
|
+
redisReaderFree(c->reader);
|
635
|
+
|
636
|
+
c->obuf = sdsempty();
|
637
|
+
c->reader = redisReaderCreate();
|
638
|
+
|
639
|
+
if (c->connection_type == REDIS_CONN_TCP) {
|
640
|
+
return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
|
641
|
+
c->timeout, c->tcp.source_addr);
|
642
|
+
} else if (c->connection_type == REDIS_CONN_UNIX) {
|
643
|
+
return redisContextConnectUnix(c, c->unix_sock.path, c->timeout);
|
644
|
+
} else {
|
645
|
+
/* Something bad happened here and shouldn't have. There isn't
|
646
|
+
enough information in the context to reconnect. */
|
647
|
+
__redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect");
|
648
|
+
}
|
649
|
+
|
650
|
+
return REDIS_ERR;
|
651
|
+
}
|
652
|
+
|
629
653
|
/* Connect to a Redis instance. On error the field error in the returned
|
630
654
|
* context will be set to the return value of the error function.
|
631
655
|
* When no set of reply functions is given, the default set will be used. */
|
@@ -668,6 +692,8 @@ redisContext *redisConnectNonBlock(const char *ip, int port) {
|
|
668
692
|
redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
669
693
|
const char *source_addr) {
|
670
694
|
redisContext *c = redisContextInit();
|
695
|
+
if (c == NULL)
|
696
|
+
return NULL;
|
671
697
|
c->flags &= ~REDIS_BLOCK;
|
672
698
|
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
673
699
|
return c;
|
@@ -676,6 +702,8 @@ redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
|
676
702
|
redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
|
677
703
|
const char *source_addr) {
|
678
704
|
redisContext *c = redisContextInit();
|
705
|
+
if (c == NULL)
|
706
|
+
return NULL;
|
679
707
|
c->flags &= ~REDIS_BLOCK;
|
680
708
|
c->flags |= REDIS_REUSEADDR;
|
681
709
|
redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
|
@@ -780,10 +808,10 @@ int redisBufferRead(redisContext *c) {
|
|
780
808
|
/* Write the output buffer to the socket.
|
781
809
|
*
|
782
810
|
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
|
783
|
-
*
|
811
|
+
* successfully written to the socket. When the buffer is empty after the
|
784
812
|
* write operation, "done" is set to 1 (if given).
|
785
813
|
*
|
786
|
-
* Returns REDIS_ERR if an error
|
814
|
+
* Returns REDIS_ERR if an error occurred trying to write and sets
|
787
815
|
* c->errstr to hold the appropriate error string.
|
788
816
|
*/
|
789
817
|
int redisBufferWrite(redisContext *c, int *done) {
|
@@ -942,7 +970,7 @@ int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const s
|
|
942
970
|
* context is non-blocking, the "reply" pointer will not be used and the
|
943
971
|
* command is simply appended to the write buffer.
|
944
972
|
*
|
945
|
-
* Returns the reply when a reply was
|
973
|
+
* Returns the reply when a reply was successfully retrieved. Returns NULL
|
946
974
|
* otherwise. When NULL is returned in a blocking context, the error field
|
947
975
|
* in the context will be set.
|
948
976
|
*/
|
@@ -965,9 +993,8 @@ void *redisvCommand(redisContext *c, const char *format, va_list ap) {
|
|
965
993
|
|
966
994
|
void *redisCommand(redisContext *c, const char *format, ...) {
|
967
995
|
va_list ap;
|
968
|
-
void *reply = NULL;
|
969
996
|
va_start(ap,format);
|
970
|
-
reply = redisvCommand(c,format,ap);
|
997
|
+
void *reply = redisvCommand(c,format,ap);
|
971
998
|
va_end(ap);
|
972
999
|
return reply;
|
973
1000
|
}
|
data/vendor/hiredis/hiredis.h
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
3
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
4
|
+
* Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
|
5
|
+
* Jan-Erik Rediger <janerik at fnordig dot com>
|
4
6
|
*
|
5
7
|
* All rights reserved.
|
6
8
|
*
|
@@ -38,8 +40,9 @@
|
|
38
40
|
#include "sds.h" /* for sds */
|
39
41
|
|
40
42
|
#define HIREDIS_MAJOR 0
|
41
|
-
#define HIREDIS_MINOR
|
43
|
+
#define HIREDIS_MINOR 14
|
42
44
|
#define HIREDIS_PATCH 0
|
45
|
+
#define HIREDIS_SONAME 0.14
|
43
46
|
|
44
47
|
/* Connection type can be blocking or non-blocking and is set in the
|
45
48
|
* least significant bit of the flags field in redisContext. */
|
@@ -77,30 +80,6 @@
|
|
77
80
|
* SO_REUSEADDR is being used. */
|
78
81
|
#define REDIS_CONNECT_RETRIES 10
|
79
82
|
|
80
|
-
/* strerror_r has two completely different prototypes and behaviors
|
81
|
-
* depending on system issues, so we need to operate on the error buffer
|
82
|
-
* differently depending on which strerror_r we're using. */
|
83
|
-
#ifndef _GNU_SOURCE
|
84
|
-
/* "regular" POSIX strerror_r that does the right thing. */
|
85
|
-
#define __redis_strerror_r(errno, buf, len) \
|
86
|
-
do { \
|
87
|
-
strerror_r((errno), (buf), (len)); \
|
88
|
-
} while (0)
|
89
|
-
#else
|
90
|
-
/* "bad" GNU strerror_r we need to clean up after. */
|
91
|
-
#define __redis_strerror_r(errno, buf, len) \
|
92
|
-
do { \
|
93
|
-
char *err_str = strerror_r((errno), (buf), (len)); \
|
94
|
-
/* If return value _isn't_ the start of the buffer we passed in, \
|
95
|
-
* then GNU strerror_r returned an internal static buffer and we \
|
96
|
-
* need to copy the result into our private buffer. */ \
|
97
|
-
if (err_str != (buf)) { \
|
98
|
-
buf[(len)] = '\0'; \
|
99
|
-
strncat((buf), err_str, ((len) - 1)); \
|
100
|
-
} \
|
101
|
-
} while (0)
|
102
|
-
#endif
|
103
|
-
|
104
83
|
#ifdef __cplusplus
|
105
84
|
extern "C" {
|
106
85
|
#endif
|
@@ -109,7 +88,7 @@ extern "C" {
|
|
109
88
|
typedef struct redisReply {
|
110
89
|
int type; /* REDIS_REPLY_* */
|
111
90
|
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
|
112
|
-
|
91
|
+
size_t len; /* Length of string */
|
113
92
|
char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
|
114
93
|
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
|
115
94
|
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
|
@@ -128,6 +107,11 @@ int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const s
|
|
128
107
|
void redisFreeCommand(char *cmd);
|
129
108
|
void redisFreeSdsCommand(sds cmd);
|
130
109
|
|
110
|
+
enum redisConnectionType {
|
111
|
+
REDIS_CONN_TCP,
|
112
|
+
REDIS_CONN_UNIX
|
113
|
+
};
|
114
|
+
|
131
115
|
/* Context for a connection to Redis */
|
132
116
|
typedef struct redisContext {
|
133
117
|
int err; /* Error flags, 0 when there is no error */
|
@@ -136,6 +120,20 @@ typedef struct redisContext {
|
|
136
120
|
int flags;
|
137
121
|
char *obuf; /* Write buffer */
|
138
122
|
redisReader *reader; /* Protocol reader */
|
123
|
+
|
124
|
+
enum redisConnectionType connection_type;
|
125
|
+
struct timeval *timeout;
|
126
|
+
|
127
|
+
struct {
|
128
|
+
char *host;
|
129
|
+
char *source_addr;
|
130
|
+
int port;
|
131
|
+
} tcp;
|
132
|
+
|
133
|
+
struct {
|
134
|
+
char *path;
|
135
|
+
} unix_sock;
|
136
|
+
|
139
137
|
} redisContext;
|
140
138
|
|
141
139
|
redisContext *redisConnect(const char *ip, int port);
|
@@ -149,6 +147,18 @@ redisContext *redisConnectUnix(const char *path);
|
|
149
147
|
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
150
148
|
redisContext *redisConnectUnixNonBlock(const char *path);
|
151
149
|
redisContext *redisConnectFd(int fd);
|
150
|
+
|
151
|
+
/**
|
152
|
+
* Reconnect the given context using the saved information.
|
153
|
+
*
|
154
|
+
* This re-uses the exact same connect options as in the initial connection.
|
155
|
+
* host, ip (or path), timeout and bind address are reused,
|
156
|
+
* flags are used unmodified from the existing context.
|
157
|
+
*
|
158
|
+
* Returns REDIS_OK on successful connect or REDIS_ERR otherwise.
|
159
|
+
*/
|
160
|
+
int redisReconnect(redisContext *c);
|
161
|
+
|
152
162
|
int redisSetTimeout(redisContext *c, const struct timeval tv);
|
153
163
|
int redisEnableKeepAlive(redisContext *c);
|
154
164
|
void redisFree(redisContext *c);
|
data/vendor/hiredis/net.c
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
2
2
|
*
|
3
|
-
* Copyright (c)
|
4
|
-
* Copyright (c) 2010-
|
3
|
+
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
4
|
+
* Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
5
|
+
* Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
|
6
|
+
* Jan-Erik Rediger <janerik at fnordig dot com>
|
5
7
|
*
|
6
8
|
* All rights reserved.
|
7
9
|
*
|
@@ -47,6 +49,7 @@
|
|
47
49
|
#include <stdio.h>
|
48
50
|
#include <poll.h>
|
49
51
|
#include <limits.h>
|
52
|
+
#include <stdlib.h>
|
50
53
|
|
51
54
|
#include "net.h"
|
52
55
|
#include "sds.h"
|
@@ -62,12 +65,13 @@ static void redisContextCloseFd(redisContext *c) {
|
|
62
65
|
}
|
63
66
|
|
64
67
|
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
68
|
+
int errorno = errno; /* snprintf() may change errno */
|
65
69
|
char buf[128] = { 0 };
|
66
70
|
size_t len = 0;
|
67
71
|
|
68
72
|
if (prefix != NULL)
|
69
73
|
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
|
70
|
-
|
74
|
+
strerror_r(errorno, (char *)(buf + len), sizeof(buf) - len);
|
71
75
|
__redisSetError(c,type,buf);
|
72
76
|
}
|
73
77
|
|
@@ -132,14 +136,13 @@ int redisKeepAlive(redisContext *c, int interval) {
|
|
132
136
|
|
133
137
|
val = interval;
|
134
138
|
|
135
|
-
#
|
139
|
+
#if defined(__APPLE__) && defined(__MACH__)
|
136
140
|
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
|
137
141
|
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
138
142
|
return REDIS_ERR;
|
139
143
|
}
|
140
144
|
#else
|
141
145
|
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__)
|
142
|
-
val = interval;
|
143
146
|
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
|
144
147
|
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
145
148
|
return REDIS_ERR;
|
@@ -175,19 +178,15 @@ static int redisSetTcpNoDelay(redisContext *c) {
|
|
175
178
|
|
176
179
|
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
177
180
|
|
178
|
-
static int
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
msec = -1;
|
183
|
-
wfd[0].fd = c->fd;
|
184
|
-
wfd[0].events = POLLOUT;
|
181
|
+
static int redisContextTimeoutMsec(redisContext *c, long *result)
|
182
|
+
{
|
183
|
+
const struct timeval *timeout = c->timeout;
|
184
|
+
long msec = -1;
|
185
185
|
|
186
186
|
/* Only use timeout when not NULL. */
|
187
187
|
if (timeout != NULL) {
|
188
188
|
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
189
|
-
|
190
|
-
redisContextCloseFd(c);
|
189
|
+
*result = msec;
|
191
190
|
return REDIS_ERR;
|
192
191
|
}
|
193
192
|
|
@@ -198,6 +197,16 @@ static int redisContextWaitReady(redisContext *c, const struct timeval *timeout)
|
|
198
197
|
}
|
199
198
|
}
|
200
199
|
|
200
|
+
*result = msec;
|
201
|
+
return REDIS_OK;
|
202
|
+
}
|
203
|
+
|
204
|
+
static int redisContextWaitReady(redisContext *c, long msec) {
|
205
|
+
struct pollfd wfd[1];
|
206
|
+
|
207
|
+
wfd[0].fd = c->fd;
|
208
|
+
wfd[0].events = POLLOUT;
|
209
|
+
|
201
210
|
if (errno == EINPROGRESS) {
|
202
211
|
int res;
|
203
212
|
|
@@ -262,6 +271,49 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
|
262
271
|
int blocking = (c->flags & REDIS_BLOCK);
|
263
272
|
int reuseaddr = (c->flags & REDIS_REUSEADDR);
|
264
273
|
int reuses = 0;
|
274
|
+
long timeout_msec = -1;
|
275
|
+
|
276
|
+
servinfo = NULL;
|
277
|
+
c->connection_type = REDIS_CONN_TCP;
|
278
|
+
c->tcp.port = port;
|
279
|
+
|
280
|
+
/* We need to take possession of the passed parameters
|
281
|
+
* to make them reusable for a reconnect.
|
282
|
+
* We also carefully check we don't free data we already own,
|
283
|
+
* as in the case of the reconnect method.
|
284
|
+
*
|
285
|
+
* This is a bit ugly, but atleast it works and doesn't leak memory.
|
286
|
+
**/
|
287
|
+
if (c->tcp.host != addr) {
|
288
|
+
free(c->tcp.host);
|
289
|
+
|
290
|
+
c->tcp.host = strdup(addr);
|
291
|
+
}
|
292
|
+
|
293
|
+
if (timeout) {
|
294
|
+
if (c->timeout != timeout) {
|
295
|
+
if (c->timeout == NULL)
|
296
|
+
c->timeout = malloc(sizeof(struct timeval));
|
297
|
+
|
298
|
+
memcpy(c->timeout, timeout, sizeof(struct timeval));
|
299
|
+
}
|
300
|
+
} else {
|
301
|
+
free(c->timeout);
|
302
|
+
c->timeout = NULL;
|
303
|
+
}
|
304
|
+
|
305
|
+
if (redisContextTimeoutMsec(c, &timeout_msec) != REDIS_OK) {
|
306
|
+
__redisSetError(c, REDIS_ERR_IO, "Invalid timeout specified");
|
307
|
+
goto error;
|
308
|
+
}
|
309
|
+
|
310
|
+
if (source_addr == NULL) {
|
311
|
+
free(c->tcp.source_addr);
|
312
|
+
c->tcp.source_addr = NULL;
|
313
|
+
} else if (c->tcp.source_addr != source_addr) {
|
314
|
+
free(c->tcp.source_addr);
|
315
|
+
c->tcp.source_addr = strdup(source_addr);
|
316
|
+
}
|
265
317
|
|
266
318
|
snprintf(_port, 6, "%d", port);
|
267
319
|
memset(&hints,0,sizeof(hints));
|
@@ -273,7 +325,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
|
273
325
|
* as this would add latency to every connect. Otherwise a more sensible
|
274
326
|
* route could be: Use IPv6 if both addresses are available and there is IPv6
|
275
327
|
* connectivity. */
|
276
|
-
if ((rv = getaddrinfo(
|
328
|
+
if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) {
|
277
329
|
hints.ai_family = AF_INET6;
|
278
330
|
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
279
331
|
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
@@ -288,10 +340,10 @@ addrretry:
|
|
288
340
|
c->fd = s;
|
289
341
|
if (redisSetBlocking(c,0) != REDIS_OK)
|
290
342
|
goto error;
|
291
|
-
if (source_addr) {
|
343
|
+
if (c->tcp.source_addr) {
|
292
344
|
int bound = 0;
|
293
345
|
/* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
|
294
|
-
if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) {
|
346
|
+
if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) {
|
295
347
|
char buf[128];
|
296
348
|
snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
|
297
349
|
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
@@ -302,6 +354,7 @@ addrretry:
|
|
302
354
|
n = 1;
|
303
355
|
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n,
|
304
356
|
sizeof(n)) < 0) {
|
357
|
+
freeaddrinfo(bservinfo);
|
305
358
|
goto error;
|
306
359
|
}
|
307
360
|
}
|
@@ -330,10 +383,11 @@ addrretry:
|
|
330
383
|
if (++reuses >= REDIS_CONNECT_RETRIES) {
|
331
384
|
goto error;
|
332
385
|
} else {
|
386
|
+
redisContextCloseFd(c);
|
333
387
|
goto addrretry;
|
334
388
|
}
|
335
389
|
} else {
|
336
|
-
if (redisContextWaitReady(c,
|
390
|
+
if (redisContextWaitReady(c,timeout_msec) != REDIS_OK)
|
337
391
|
goto error;
|
338
392
|
}
|
339
393
|
}
|
@@ -356,7 +410,10 @@ addrretry:
|
|
356
410
|
error:
|
357
411
|
rv = REDIS_ERR;
|
358
412
|
end:
|
359
|
-
|
413
|
+
if(servinfo) {
|
414
|
+
freeaddrinfo(servinfo);
|
415
|
+
}
|
416
|
+
|
360
417
|
return rv; // Need to return REDIS_OK if alright
|
361
418
|
}
|
362
419
|
|
@@ -374,19 +431,39 @@ int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
|
374
431
|
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
375
432
|
int blocking = (c->flags & REDIS_BLOCK);
|
376
433
|
struct sockaddr_un sa;
|
434
|
+
long timeout_msec = -1;
|
377
435
|
|
378
|
-
if (redisCreateSocket(c,
|
436
|
+
if (redisCreateSocket(c,AF_UNIX) < 0)
|
379
437
|
return REDIS_ERR;
|
380
438
|
if (redisSetBlocking(c,0) != REDIS_OK)
|
381
439
|
return REDIS_ERR;
|
382
440
|
|
383
|
-
|
441
|
+
c->connection_type = REDIS_CONN_UNIX;
|
442
|
+
if (c->unix_sock.path != path)
|
443
|
+
c->unix_sock.path = strdup(path);
|
444
|
+
|
445
|
+
if (timeout) {
|
446
|
+
if (c->timeout != timeout) {
|
447
|
+
if (c->timeout == NULL)
|
448
|
+
c->timeout = malloc(sizeof(struct timeval));
|
449
|
+
|
450
|
+
memcpy(c->timeout, timeout, sizeof(struct timeval));
|
451
|
+
}
|
452
|
+
} else {
|
453
|
+
free(c->timeout);
|
454
|
+
c->timeout = NULL;
|
455
|
+
}
|
456
|
+
|
457
|
+
if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK)
|
458
|
+
return REDIS_ERR;
|
459
|
+
|
460
|
+
sa.sun_family = AF_UNIX;
|
384
461
|
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
|
385
462
|
if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
386
463
|
if (errno == EINPROGRESS && !blocking) {
|
387
464
|
/* This is ok. */
|
388
465
|
} else {
|
389
|
-
if (redisContextWaitReady(c,
|
466
|
+
if (redisContextWaitReady(c,timeout_msec) != REDIS_OK)
|
390
467
|
return REDIS_ERR;
|
391
468
|
}
|
392
469
|
}
|