hiredis 0.6.1 → 0.6.2

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