durable_rules 0.34.57 → 2.00.001

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- }