durable_rules 0.34.57 → 2.00.001

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,223 +0,0 @@
1
- /*
2
- * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
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>
6
- *
7
- * All rights reserved.
8
- *
9
- * Redistribution and use in source and binary forms, with or without
10
- * modification, are permitted provided that the following conditions are met:
11
- *
12
- * * Redistributions of source code must retain the above copyright notice,
13
- * this list of conditions and the following disclaimer.
14
- * * Redistributions in binary form must reproduce the above copyright
15
- * notice, this list of conditions and the following disclaimer in the
16
- * documentation and/or other materials provided with the distribution.
17
- * * Neither the name of Redis nor the names of its contributors may be used
18
- * to endorse or promote products derived from this software without
19
- * specific prior written permission.
20
- *
21
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
- * POSSIBILITY OF SUCH DAMAGE.
32
- */
33
-
34
- #ifndef __HIREDIS_H
35
- #define __HIREDIS_H
36
- #include "read.h"
37
- #include <stdarg.h> /* for va_list */
38
- #include <sys/time.h> /* for struct timeval */
39
- #include <stdint.h> /* uintXX_t, etc */
40
- #include "sds.h" /* for sds */
41
-
42
- #define HIREDIS_MAJOR 0
43
- #define HIREDIS_MINOR 13
44
- #define HIREDIS_PATCH 3
45
- #define HIREDIS_SONAME 0.13
46
-
47
- /* Connection type can be blocking or non-blocking and is set in the
48
- * least significant bit of the flags field in redisContext. */
49
- #define REDIS_BLOCK 0x1
50
-
51
- /* Connection may be disconnected before being free'd. The second bit
52
- * in the flags field is set when the context is connected. */
53
- #define REDIS_CONNECTED 0x2
54
-
55
- /* The async API might try to disconnect cleanly and flush the output
56
- * buffer and read all subsequent replies before disconnecting.
57
- * This flag means no new commands can come in and the connection
58
- * should be terminated once all replies have been read. */
59
- #define REDIS_DISCONNECTING 0x4
60
-
61
- /* Flag specific to the async API which means that the context should be clean
62
- * up as soon as possible. */
63
- #define REDIS_FREEING 0x8
64
-
65
- /* Flag that is set when an async callback is executed. */
66
- #define REDIS_IN_CALLBACK 0x10
67
-
68
- /* Flag that is set when the async context has one or more subscriptions. */
69
- #define REDIS_SUBSCRIBED 0x20
70
-
71
- /* Flag that is set when monitor mode is active */
72
- #define REDIS_MONITORING 0x40
73
-
74
- /* Flag that is set when we should set SO_REUSEADDR before calling bind() */
75
- #define REDIS_REUSEADDR 0x80
76
-
77
- #define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
78
-
79
- /* number of times we retry to connect in the case of EADDRNOTAVAIL and
80
- * SO_REUSEADDR is being used. */
81
- #define REDIS_CONNECT_RETRIES 10
82
-
83
- /* strerror_r has two completely different prototypes and behaviors
84
- * depending on system issues, so we need to operate on the error buffer
85
- * differently depending on which strerror_r we're using. */
86
- #ifndef _GNU_SOURCE_PLUS
87
- /* "regular" POSIX strerror_r that does the right thing. */
88
- #define __redis_strerror_r(errno, buf, len) \
89
- do { \
90
- strerror_r((errno), (buf), (len)); \
91
- } while (0)
92
- #else
93
- /* "bad" GNU strerror_r we need to clean up after. */
94
- #define __redis_strerror_r(errno, buf, len) \
95
- do { \
96
- char *err_str = strerror_r((errno), (buf), (len)); \
97
- /* If return value _isn't_ the start of the buffer we passed in, \
98
- * then GNU strerror_r returned an internal static buffer and we \
99
- * need to copy the result into our private buffer. */ \
100
- if (err_str != (buf)) { \
101
- buf[(len)] = '\0'; \
102
- strncat((buf), err_str, ((len) - 1)); \
103
- } \
104
- } while (0)
105
- #endif
106
-
107
- #ifdef __cplusplus
108
- extern "C" {
109
- #endif
110
-
111
- /* This is the reply object returned by redisCommand() */
112
- typedef struct redisReply {
113
- int type; /* REDIS_REPLY_* */
114
- long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
115
- int len; /* Length of string */
116
- char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
117
- size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
118
- struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
119
- } redisReply;
120
-
121
- redisReader *redisReaderCreate(void);
122
-
123
- /* Function to free the reply objects hiredis returns by default. */
124
- void freeReplyObject(void *reply);
125
-
126
- /* Functions to format a command according to the protocol. */
127
- int redisvFormatCommand(char **target, const char *format, va_list ap);
128
- int redisFormatCommand(char **target, const char *format, ...);
129
- int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
130
- int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen);
131
- void redisFreeCommand(char *cmd);
132
- void redisFreeSdsCommand(sds cmd);
133
-
134
- enum redisConnectionType {
135
- REDIS_CONN_TCP,
136
- REDIS_CONN_UNIX,
137
- };
138
-
139
- /* Context for a connection to Redis */
140
- typedef struct redisContext {
141
- int err; /* Error flags, 0 when there is no error */
142
- char errstr[128]; /* String representation of error when applicable */
143
- int fd;
144
- int flags;
145
- char *obuf; /* Write buffer */
146
- redisReader *reader; /* Protocol reader */
147
-
148
- enum redisConnectionType connection_type;
149
- struct timeval *timeout;
150
-
151
- struct {
152
- char *host;
153
- char *source_addr;
154
- int port;
155
- } tcp;
156
-
157
- struct {
158
- char *path;
159
- } unix_sock;
160
-
161
- } redisContext;
162
-
163
- redisContext *redisConnect(const char *ip, int port);
164
- redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
165
- redisContext *redisConnectNonBlock(const char *ip, int port);
166
- redisContext *redisConnectBindNonBlock(const char *ip, int port,
167
- const char *source_addr);
168
- redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
169
- const char *source_addr);
170
- redisContext *redisConnectUnix(const char *path);
171
- redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
172
- redisContext *redisConnectUnixNonBlock(const char *path);
173
- redisContext *redisConnectFd(int fd);
174
-
175
- /**
176
- * Reconnect the given context using the saved information.
177
- *
178
- * This re-uses the exact same connect options as in the initial connection.
179
- * host, ip (or path), timeout and bind address are reused,
180
- * flags are used unmodified from the existing context.
181
- *
182
- * Returns REDIS_OK on successfull connect or REDIS_ERR otherwise.
183
- */
184
- int redisReconnect(redisContext *c);
185
-
186
- int redisSetTimeout(redisContext *c, const struct timeval tv);
187
- int redisEnableKeepAlive(redisContext *c);
188
- void redisFree(redisContext *c);
189
- int redisFreeKeepFd(redisContext *c);
190
- int redisBufferRead(redisContext *c);
191
- int redisBufferWrite(redisContext *c, int *done);
192
-
193
- /* In a blocking context, this function first checks if there are unconsumed
194
- * replies to return and returns one if so. Otherwise, it flushes the output
195
- * buffer to the socket and reads until it has a reply. In a non-blocking
196
- * context, it will return unconsumed replies until there are no more. */
197
- int redisGetReply(redisContext *c, void **reply);
198
- int redisGetReplyFromReader(redisContext *c, void **reply);
199
-
200
- /* Write a formatted command to the output buffer. Use these functions in blocking mode
201
- * to get a pipeline of commands. */
202
- int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
203
-
204
- /* Write a command to the output buffer. Use these functions in blocking mode
205
- * to get a pipeline of commands. */
206
- int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
207
- int redisAppendCommand(redisContext *c, const char *format, ...);
208
- int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
209
-
210
- /* Issue a command to Redis. In a blocking context, it is identical to calling
211
- * redisAppendCommand, followed by redisGetReply. The function will return
212
- * NULL if there was an error in performing the request, otherwise it will
213
- * return the reply. In a non-blocking context, it is identical to calling
214
- * only redisAppendCommand and will always return NULL. */
215
- void *redisvCommand(redisContext *c, const char *format, va_list ap);
216
- void *redisCommand(redisContext *c, const char *format, ...);
217
- void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
218
-
219
- #ifdef __cplusplus
220
- }
221
- #endif
222
-
223
- #endif
data/deps/hiredis/net.c DELETED
@@ -1,458 +0,0 @@
1
- /* Extracted from anet.c to work properly with Hiredis error reporting.
2
- *
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>
7
- *
8
- * All rights reserved.
9
- *
10
- * Redistribution and use in source and binary forms, with or without
11
- * modification, are permitted provided that the following conditions are met:
12
- *
13
- * * Redistributions of source code must retain the above copyright notice,
14
- * this list of conditions and the following disclaimer.
15
- * * Redistributions in binary form must reproduce the above copyright
16
- * notice, this list of conditions and the following disclaimer in the
17
- * documentation and/or other materials provided with the distribution.
18
- * * Neither the name of Redis nor the names of its contributors may be used
19
- * to endorse or promote products derived from this software without
20
- * specific prior written permission.
21
- *
22
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
- * POSSIBILITY OF SUCH DAMAGE.
33
- */
34
-
35
- #include "fmacros.h"
36
- #include <sys/types.h>
37
- #include <sys/socket.h>
38
- #include <sys/select.h>
39
- #include <sys/un.h>
40
- #include <netinet/in.h>
41
- #include <netinet/tcp.h>
42
- #include <arpa/inet.h>
43
- #include <unistd.h>
44
- #include <fcntl.h>
45
- #include <string.h>
46
- #include <netdb.h>
47
- #include <errno.h>
48
- #include <stdarg.h>
49
- #include <stdio.h>
50
- #include <poll.h>
51
- #include <limits.h>
52
- #include <stdlib.h>
53
-
54
- #include "net.h"
55
- #include "sds.h"
56
-
57
- /* Defined in hiredis.c */
58
- void __redisSetError(redisContext *c, int type, const char *str);
59
-
60
- static void redisContextCloseFd(redisContext *c) {
61
- if (c && c->fd >= 0) {
62
- close(c->fd);
63
- c->fd = -1;
64
- }
65
- }
66
-
67
- static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
68
- char buf[128] = { 0 };
69
- size_t len = 0;
70
-
71
- if (prefix != NULL)
72
- len = snprintf(buf,sizeof(buf),"%s: ",prefix);
73
- //__redis_strerror_r(errno, (char *)(buf + len), sizeof(buf) - len);
74
- __redisSetError(c,type,buf);
75
- }
76
-
77
- static int redisSetReuseAddr(redisContext *c) {
78
- int on = 1;
79
- if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
80
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
81
- redisContextCloseFd(c);
82
- return REDIS_ERR;
83
- }
84
- return REDIS_OK;
85
- }
86
-
87
- static int redisCreateSocket(redisContext *c, int type) {
88
- int s;
89
- if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
90
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
91
- return REDIS_ERR;
92
- }
93
- c->fd = s;
94
- if (type == AF_INET) {
95
- if (redisSetReuseAddr(c) == REDIS_ERR) {
96
- return REDIS_ERR;
97
- }
98
- }
99
- return REDIS_OK;
100
- }
101
-
102
- static int redisSetBlocking(redisContext *c, int blocking) {
103
- int flags;
104
-
105
- /* Set the socket nonblocking.
106
- * Note that fcntl(2) for F_GETFL and F_SETFL can't be
107
- * interrupted by a signal. */
108
- if ((flags = fcntl(c->fd, F_GETFL)) == -1) {
109
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
110
- redisContextCloseFd(c);
111
- return REDIS_ERR;
112
- }
113
-
114
- if (blocking)
115
- flags &= ~O_NONBLOCK;
116
- else
117
- flags |= O_NONBLOCK;
118
-
119
- if (fcntl(c->fd, F_SETFL, flags) == -1) {
120
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
121
- redisContextCloseFd(c);
122
- return REDIS_ERR;
123
- }
124
- return REDIS_OK;
125
- }
126
-
127
- int redisKeepAlive(redisContext *c, int interval) {
128
- int val = 1;
129
- int fd = c->fd;
130
-
131
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
132
- __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
133
- return REDIS_ERR;
134
- }
135
-
136
- val = interval;
137
-
138
- #ifdef _OSX
139
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
140
- __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
141
- return REDIS_ERR;
142
- }
143
- #else
144
- #if defined(__GLIBC__) && !defined(__FreeBSD_kernel__)
145
- val = interval;
146
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
147
- __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
148
- return REDIS_ERR;
149
- }
150
-
151
- val = interval/3;
152
- if (val == 0) val = 1;
153
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
154
- __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
155
- return REDIS_ERR;
156
- }
157
-
158
- val = 3;
159
- if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
160
- __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
161
- return REDIS_ERR;
162
- }
163
- #endif
164
- #endif
165
-
166
- return REDIS_OK;
167
- }
168
-
169
- static int redisSetTcpNoDelay(redisContext *c) {
170
- int yes = 1;
171
- if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
172
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
173
- redisContextCloseFd(c);
174
- return REDIS_ERR;
175
- }
176
- return REDIS_OK;
177
- }
178
-
179
- #define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
180
-
181
- static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {
182
- struct pollfd wfd[1];
183
- long msec;
184
-
185
- msec = -1;
186
- wfd[0].fd = c->fd;
187
- wfd[0].events = POLLOUT;
188
-
189
- /* Only use timeout when not NULL. */
190
- if (timeout != NULL) {
191
- if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
192
- __redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
193
- redisContextCloseFd(c);
194
- return REDIS_ERR;
195
- }
196
-
197
- msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
198
-
199
- if (msec < 0 || msec > INT_MAX) {
200
- msec = INT_MAX;
201
- }
202
- }
203
-
204
- if (errno == EINPROGRESS) {
205
- int res;
206
-
207
- if ((res = poll(wfd, 1, msec)) == -1) {
208
- __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
209
- redisContextCloseFd(c);
210
- return REDIS_ERR;
211
- } else if (res == 0) {
212
- errno = ETIMEDOUT;
213
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
214
- redisContextCloseFd(c);
215
- return REDIS_ERR;
216
- }
217
-
218
- if (redisCheckSocketError(c) != REDIS_OK)
219
- return REDIS_ERR;
220
-
221
- return REDIS_OK;
222
- }
223
-
224
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
225
- redisContextCloseFd(c);
226
- return REDIS_ERR;
227
- }
228
-
229
- int redisCheckSocketError(redisContext *c) {
230
- int err = 0;
231
- socklen_t errlen = sizeof(err);
232
-
233
- if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
234
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
235
- return REDIS_ERR;
236
- }
237
-
238
- if (err) {
239
- errno = err;
240
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
241
- return REDIS_ERR;
242
- }
243
-
244
- return REDIS_OK;
245
- }
246
-
247
- int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
248
- if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
249
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
250
- return REDIS_ERR;
251
- }
252
- if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
253
- __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
254
- return REDIS_ERR;
255
- }
256
- return REDIS_OK;
257
- }
258
-
259
- static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
260
- const struct timeval *timeout,
261
- const char *source_addr) {
262
- int s, rv, n;
263
- char _port[6]; /* strlen("65535"); */
264
- struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
265
- int blocking = (c->flags & REDIS_BLOCK);
266
- int reuseaddr = (c->flags & REDIS_REUSEADDR);
267
- int reuses = 0;
268
-
269
- c->connection_type = REDIS_CONN_TCP;
270
- c->tcp.port = port;
271
-
272
- /* We need to take possession of the passed parameters
273
- * to make them reusable for a reconnect.
274
- * We also carefully check we don't free data we already own,
275
- * as in the case of the reconnect method.
276
- *
277
- * This is a bit ugly, but atleast it works and doesn't leak memory.
278
- **/
279
- if (c->tcp.host != addr) {
280
- if (c->tcp.host)
281
- free(c->tcp.host);
282
-
283
- c->tcp.host = strdup(addr);
284
- }
285
-
286
- if (timeout) {
287
- if (c->timeout != timeout) {
288
- if (c->timeout == NULL)
289
- c->timeout = malloc(sizeof(struct timeval));
290
-
291
- memcpy(c->timeout, timeout, sizeof(struct timeval));
292
- }
293
- } else {
294
- if (c->timeout)
295
- free(c->timeout);
296
- c->timeout = NULL;
297
- }
298
-
299
- if (source_addr == NULL) {
300
- free(c->tcp.source_addr);
301
- c->tcp.source_addr = NULL;
302
- } else if (c->tcp.source_addr != source_addr) {
303
- free(c->tcp.source_addr);
304
- c->tcp.source_addr = strdup(source_addr);
305
- }
306
-
307
- snprintf(_port, 6, "%d", port);
308
- memset(&hints,0,sizeof(hints));
309
- hints.ai_family = AF_INET;
310
- hints.ai_socktype = SOCK_STREAM;
311
-
312
- /* Try with IPv6 if no IPv4 address was found. We do it in this order since
313
- * in a Redis client you can't afford to test if you have IPv6 connectivity
314
- * as this would add latency to every connect. Otherwise a more sensible
315
- * route could be: Use IPv6 if both addresses are available and there is IPv6
316
- * connectivity. */
317
- if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) {
318
- hints.ai_family = AF_INET6;
319
- if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
320
- __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
321
- return REDIS_ERR;
322
- }
323
- }
324
- for (p = servinfo; p != NULL; p = p->ai_next) {
325
- addrretry:
326
- if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
327
- continue;
328
-
329
- c->fd = s;
330
- if (redisSetBlocking(c,0) != REDIS_OK)
331
- goto error;
332
- if (c->tcp.source_addr) {
333
- int bound = 0;
334
- /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
335
- if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) {
336
- char buf[128];
337
- snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
338
- __redisSetError(c,REDIS_ERR_OTHER,buf);
339
- goto error;
340
- }
341
-
342
- if (reuseaddr) {
343
- n = 1;
344
- if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n,
345
- sizeof(n)) < 0) {
346
- goto error;
347
- }
348
- }
349
-
350
- for (b = bservinfo; b != NULL; b = b->ai_next) {
351
- if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {
352
- bound = 1;
353
- break;
354
- }
355
- }
356
- freeaddrinfo(bservinfo);
357
- if (!bound) {
358
- char buf[128];
359
- snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno));
360
- __redisSetError(c,REDIS_ERR_OTHER,buf);
361
- goto error;
362
- }
363
- }
364
- if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
365
- if (errno == EHOSTUNREACH) {
366
- redisContextCloseFd(c);
367
- continue;
368
- } else if (errno == EINPROGRESS && !blocking) {
369
- /* This is ok. */
370
- } else if (errno == EADDRNOTAVAIL && reuseaddr) {
371
- if (++reuses >= REDIS_CONNECT_RETRIES) {
372
- goto error;
373
- } else {
374
- goto addrretry;
375
- }
376
- } else {
377
- if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
378
- goto error;
379
- }
380
- }
381
- if (blocking && redisSetBlocking(c,1) != REDIS_OK)
382
- goto error;
383
- if (redisSetTcpNoDelay(c) != REDIS_OK)
384
- goto error;
385
-
386
- c->flags |= REDIS_CONNECTED;
387
- rv = REDIS_OK;
388
- goto end;
389
- }
390
- if (p == NULL) {
391
- char buf[128];
392
- snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno));
393
- __redisSetError(c,REDIS_ERR_OTHER,buf);
394
- goto error;
395
- }
396
-
397
- error:
398
- rv = REDIS_ERR;
399
- end:
400
- freeaddrinfo(servinfo);
401
- return rv; // Need to return REDIS_OK if alright
402
- }
403
-
404
- int redisContextConnectTcp(redisContext *c, const char *addr, int port,
405
- const struct timeval *timeout) {
406
- return _redisContextConnectTcp(c, addr, port, timeout, NULL);
407
- }
408
-
409
- int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
410
- const struct timeval *timeout,
411
- const char *source_addr) {
412
- return _redisContextConnectTcp(c, addr, port, timeout, source_addr);
413
- }
414
-
415
- int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
416
- int blocking = (c->flags & REDIS_BLOCK);
417
- struct sockaddr_un sa;
418
-
419
- if (redisCreateSocket(c,AF_LOCAL) < 0)
420
- return REDIS_ERR;
421
- if (redisSetBlocking(c,0) != REDIS_OK)
422
- return REDIS_ERR;
423
-
424
- c->connection_type = REDIS_CONN_UNIX;
425
- if (c->unix_sock.path != path)
426
- c->unix_sock.path = strdup(path);
427
-
428
- if (timeout) {
429
- if (c->timeout != timeout) {
430
- if (c->timeout == NULL)
431
- c->timeout = malloc(sizeof(struct timeval));
432
-
433
- memcpy(c->timeout, timeout, sizeof(struct timeval));
434
- }
435
- } else {
436
- if (c->timeout)
437
- free(c->timeout);
438
- c->timeout = NULL;
439
- }
440
-
441
- sa.sun_family = AF_LOCAL;
442
- strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
443
- if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
444
- if (errno == EINPROGRESS && !blocking) {
445
- /* This is ok. */
446
- } else {
447
- if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
448
- return REDIS_ERR;
449
- }
450
- }
451
-
452
- /* Reset socket to be blocking after connect(2). */
453
- if (blocking && redisSetBlocking(c,1) != REDIS_OK)
454
- return REDIS_ERR;
455
-
456
- c->flags |= REDIS_CONNECTED;
457
- return REDIS_OK;
458
- }