]> git.saurik.com Git - redis.git/blob - deps/hiredis/hiredis.c
Better Out of Memory handling.
[redis.git] / deps / hiredis / hiredis.c
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 #include "fmacros.h"
33 #include <string.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <assert.h>
37 #include <errno.h>
38 #include <ctype.h>
39
40 #include "hiredis.h"
41 #include "net.h"
42 #include "sds.h"
43
44 static redisReply *createReplyObject(int type);
45 static void *createStringObject(const redisReadTask *task, char *str, size_t len);
46 static void *createArrayObject(const redisReadTask *task, int elements);
47 static void *createIntegerObject(const redisReadTask *task, long long value);
48 static void *createNilObject(const redisReadTask *task);
49
50 /* Default set of functions to build the reply. Keep in mind that such a
51 * function returning NULL is interpreted as OOM. */
52 static redisReplyObjectFunctions defaultFunctions = {
53 createStringObject,
54 createArrayObject,
55 createIntegerObject,
56 createNilObject,
57 freeReplyObject
58 };
59
60 /* Create a reply object */
61 static redisReply *createReplyObject(int type) {
62 redisReply *r = calloc(1,sizeof(*r));
63
64 if (r == NULL)
65 return NULL;
66
67 r->type = type;
68 return r;
69 }
70
71 /* Free a reply object */
72 void freeReplyObject(void *reply) {
73 redisReply *r = reply;
74 size_t j;
75
76 switch(r->type) {
77 case REDIS_REPLY_INTEGER:
78 break; /* Nothing to free */
79 case REDIS_REPLY_ARRAY:
80 if (r->element != NULL) {
81 for (j = 0; j < r->elements; j++)
82 if (r->element[j] != NULL)
83 freeReplyObject(r->element[j]);
84 free(r->element);
85 }
86 break;
87 case REDIS_REPLY_ERROR:
88 case REDIS_REPLY_STATUS:
89 case REDIS_REPLY_STRING:
90 if (r->str != NULL)
91 free(r->str);
92 break;
93 }
94 free(r);
95 }
96
97 static void *createStringObject(const redisReadTask *task, char *str, size_t len) {
98 redisReply *r, *parent;
99 char *buf;
100
101 r = createReplyObject(task->type);
102 if (r == NULL)
103 return NULL;
104
105 buf = malloc(len+1);
106 if (buf == NULL) {
107 freeReplyObject(r);
108 return NULL;
109 }
110
111 assert(task->type == REDIS_REPLY_ERROR ||
112 task->type == REDIS_REPLY_STATUS ||
113 task->type == REDIS_REPLY_STRING);
114
115 /* Copy string value */
116 memcpy(buf,str,len);
117 buf[len] = '\0';
118 r->str = buf;
119 r->len = len;
120
121 if (task->parent) {
122 parent = task->parent->obj;
123 assert(parent->type == REDIS_REPLY_ARRAY);
124 parent->element[task->idx] = r;
125 }
126 return r;
127 }
128
129 static void *createArrayObject(const redisReadTask *task, int elements) {
130 redisReply *r, *parent;
131
132 r = createReplyObject(REDIS_REPLY_ARRAY);
133 if (r == NULL)
134 return NULL;
135
136 if (elements > 0) {
137 r->element = calloc(elements,sizeof(redisReply*));
138 if (r->element == NULL) {
139 freeReplyObject(r);
140 return NULL;
141 }
142 }
143
144 r->elements = elements;
145
146 if (task->parent) {
147 parent = task->parent->obj;
148 assert(parent->type == REDIS_REPLY_ARRAY);
149 parent->element[task->idx] = r;
150 }
151 return r;
152 }
153
154 static void *createIntegerObject(const redisReadTask *task, long long value) {
155 redisReply *r, *parent;
156
157 r = createReplyObject(REDIS_REPLY_INTEGER);
158 if (r == NULL)
159 return NULL;
160
161 r->integer = value;
162
163 if (task->parent) {
164 parent = task->parent->obj;
165 assert(parent->type == REDIS_REPLY_ARRAY);
166 parent->element[task->idx] = r;
167 }
168 return r;
169 }
170
171 static void *createNilObject(const redisReadTask *task) {
172 redisReply *r, *parent;
173
174 r = createReplyObject(REDIS_REPLY_NIL);
175 if (r == NULL)
176 return NULL;
177
178 if (task->parent) {
179 parent = task->parent->obj;
180 assert(parent->type == REDIS_REPLY_ARRAY);
181 parent->element[task->idx] = r;
182 }
183 return r;
184 }
185
186 static void __redisReaderSetError(redisReader *r, int type, const char *str) {
187 size_t len;
188
189 if (r->reply != NULL && r->fn && r->fn->freeObject) {
190 r->fn->freeObject(r->reply);
191 r->reply = NULL;
192 }
193
194 /* Clear input buffer on errors. */
195 if (r->buf != NULL) {
196 sdsfree(r->buf);
197 r->buf = NULL;
198 r->pos = r->len = 0;
199 }
200
201 /* Reset task stack. */
202 r->ridx = -1;
203
204 /* Set error. */
205 r->err = type;
206 len = strlen(str);
207 len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);
208 memcpy(r->errstr,str,len);
209 r->errstr[len] = '\0';
210 }
211
212 static size_t chrtos(char *buf, size_t size, char byte) {
213 size_t len = 0;
214
215 switch(byte) {
216 case '\\':
217 case '"':
218 len = snprintf(buf,size,"\"\\%c\"",byte);
219 break;
220 case '\n': len = snprintf(buf,size,"\"\\n\""); break;
221 case '\r': len = snprintf(buf,size,"\"\\r\""); break;
222 case '\t': len = snprintf(buf,size,"\"\\t\""); break;
223 case '\a': len = snprintf(buf,size,"\"\\a\""); break;
224 case '\b': len = snprintf(buf,size,"\"\\b\""); break;
225 default:
226 if (isprint(byte))
227 len = snprintf(buf,size,"\"%c\"",byte);
228 else
229 len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte);
230 break;
231 }
232
233 return len;
234 }
235
236 static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {
237 char cbuf[8], sbuf[128];
238
239 chrtos(cbuf,sizeof(cbuf),byte);
240 snprintf(sbuf,sizeof(sbuf),
241 "Protocol error, got %s as reply type byte", cbuf);
242 __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);
243 }
244
245 static void __redisReaderSetErrorOOM(redisReader *r) {
246 __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory");
247 }
248
249 static char *readBytes(redisReader *r, unsigned int bytes) {
250 char *p;
251 if (r->len-r->pos >= bytes) {
252 p = r->buf+r->pos;
253 r->pos += bytes;
254 return p;
255 }
256 return NULL;
257 }
258
259 /* Find pointer to \r\n. */
260 static char *seekNewline(char *s, size_t len) {
261 int pos = 0;
262 int _len = len-1;
263
264 /* Position should be < len-1 because the character at "pos" should be
265 * followed by a \n. Note that strchr cannot be used because it doesn't
266 * allow to search a limited length and the buffer that is being searched
267 * might not have a trailing NULL character. */
268 while (pos < _len) {
269 while(pos < _len && s[pos] != '\r') pos++;
270 if (s[pos] != '\r') {
271 /* Not found. */
272 return NULL;
273 } else {
274 if (s[pos+1] == '\n') {
275 /* Found. */
276 return s+pos;
277 } else {
278 /* Continue searching. */
279 pos++;
280 }
281 }
282 }
283 return NULL;
284 }
285
286 /* Read a long long value starting at *s, under the assumption that it will be
287 * terminated by \r\n. Ambiguously returns -1 for unexpected input. */
288 static long long readLongLong(char *s) {
289 long long v = 0;
290 int dec, mult = 1;
291 char c;
292
293 if (*s == '-') {
294 mult = -1;
295 s++;
296 } else if (*s == '+') {
297 mult = 1;
298 s++;
299 }
300
301 while ((c = *(s++)) != '\r') {
302 dec = c - '0';
303 if (dec >= 0 && dec < 10) {
304 v *= 10;
305 v += dec;
306 } else {
307 /* Should not happen... */
308 return -1;
309 }
310 }
311
312 return mult*v;
313 }
314
315 static char *readLine(redisReader *r, int *_len) {
316 char *p, *s;
317 int len;
318
319 p = r->buf+r->pos;
320 s = seekNewline(p,(r->len-r->pos));
321 if (s != NULL) {
322 len = s-(r->buf+r->pos);
323 r->pos += len+2; /* skip \r\n */
324 if (_len) *_len = len;
325 return p;
326 }
327 return NULL;
328 }
329
330 static void moveToNextTask(redisReader *r) {
331 redisReadTask *cur, *prv;
332 while (r->ridx >= 0) {
333 /* Return a.s.a.p. when the stack is now empty. */
334 if (r->ridx == 0) {
335 r->ridx--;
336 return;
337 }
338
339 cur = &(r->rstack[r->ridx]);
340 prv = &(r->rstack[r->ridx-1]);
341 assert(prv->type == REDIS_REPLY_ARRAY);
342 if (cur->idx == prv->elements-1) {
343 r->ridx--;
344 } else {
345 /* Reset the type because the next item can be anything */
346 assert(cur->idx < prv->elements);
347 cur->type = -1;
348 cur->elements = -1;
349 cur->idx++;
350 return;
351 }
352 }
353 }
354
355 static int processLineItem(redisReader *r) {
356 redisReadTask *cur = &(r->rstack[r->ridx]);
357 void *obj;
358 char *p;
359 int len;
360
361 if ((p = readLine(r,&len)) != NULL) {
362 if (cur->type == REDIS_REPLY_INTEGER) {
363 if (r->fn && r->fn->createInteger)
364 obj = r->fn->createInteger(cur,readLongLong(p));
365 else
366 obj = (void*)REDIS_REPLY_INTEGER;
367 } else {
368 /* Type will be error or status. */
369 if (r->fn && r->fn->createString)
370 obj = r->fn->createString(cur,p,len);
371 else
372 obj = (void*)(size_t)(cur->type);
373 }
374
375 if (obj == NULL) {
376 __redisReaderSetErrorOOM(r);
377 return REDIS_ERR;
378 }
379
380 /* Set reply if this is the root object. */
381 if (r->ridx == 0) r->reply = obj;
382 moveToNextTask(r);
383 return REDIS_OK;
384 }
385
386 return REDIS_ERR;
387 }
388
389 static int processBulkItem(redisReader *r) {
390 redisReadTask *cur = &(r->rstack[r->ridx]);
391 void *obj = NULL;
392 char *p, *s;
393 long len;
394 unsigned long bytelen;
395 int success = 0;
396
397 p = r->buf+r->pos;
398 s = seekNewline(p,r->len-r->pos);
399 if (s != NULL) {
400 p = r->buf+r->pos;
401 bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
402 len = readLongLong(p);
403
404 if (len < 0) {
405 /* The nil object can always be created. */
406 if (r->fn && r->fn->createNil)
407 obj = r->fn->createNil(cur);
408 else
409 obj = (void*)REDIS_REPLY_NIL;
410 success = 1;
411 } else {
412 /* Only continue when the buffer contains the entire bulk item. */
413 bytelen += len+2; /* include \r\n */
414 if (r->pos+bytelen <= r->len) {
415 if (r->fn && r->fn->createString)
416 obj = r->fn->createString(cur,s+2,len);
417 else
418 obj = (void*)REDIS_REPLY_STRING;
419 success = 1;
420 }
421 }
422
423 /* Proceed when obj was created. */
424 if (success) {
425 if (obj == NULL) {
426 __redisReaderSetErrorOOM(r);
427 return REDIS_ERR;
428 }
429
430 r->pos += bytelen;
431
432 /* Set reply if this is the root object. */
433 if (r->ridx == 0) r->reply = obj;
434 moveToNextTask(r);
435 return REDIS_OK;
436 }
437 }
438
439 return REDIS_ERR;
440 }
441
442 static int processMultiBulkItem(redisReader *r) {
443 redisReadTask *cur = &(r->rstack[r->ridx]);
444 void *obj;
445 char *p;
446 long elements;
447 int root = 0;
448
449 /* Set error for nested multi bulks with depth > 7 */
450 if (r->ridx == 8) {
451 __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
452 "No support for nested multi bulk replies with depth > 7");
453 return REDIS_ERR;
454 }
455
456 if ((p = readLine(r,NULL)) != NULL) {
457 elements = readLongLong(p);
458 root = (r->ridx == 0);
459
460 if (elements == -1) {
461 if (r->fn && r->fn->createNil)
462 obj = r->fn->createNil(cur);
463 else
464 obj = (void*)REDIS_REPLY_NIL;
465
466 if (obj == NULL) {
467 __redisReaderSetErrorOOM(r);
468 return REDIS_ERR;
469 }
470
471 moveToNextTask(r);
472 } else {
473 if (r->fn && r->fn->createArray)
474 obj = r->fn->createArray(cur,elements);
475 else
476 obj = (void*)REDIS_REPLY_ARRAY;
477
478 if (obj == NULL) {
479 __redisReaderSetErrorOOM(r);
480 return REDIS_ERR;
481 }
482
483 /* Modify task stack when there are more than 0 elements. */
484 if (elements > 0) {
485 cur->elements = elements;
486 cur->obj = obj;
487 r->ridx++;
488 r->rstack[r->ridx].type = -1;
489 r->rstack[r->ridx].elements = -1;
490 r->rstack[r->ridx].idx = 0;
491 r->rstack[r->ridx].obj = NULL;
492 r->rstack[r->ridx].parent = cur;
493 r->rstack[r->ridx].privdata = r->privdata;
494 } else {
495 moveToNextTask(r);
496 }
497 }
498
499 /* Set reply if this is the root object. */
500 if (root) r->reply = obj;
501 return REDIS_OK;
502 }
503
504 return REDIS_ERR;
505 }
506
507 static int processItem(redisReader *r) {
508 redisReadTask *cur = &(r->rstack[r->ridx]);
509 char *p;
510
511 /* check if we need to read type */
512 if (cur->type < 0) {
513 if ((p = readBytes(r,1)) != NULL) {
514 switch (p[0]) {
515 case '-':
516 cur->type = REDIS_REPLY_ERROR;
517 break;
518 case '+':
519 cur->type = REDIS_REPLY_STATUS;
520 break;
521 case ':':
522 cur->type = REDIS_REPLY_INTEGER;
523 break;
524 case '$':
525 cur->type = REDIS_REPLY_STRING;
526 break;
527 case '*':
528 cur->type = REDIS_REPLY_ARRAY;
529 break;
530 default:
531 __redisReaderSetErrorProtocolByte(r,*p);
532 return REDIS_ERR;
533 }
534 } else {
535 /* could not consume 1 byte */
536 return REDIS_ERR;
537 }
538 }
539
540 /* process typed item */
541 switch(cur->type) {
542 case REDIS_REPLY_ERROR:
543 case REDIS_REPLY_STATUS:
544 case REDIS_REPLY_INTEGER:
545 return processLineItem(r);
546 case REDIS_REPLY_STRING:
547 return processBulkItem(r);
548 case REDIS_REPLY_ARRAY:
549 return processMultiBulkItem(r);
550 default:
551 assert(NULL);
552 return REDIS_ERR; /* Avoid warning. */
553 }
554 }
555
556 redisReader *redisReaderCreate(void) {
557 redisReader *r;
558
559 r = calloc(sizeof(redisReader),1);
560 if (r == NULL)
561 return NULL;
562
563 r->err = 0;
564 r->errstr[0] = '\0';
565 r->fn = &defaultFunctions;
566 r->buf = sdsempty();
567 r->maxbuf = REDIS_READER_MAX_BUF;
568 if (r->buf == NULL) {
569 free(r);
570 return NULL;
571 }
572
573 r->ridx = -1;
574 return r;
575 }
576
577 void redisReaderFree(redisReader *r) {
578 if (r->reply != NULL && r->fn && r->fn->freeObject)
579 r->fn->freeObject(r->reply);
580 if (r->buf != NULL)
581 sdsfree(r->buf);
582 free(r);
583 }
584
585 int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
586 sds newbuf;
587
588 /* Return early when this reader is in an erroneous state. */
589 if (r->err)
590 return REDIS_ERR;
591
592 /* Copy the provided buffer. */
593 if (buf != NULL && len >= 1) {
594 /* Destroy internal buffer when it is empty and is quite large. */
595 if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
596 sdsfree(r->buf);
597 r->buf = sdsempty();
598 r->pos = 0;
599
600 /* r->buf should not be NULL since we just free'd a larger one. */
601 assert(r->buf != NULL);
602 }
603
604 newbuf = sdscatlen(r->buf,buf,len);
605 if (newbuf == NULL) {
606 __redisReaderSetErrorOOM(r);
607 return REDIS_ERR;
608 }
609
610 r->buf = newbuf;
611 r->len = sdslen(r->buf);
612 }
613
614 return REDIS_OK;
615 }
616
617 int redisReaderGetReply(redisReader *r, void **reply) {
618 /* Default target pointer to NULL. */
619 if (reply != NULL)
620 *reply = NULL;
621
622 /* Return early when this reader is in an erroneous state. */
623 if (r->err)
624 return REDIS_ERR;
625
626 /* When the buffer is empty, there will never be a reply. */
627 if (r->len == 0)
628 return REDIS_OK;
629
630 /* Set first item to process when the stack is empty. */
631 if (r->ridx == -1) {
632 r->rstack[0].type = -1;
633 r->rstack[0].elements = -1;
634 r->rstack[0].idx = -1;
635 r->rstack[0].obj = NULL;
636 r->rstack[0].parent = NULL;
637 r->rstack[0].privdata = r->privdata;
638 r->ridx = 0;
639 }
640
641 /* Process items in reply. */
642 while (r->ridx >= 0)
643 if (processItem(r) != REDIS_OK)
644 break;
645
646 /* Return ASAP when an error occurred. */
647 if (r->err)
648 return REDIS_ERR;
649
650 /* Discard part of the buffer when we've consumed at least 1k, to avoid
651 * doing unnecessary calls to memmove() in sds.c. */
652 if (r->pos >= 1024) {
653 r->buf = sdsrange(r->buf,r->pos,-1);
654 r->pos = 0;
655 r->len = sdslen(r->buf);
656 }
657
658 /* Emit a reply when there is one. */
659 if (r->ridx == -1) {
660 if (reply != NULL)
661 *reply = r->reply;
662 r->reply = NULL;
663 }
664 return REDIS_OK;
665 }
666
667 /* Calculate the number of bytes needed to represent an integer as string. */
668 static int intlen(int i) {
669 int len = 0;
670 if (i < 0) {
671 len++;
672 i = -i;
673 }
674 do {
675 len++;
676 i /= 10;
677 } while(i);
678 return len;
679 }
680
681 /* Helper that calculates the bulk length given a certain string length. */
682 static size_t bulklen(size_t len) {
683 return 1+intlen(len)+2+len+2;
684 }
685
686 int redisvFormatCommand(char **target, const char *format, va_list ap) {
687 const char *c = format;
688 char *cmd = NULL; /* final command */
689 int pos; /* position in final command */
690 sds curarg, newarg; /* current argument */
691 int touched = 0; /* was the current argument touched? */
692 char **curargv = NULL, **newargv = NULL;
693 int argc = 0;
694 int totlen = 0;
695 int j;
696
697 /* Abort if there is not target to set */
698 if (target == NULL)
699 return -1;
700
701 /* Build the command string accordingly to protocol */
702 curarg = sdsempty();
703 if (curarg == NULL)
704 return -1;
705
706 while(*c != '\0') {
707 if (*c != '%' || c[1] == '\0') {
708 if (*c == ' ') {
709 if (touched) {
710 newargv = realloc(curargv,sizeof(char*)*(argc+1));
711 if (newargv == NULL) goto err;
712 curargv = newargv;
713 curargv[argc++] = curarg;
714 totlen += bulklen(sdslen(curarg));
715
716 /* curarg is put in argv so it can be overwritten. */
717 curarg = sdsempty();
718 if (curarg == NULL) goto err;
719 touched = 0;
720 }
721 } else {
722 newarg = sdscatlen(curarg,c,1);
723 if (newarg == NULL) goto err;
724 curarg = newarg;
725 touched = 1;
726 }
727 } else {
728 char *arg;
729 size_t size;
730
731 /* Set newarg so it can be checked even if it is not touched. */
732 newarg = curarg;
733
734 switch(c[1]) {
735 case 's':
736 arg = va_arg(ap,char*);
737 size = strlen(arg);
738 if (size > 0)
739 newarg = sdscatlen(curarg,arg,size);
740 break;
741 case 'b':
742 arg = va_arg(ap,char*);
743 size = va_arg(ap,size_t);
744 if (size > 0)
745 newarg = sdscatlen(curarg,arg,size);
746 break;
747 case '%':
748 newarg = sdscat(curarg,"%");
749 break;
750 default:
751 /* Try to detect printf format */
752 {
753 static const char intfmts[] = "diouxX";
754 char _format[16];
755 const char *_p = c+1;
756 size_t _l = 0;
757 va_list _cpy;
758
759 /* Flags */
760 if (*_p != '\0' && *_p == '#') _p++;
761 if (*_p != '\0' && *_p == '0') _p++;
762 if (*_p != '\0' && *_p == '-') _p++;
763 if (*_p != '\0' && *_p == ' ') _p++;
764 if (*_p != '\0' && *_p == '+') _p++;
765
766 /* Field width */
767 while (*_p != '\0' && isdigit(*_p)) _p++;
768
769 /* Precision */
770 if (*_p == '.') {
771 _p++;
772 while (*_p != '\0' && isdigit(*_p)) _p++;
773 }
774
775 /* Copy va_list before consuming with va_arg */
776 va_copy(_cpy,ap);
777
778 /* Integer conversion (without modifiers) */
779 if (strchr(intfmts,*_p) != NULL) {
780 va_arg(ap,int);
781 goto fmt_valid;
782 }
783
784 /* Double conversion (without modifiers) */
785 if (strchr("eEfFgGaA",*_p) != NULL) {
786 va_arg(ap,double);
787 goto fmt_valid;
788 }
789
790 /* Size: char */
791 if (_p[0] == 'h' && _p[1] == 'h') {
792 _p += 2;
793 if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
794 va_arg(ap,int); /* char gets promoted to int */
795 goto fmt_valid;
796 }
797 goto fmt_invalid;
798 }
799
800 /* Size: short */
801 if (_p[0] == 'h') {
802 _p += 1;
803 if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
804 va_arg(ap,int); /* short gets promoted to int */
805 goto fmt_valid;
806 }
807 goto fmt_invalid;
808 }
809
810 /* Size: long long */
811 if (_p[0] == 'l' && _p[1] == 'l') {
812 _p += 2;
813 if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
814 va_arg(ap,long long);
815 goto fmt_valid;
816 }
817 goto fmt_invalid;
818 }
819
820 /* Size: long */
821 if (_p[0] == 'l') {
822 _p += 1;
823 if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
824 va_arg(ap,long);
825 goto fmt_valid;
826 }
827 goto fmt_invalid;
828 }
829
830 fmt_invalid:
831 va_end(_cpy);
832 goto err;
833
834 fmt_valid:
835 _l = (_p+1)-c;
836 if (_l < sizeof(_format)-2) {
837 memcpy(_format,c,_l);
838 _format[_l] = '\0';
839 newarg = sdscatvprintf(curarg,_format,_cpy);
840
841 /* Update current position (note: outer blocks
842 * increment c twice so compensate here) */
843 c = _p-1;
844 }
845
846 va_end(_cpy);
847 break;
848 }
849 }
850
851 if (newarg == NULL) goto err;
852 curarg = newarg;
853
854 touched = 1;
855 c++;
856 }
857 c++;
858 }
859
860 /* Add the last argument if needed */
861 if (touched) {
862 newargv = realloc(curargv,sizeof(char*)*(argc+1));
863 if (newargv == NULL) goto err;
864 curargv = newargv;
865 curargv[argc++] = curarg;
866 totlen += bulklen(sdslen(curarg));
867 } else {
868 sdsfree(curarg);
869 }
870
871 /* Clear curarg because it was put in curargv or was free'd. */
872 curarg = NULL;
873
874 /* Add bytes needed to hold multi bulk count */
875 totlen += 1+intlen(argc)+2;
876
877 /* Build the command at protocol level */
878 cmd = malloc(totlen+1);
879 if (cmd == NULL) goto err;
880
881 pos = sprintf(cmd,"*%d\r\n",argc);
882 for (j = 0; j < argc; j++) {
883 pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j]));
884 memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));
885 pos += sdslen(curargv[j]);
886 sdsfree(curargv[j]);
887 cmd[pos++] = '\r';
888 cmd[pos++] = '\n';
889 }
890 assert(pos == totlen);
891 cmd[pos] = '\0';
892
893 free(curargv);
894 *target = cmd;
895 return totlen;
896
897 err:
898 while(argc--)
899 sdsfree(curargv[argc]);
900 free(curargv);
901
902 if (curarg != NULL)
903 sdsfree(curarg);
904
905 /* No need to check cmd since it is the last statement that can fail,
906 * but do it anyway to be as defensive as possible. */
907 if (cmd != NULL)
908 free(cmd);
909
910 return -1;
911 }
912
913 /* Format a command according to the Redis protocol. This function
914 * takes a format similar to printf:
915 *
916 * %s represents a C null terminated string you want to interpolate
917 * %b represents a binary safe string
918 *
919 * When using %b you need to provide both the pointer to the string
920 * and the length in bytes. Examples:
921 *
922 * len = redisFormatCommand(target, "GET %s", mykey);
923 * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen);
924 */
925 int redisFormatCommand(char **target, const char *format, ...) {
926 va_list ap;
927 int len;
928 va_start(ap,format);
929 len = redisvFormatCommand(target,format,ap);
930 va_end(ap);
931 return len;
932 }
933
934 /* Format a command according to the Redis protocol. This function takes the
935 * number of arguments, an array with arguments and an array with their
936 * lengths. If the latter is set to NULL, strlen will be used to compute the
937 * argument lengths.
938 */
939 int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) {
940 char *cmd = NULL; /* final command */
941 int pos; /* position in final command */
942 size_t len;
943 int totlen, j;
944
945 /* Calculate number of bytes needed for the command */
946 totlen = 1+intlen(argc)+2;
947 for (j = 0; j < argc; j++) {
948 len = argvlen ? argvlen[j] : strlen(argv[j]);
949 totlen += bulklen(len);
950 }
951
952 /* Build the command at protocol level */
953 cmd = malloc(totlen+1);
954 if (cmd == NULL)
955 return -1;
956
957 pos = sprintf(cmd,"*%d\r\n",argc);
958 for (j = 0; j < argc; j++) {
959 len = argvlen ? argvlen[j] : strlen(argv[j]);
960 pos += sprintf(cmd+pos,"$%zu\r\n",len);
961 memcpy(cmd+pos,argv[j],len);
962 pos += len;
963 cmd[pos++] = '\r';
964 cmd[pos++] = '\n';
965 }
966 assert(pos == totlen);
967 cmd[pos] = '\0';
968
969 *target = cmd;
970 return totlen;
971 }
972
973 void __redisSetError(redisContext *c, int type, const char *str) {
974 size_t len;
975
976 c->err = type;
977 if (str != NULL) {
978 len = strlen(str);
979 len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);
980 memcpy(c->errstr,str,len);
981 c->errstr[len] = '\0';
982 } else {
983 /* Only REDIS_ERR_IO may lack a description! */
984 assert(type == REDIS_ERR_IO);
985 strerror_r(errno,c->errstr,sizeof(c->errstr));
986 }
987 }
988
989 static redisContext *redisContextInit(void) {
990 redisContext *c;
991
992 c = calloc(1,sizeof(redisContext));
993 if (c == NULL)
994 return NULL;
995
996 c->err = 0;
997 c->errstr[0] = '\0';
998 c->obuf = sdsempty();
999 c->reader = redisReaderCreate();
1000 return c;
1001 }
1002
1003 void redisFree(redisContext *c) {
1004 if (c->fd > 0)
1005 close(c->fd);
1006 if (c->obuf != NULL)
1007 sdsfree(c->obuf);
1008 if (c->reader != NULL)
1009 redisReaderFree(c->reader);
1010 free(c);
1011 }
1012
1013 /* Connect to a Redis instance. On error the field error in the returned
1014 * context will be set to the return value of the error function.
1015 * When no set of reply functions is given, the default set will be used. */
1016 redisContext *redisConnect(const char *ip, int port) {
1017 redisContext *c = redisContextInit();
1018 c->flags |= REDIS_BLOCK;
1019 redisContextConnectTcp(c,ip,port,NULL);
1020 return c;
1021 }
1022
1023 redisContext *redisConnectWithTimeout(const char *ip, int port, struct timeval tv) {
1024 redisContext *c = redisContextInit();
1025 c->flags |= REDIS_BLOCK;
1026 redisContextConnectTcp(c,ip,port,&tv);
1027 return c;
1028 }
1029
1030 redisContext *redisConnectNonBlock(const char *ip, int port) {
1031 redisContext *c = redisContextInit();
1032 c->flags &= ~REDIS_BLOCK;
1033 redisContextConnectTcp(c,ip,port,NULL);
1034 return c;
1035 }
1036
1037 redisContext *redisConnectUnix(const char *path) {
1038 redisContext *c = redisContextInit();
1039 c->flags |= REDIS_BLOCK;
1040 redisContextConnectUnix(c,path,NULL);
1041 return c;
1042 }
1043
1044 redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv) {
1045 redisContext *c = redisContextInit();
1046 c->flags |= REDIS_BLOCK;
1047 redisContextConnectUnix(c,path,&tv);
1048 return c;
1049 }
1050
1051 redisContext *redisConnectUnixNonBlock(const char *path) {
1052 redisContext *c = redisContextInit();
1053 c->flags &= ~REDIS_BLOCK;
1054 redisContextConnectUnix(c,path,NULL);
1055 return c;
1056 }
1057
1058 /* Set read/write timeout on a blocking socket. */
1059 int redisSetTimeout(redisContext *c, struct timeval tv) {
1060 if (c->flags & REDIS_BLOCK)
1061 return redisContextSetTimeout(c,tv);
1062 return REDIS_ERR;
1063 }
1064
1065 /* Use this function to handle a read event on the descriptor. It will try
1066 * and read some bytes from the socket and feed them to the reply parser.
1067 *
1068 * After this function is called, you may use redisContextReadReply to
1069 * see if there is a reply available. */
1070 int redisBufferRead(redisContext *c) {
1071 char buf[1024*16];
1072 int nread;
1073
1074 /* Return early when the context has seen an error. */
1075 if (c->err)
1076 return REDIS_ERR;
1077
1078 nread = read(c->fd,buf,sizeof(buf));
1079 if (nread == -1) {
1080 if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
1081 /* Try again later */
1082 } else {
1083 __redisSetError(c,REDIS_ERR_IO,NULL);
1084 return REDIS_ERR;
1085 }
1086 } else if (nread == 0) {
1087 __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection");
1088 return REDIS_ERR;
1089 } else {
1090 if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {
1091 __redisSetError(c,c->reader->err,c->reader->errstr);
1092 return REDIS_ERR;
1093 }
1094 }
1095 return REDIS_OK;
1096 }
1097
1098 /* Write the output buffer to the socket.
1099 *
1100 * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
1101 * succesfully written to the socket. When the buffer is empty after the
1102 * write operation, "done" is set to 1 (if given).
1103 *
1104 * Returns REDIS_ERR if an error occured trying to write and sets
1105 * c->errstr to hold the appropriate error string.
1106 */
1107 int redisBufferWrite(redisContext *c, int *done) {
1108 int nwritten;
1109
1110 /* Return early when the context has seen an error. */
1111 if (c->err)
1112 return REDIS_ERR;
1113
1114 if (sdslen(c->obuf) > 0) {
1115 nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
1116 if (nwritten == -1) {
1117 if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
1118 /* Try again later */
1119 } else {
1120 __redisSetError(c,REDIS_ERR_IO,NULL);
1121 return REDIS_ERR;
1122 }
1123 } else if (nwritten > 0) {
1124 if (nwritten == (signed)sdslen(c->obuf)) {
1125 sdsfree(c->obuf);
1126 c->obuf = sdsempty();
1127 } else {
1128 c->obuf = sdsrange(c->obuf,nwritten,-1);
1129 }
1130 }
1131 }
1132 if (done != NULL) *done = (sdslen(c->obuf) == 0);
1133 return REDIS_OK;
1134 }
1135
1136 /* Internal helper function to try and get a reply from the reader,
1137 * or set an error in the context otherwise. */
1138 int redisGetReplyFromReader(redisContext *c, void **reply) {
1139 if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) {
1140 __redisSetError(c,c->reader->err,c->reader->errstr);
1141 return REDIS_ERR;
1142 }
1143 return REDIS_OK;
1144 }
1145
1146 int redisGetReply(redisContext *c, void **reply) {
1147 int wdone = 0;
1148 void *aux = NULL;
1149
1150 /* Try to read pending replies */
1151 if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
1152 return REDIS_ERR;
1153
1154 /* For the blocking context, flush output buffer and read reply */
1155 if (aux == NULL && c->flags & REDIS_BLOCK) {
1156 /* Write until done */
1157 do {
1158 if (redisBufferWrite(c,&wdone) == REDIS_ERR)
1159 return REDIS_ERR;
1160 } while (!wdone);
1161
1162 /* Read until there is a reply */
1163 do {
1164 if (redisBufferRead(c) == REDIS_ERR)
1165 return REDIS_ERR;
1166 if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
1167 return REDIS_ERR;
1168 } while (aux == NULL);
1169 }
1170
1171 /* Set reply object */
1172 if (reply != NULL) *reply = aux;
1173 return REDIS_OK;
1174 }
1175
1176
1177 /* Helper function for the redisAppendCommand* family of functions.
1178 *
1179 * Write a formatted command to the output buffer. When this family
1180 * is used, you need to call redisGetReply yourself to retrieve
1181 * the reply (or replies in pub/sub).
1182 */
1183 int __redisAppendCommand(redisContext *c, char *cmd, size_t len) {
1184 sds newbuf;
1185
1186 newbuf = sdscatlen(c->obuf,cmd,len);
1187 if (newbuf == NULL) {
1188 __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
1189 return REDIS_ERR;
1190 }
1191
1192 c->obuf = newbuf;
1193 return REDIS_OK;
1194 }
1195
1196 int redisvAppendCommand(redisContext *c, const char *format, va_list ap) {
1197 char *cmd;
1198 int len;
1199
1200 len = redisvFormatCommand(&cmd,format,ap);
1201 if (len == -1) {
1202 __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
1203 return REDIS_ERR;
1204 }
1205
1206 if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
1207 free(cmd);
1208 return REDIS_ERR;
1209 }
1210
1211 free(cmd);
1212 return REDIS_OK;
1213 }
1214
1215 int redisAppendCommand(redisContext *c, const char *format, ...) {
1216 va_list ap;
1217 int ret;
1218
1219 va_start(ap,format);
1220 ret = redisvAppendCommand(c,format,ap);
1221 va_end(ap);
1222 return ret;
1223 }
1224
1225 int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
1226 char *cmd;
1227 int len;
1228
1229 len = redisFormatCommandArgv(&cmd,argc,argv,argvlen);
1230 if (len == -1) {
1231 __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
1232 return REDIS_ERR;
1233 }
1234
1235 if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
1236 free(cmd);
1237 return REDIS_ERR;
1238 }
1239
1240 free(cmd);
1241 return REDIS_OK;
1242 }
1243
1244 /* Helper function for the redisCommand* family of functions.
1245 *
1246 * Write a formatted command to the output buffer. If the given context is
1247 * blocking, immediately read the reply into the "reply" pointer. When the
1248 * context is non-blocking, the "reply" pointer will not be used and the
1249 * command is simply appended to the write buffer.
1250 *
1251 * Returns the reply when a reply was succesfully retrieved. Returns NULL
1252 * otherwise. When NULL is returned in a blocking context, the error field
1253 * in the context will be set.
1254 */
1255 static void *__redisBlockForReply(redisContext *c) {
1256 void *reply;
1257
1258 if (c->flags & REDIS_BLOCK) {
1259 if (redisGetReply(c,&reply) != REDIS_OK)
1260 return NULL;
1261 return reply;
1262 }
1263 return NULL;
1264 }
1265
1266 void *redisvCommand(redisContext *c, const char *format, va_list ap) {
1267 if (redisvAppendCommand(c,format,ap) != REDIS_OK)
1268 return NULL;
1269 return __redisBlockForReply(c);
1270 }
1271
1272 void *redisCommand(redisContext *c, const char *format, ...) {
1273 va_list ap;
1274 void *reply = NULL;
1275 va_start(ap,format);
1276 reply = redisvCommand(c,format,ap);
1277 va_end(ap);
1278 return reply;
1279 }
1280
1281 void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
1282 if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)
1283 return NULL;
1284 return __redisBlockForReply(c);
1285 }