hiredis.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  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. #include "fmacros.h"
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <unistd.h>
  37. #include <assert.h>
  38. #include <errno.h>
  39. #include <ctype.h>
  40. #include "hiredis.h"
  41. #include "net.h"
  42. #include "sds.h"
  43. static redisReply *createReplyObject(int type);
  44. static void *createStringObject(const redisReadTask *task, char *str, size_t len);
  45. static void *createArrayObject(const redisReadTask *task, int elements);
  46. static void *createIntegerObject(const redisReadTask *task, long long value);
  47. static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len);
  48. static void *createNilObject(const redisReadTask *task);
  49. static void *createBoolObject(const redisReadTask *task, int bval);
  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. createDoubleObject,
  57. createNilObject,
  58. createBoolObject,
  59. freeReplyObject
  60. };
  61. /* Create a reply object */
  62. static redisReply *createReplyObject(int type) {
  63. redisReply *r = calloc(1,sizeof(*r));
  64. if (r == NULL)
  65. return NULL;
  66. r->type = type;
  67. return r;
  68. }
  69. /* Free a reply object */
  70. void freeReplyObject(void *reply) {
  71. redisReply *r = reply;
  72. size_t j;
  73. if (r == NULL)
  74. return;
  75. switch(r->type) {
  76. case REDIS_REPLY_INTEGER:
  77. break; /* Nothing to free */
  78. case REDIS_REPLY_ARRAY:
  79. case REDIS_REPLY_MAP:
  80. case REDIS_REPLY_SET:
  81. if (r->element != NULL) {
  82. for (j = 0; j < r->elements; j++)
  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. case REDIS_REPLY_DOUBLE:
  91. free(r->str);
  92. break;
  93. }
  94. free(r);
  95. }
  96. static void *createStringObject(const redisReadTask *task, char *str, size_t len) {
  97. redisReply *r, *parent;
  98. char *buf;
  99. r = createReplyObject(task->type);
  100. if (r == NULL)
  101. return NULL;
  102. buf = malloc(len+1);
  103. if (buf == NULL) {
  104. freeReplyObject(r);
  105. return NULL;
  106. }
  107. assert(task->type == REDIS_REPLY_ERROR ||
  108. task->type == REDIS_REPLY_STATUS ||
  109. task->type == REDIS_REPLY_STRING);
  110. /* Copy string value */
  111. memcpy(buf,str,len);
  112. buf[len] = '\0';
  113. r->str = buf;
  114. r->len = len;
  115. if (task->parent) {
  116. parent = task->parent->obj;
  117. assert(parent->type == REDIS_REPLY_ARRAY ||
  118. parent->type == REDIS_REPLY_MAP ||
  119. parent->type == REDIS_REPLY_SET);
  120. parent->element[task->idx] = r;
  121. }
  122. return r;
  123. }
  124. static void *createArrayObject(const redisReadTask *task, int elements) {
  125. redisReply *r, *parent;
  126. r = createReplyObject(task->type);
  127. if (r == NULL)
  128. return NULL;
  129. if (elements > 0) {
  130. r->element = calloc(elements,sizeof(redisReply*));
  131. if (r->element == NULL) {
  132. freeReplyObject(r);
  133. return NULL;
  134. }
  135. }
  136. r->elements = elements;
  137. if (task->parent) {
  138. parent = task->parent->obj;
  139. assert(parent->type == REDIS_REPLY_ARRAY ||
  140. parent->type == REDIS_REPLY_MAP ||
  141. parent->type == REDIS_REPLY_SET);
  142. parent->element[task->idx] = r;
  143. }
  144. return r;
  145. }
  146. static void *createIntegerObject(const redisReadTask *task, long long value) {
  147. redisReply *r, *parent;
  148. r = createReplyObject(REDIS_REPLY_INTEGER);
  149. if (r == NULL)
  150. return NULL;
  151. r->integer = value;
  152. if (task->parent) {
  153. parent = task->parent->obj;
  154. assert(parent->type == REDIS_REPLY_ARRAY ||
  155. parent->type == REDIS_REPLY_MAP ||
  156. parent->type == REDIS_REPLY_SET);
  157. parent->element[task->idx] = r;
  158. }
  159. return r;
  160. }
  161. static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len) {
  162. redisReply *r, *parent;
  163. r = createReplyObject(REDIS_REPLY_DOUBLE);
  164. if (r == NULL)
  165. return NULL;
  166. r->dval = value;
  167. r->str = malloc(len+1);
  168. if (r->str == NULL) {
  169. freeReplyObject(r);
  170. return NULL;
  171. }
  172. /* The double reply also has the original protocol string representing a
  173. * double as a null terminated string. This way the caller does not need
  174. * to format back for string conversion, especially since Redis does efforts
  175. * to make the string more human readable avoiding the calssical double
  176. * decimal string conversion artifacts. */
  177. memcpy(r->str, str, len);
  178. r->str[len] = '\0';
  179. if (task->parent) {
  180. parent = task->parent->obj;
  181. assert(parent->type == REDIS_REPLY_ARRAY ||
  182. parent->type == REDIS_REPLY_MAP ||
  183. parent->type == REDIS_REPLY_SET);
  184. parent->element[task->idx] = r;
  185. }
  186. return r;
  187. }
  188. static void *createNilObject(const redisReadTask *task) {
  189. redisReply *r, *parent;
  190. r = createReplyObject(REDIS_REPLY_NIL);
  191. if (r == NULL)
  192. return NULL;
  193. if (task->parent) {
  194. parent = task->parent->obj;
  195. assert(parent->type == REDIS_REPLY_ARRAY ||
  196. parent->type == REDIS_REPLY_MAP ||
  197. parent->type == REDIS_REPLY_SET);
  198. parent->element[task->idx] = r;
  199. }
  200. return r;
  201. }
  202. static void *createBoolObject(const redisReadTask *task, int bval) {
  203. redisReply *r, *parent;
  204. r = createReplyObject(REDIS_REPLY_BOOL);
  205. if (r == NULL)
  206. return NULL;
  207. r->integer = bval != 0;
  208. if (task->parent) {
  209. parent = task->parent->obj;
  210. assert(parent->type == REDIS_REPLY_ARRAY ||
  211. parent->type == REDIS_REPLY_MAP ||
  212. parent->type == REDIS_REPLY_SET);
  213. parent->element[task->idx] = r;
  214. }
  215. return r;
  216. }
  217. /* Return the number of digits of 'v' when converted to string in radix 10.
  218. * Implementation borrowed from link in redis/src/util.c:string2ll(). */
  219. static uint32_t countDigits(uint64_t v) {
  220. uint32_t result = 1;
  221. for (;;) {
  222. if (v < 10) return result;
  223. if (v < 100) return result + 1;
  224. if (v < 1000) return result + 2;
  225. if (v < 10000) return result + 3;
  226. v /= 10000U;
  227. result += 4;
  228. }
  229. }
  230. /* Helper that calculates the bulk length given a certain string length. */
  231. static size_t bulklen(size_t len) {
  232. return 1+countDigits(len)+2+len+2;
  233. }
  234. int redisvFormatCommand(char **target, const char *format, va_list ap) {
  235. const char *c = format;
  236. char *cmd = NULL; /* final command */
  237. int pos; /* position in final command */
  238. sds curarg, newarg; /* current argument */
  239. int touched = 0; /* was the current argument touched? */
  240. char **curargv = NULL, **newargv = NULL;
  241. int argc = 0;
  242. int totlen = 0;
  243. int error_type = 0; /* 0 = no error; -1 = memory error; -2 = format error */
  244. int j;
  245. /* Abort if there is not target to set */
  246. if (target == NULL)
  247. return -1;
  248. /* Build the command string accordingly to protocol */
  249. curarg = sdsempty();
  250. if (curarg == NULL)
  251. return -1;
  252. while(*c != '\0') {
  253. if (*c != '%' || c[1] == '\0') {
  254. if (*c == ' ') {
  255. if (touched) {
  256. newargv = realloc(curargv,sizeof(char*)*(argc+1));
  257. if (newargv == NULL) goto memory_err;
  258. curargv = newargv;
  259. curargv[argc++] = curarg;
  260. totlen += bulklen(sdslen(curarg));
  261. /* curarg is put in argv so it can be overwritten. */
  262. curarg = sdsempty();
  263. if (curarg == NULL) goto memory_err;
  264. touched = 0;
  265. }
  266. } else {
  267. newarg = sdscatlen(curarg,c,1);
  268. if (newarg == NULL) goto memory_err;
  269. curarg = newarg;
  270. touched = 1;
  271. }
  272. } else {
  273. char *arg;
  274. size_t size;
  275. /* Set newarg so it can be checked even if it is not touched. */
  276. newarg = curarg;
  277. switch(c[1]) {
  278. case 's':
  279. arg = va_arg(ap,char*);
  280. size = strlen(arg);
  281. if (size > 0)
  282. newarg = sdscatlen(curarg,arg,size);
  283. break;
  284. case 'b':
  285. arg = va_arg(ap,char*);
  286. size = va_arg(ap,size_t);
  287. if (size > 0)
  288. newarg = sdscatlen(curarg,arg,size);
  289. break;
  290. case '%':
  291. newarg = sdscat(curarg,"%");
  292. break;
  293. default:
  294. /* Try to detect printf format */
  295. {
  296. static const char intfmts[] = "diouxX";
  297. static const char flags[] = "#0-+ ";
  298. char _format[16];
  299. const char *_p = c+1;
  300. size_t _l = 0;
  301. va_list _cpy;
  302. /* Flags */
  303. while (*_p != '\0' && strchr(flags,*_p) != NULL) _p++;
  304. /* Field width */
  305. while (*_p != '\0' && isdigit(*_p)) _p++;
  306. /* Precision */
  307. if (*_p == '.') {
  308. _p++;
  309. while (*_p != '\0' && isdigit(*_p)) _p++;
  310. }
  311. /* Copy va_list before consuming with va_arg */
  312. va_copy(_cpy,ap);
  313. /* Integer conversion (without modifiers) */
  314. if (strchr(intfmts,*_p) != NULL) {
  315. va_arg(ap,int);
  316. goto fmt_valid;
  317. }
  318. /* Double conversion (without modifiers) */
  319. if (strchr("eEfFgGaA",*_p) != NULL) {
  320. va_arg(ap,double);
  321. goto fmt_valid;
  322. }
  323. /* Size: char */
  324. if (_p[0] == 'h' && _p[1] == 'h') {
  325. _p += 2;
  326. if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
  327. va_arg(ap,int); /* char gets promoted to int */
  328. goto fmt_valid;
  329. }
  330. goto fmt_invalid;
  331. }
  332. /* Size: short */
  333. if (_p[0] == 'h') {
  334. _p += 1;
  335. if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
  336. va_arg(ap,int); /* short gets promoted to int */
  337. goto fmt_valid;
  338. }
  339. goto fmt_invalid;
  340. }
  341. /* Size: long long */
  342. if (_p[0] == 'l' && _p[1] == 'l') {
  343. _p += 2;
  344. if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
  345. va_arg(ap,long long);
  346. goto fmt_valid;
  347. }
  348. goto fmt_invalid;
  349. }
  350. /* Size: long */
  351. if (_p[0] == 'l') {
  352. _p += 1;
  353. if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
  354. va_arg(ap,long);
  355. goto fmt_valid;
  356. }
  357. goto fmt_invalid;
  358. }
  359. fmt_invalid:
  360. va_end(_cpy);
  361. goto format_err;
  362. fmt_valid:
  363. _l = (_p+1)-c;
  364. if (_l < sizeof(_format)-2) {
  365. memcpy(_format,c,_l);
  366. _format[_l] = '\0';
  367. newarg = sdscatvprintf(curarg,_format,_cpy);
  368. /* Update current position (note: outer blocks
  369. * increment c twice so compensate here) */
  370. c = _p-1;
  371. }
  372. va_end(_cpy);
  373. break;
  374. }
  375. }
  376. if (newarg == NULL) goto memory_err;
  377. curarg = newarg;
  378. touched = 1;
  379. c++;
  380. }
  381. c++;
  382. }
  383. /* Add the last argument if needed */
  384. if (touched) {
  385. newargv = realloc(curargv,sizeof(char*)*(argc+1));
  386. if (newargv == NULL) goto memory_err;
  387. curargv = newargv;
  388. curargv[argc++] = curarg;
  389. totlen += bulklen(sdslen(curarg));
  390. } else {
  391. sdsfree(curarg);
  392. }
  393. /* Clear curarg because it was put in curargv or was free'd. */
  394. curarg = NULL;
  395. /* Add bytes needed to hold multi bulk count */
  396. totlen += 1+countDigits(argc)+2;
  397. /* Build the command at protocol level */
  398. cmd = malloc(totlen+1);
  399. if (cmd == NULL) goto memory_err;
  400. pos = sprintf(cmd,"*%d\r\n",argc);
  401. for (j = 0; j < argc; j++) {
  402. pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j]));
  403. memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));
  404. pos += sdslen(curargv[j]);
  405. sdsfree(curargv[j]);
  406. cmd[pos++] = '\r';
  407. cmd[pos++] = '\n';
  408. }
  409. assert(pos == totlen);
  410. cmd[pos] = '\0';
  411. free(curargv);
  412. *target = cmd;
  413. return totlen;
  414. format_err:
  415. error_type = -2;
  416. goto cleanup;
  417. memory_err:
  418. error_type = -1;
  419. goto cleanup;
  420. cleanup:
  421. if (curargv) {
  422. while(argc--)
  423. sdsfree(curargv[argc]);
  424. free(curargv);
  425. }
  426. sdsfree(curarg);
  427. free(cmd);
  428. return error_type;
  429. }
  430. /* Format a command according to the Redis protocol. This function
  431. * takes a format similar to printf:
  432. *
  433. * %s represents a C null terminated string you want to interpolate
  434. * %b represents a binary safe string
  435. *
  436. * When using %b you need to provide both the pointer to the string
  437. * and the length in bytes as a size_t. Examples:
  438. *
  439. * len = redisFormatCommand(target, "GET %s", mykey);
  440. * len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen);
  441. */
  442. int redisFormatCommand(char **target, const char *format, ...) {
  443. va_list ap;
  444. int len;
  445. va_start(ap,format);
  446. len = redisvFormatCommand(target,format,ap);
  447. va_end(ap);
  448. /* The API says "-1" means bad result, but we now also return "-2" in some
  449. * cases. Force the return value to always be -1. */
  450. if (len < 0)
  451. len = -1;
  452. return len;
  453. }
  454. /* Format a command according to the Redis protocol using an sds string and
  455. * sdscatfmt for the processing of arguments. This function takes the
  456. * number of arguments, an array with arguments and an array with their
  457. * lengths. If the latter is set to NULL, strlen will be used to compute the
  458. * argument lengths.
  459. */
  460. int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv,
  461. const size_t *argvlen)
  462. {
  463. sds cmd;
  464. unsigned long long totlen;
  465. int j;
  466. size_t len;
  467. /* Abort on a NULL target */
  468. if (target == NULL)
  469. return -1;
  470. /* Calculate our total size */
  471. totlen = 1+countDigits(argc)+2;
  472. for (j = 0; j < argc; j++) {
  473. len = argvlen ? argvlen[j] : strlen(argv[j]);
  474. totlen += bulklen(len);
  475. }
  476. /* Use an SDS string for command construction */
  477. cmd = sdsempty();
  478. if (cmd == NULL)
  479. return -1;
  480. /* We already know how much storage we need */
  481. cmd = sdsMakeRoomFor(cmd, totlen);
  482. if (cmd == NULL)
  483. return -1;
  484. /* Construct command */
  485. cmd = sdscatfmt(cmd, "*%i\r\n", argc);
  486. for (j=0; j < argc; j++) {
  487. len = argvlen ? argvlen[j] : strlen(argv[j]);
  488. cmd = sdscatfmt(cmd, "$%u\r\n", len);
  489. cmd = sdscatlen(cmd, argv[j], len);
  490. cmd = sdscatlen(cmd, "\r\n", sizeof("\r\n")-1);
  491. }
  492. assert(sdslen(cmd)==totlen);
  493. *target = cmd;
  494. return totlen;
  495. }
  496. void redisFreeSdsCommand(sds cmd) {
  497. sdsfree(cmd);
  498. }
  499. /* Format a command according to the Redis protocol. This function takes the
  500. * number of arguments, an array with arguments and an array with their
  501. * lengths. If the latter is set to NULL, strlen will be used to compute the
  502. * argument lengths.
  503. */
  504. int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen) {
  505. char *cmd = NULL; /* final command */
  506. int pos; /* position in final command */
  507. size_t len;
  508. int totlen, j;
  509. /* Abort on a NULL target */
  510. if (target == NULL)
  511. return -1;
  512. /* Calculate number of bytes needed for the command */
  513. totlen = 1+countDigits(argc)+2;
  514. for (j = 0; j < argc; j++) {
  515. len = argvlen ? argvlen[j] : strlen(argv[j]);
  516. totlen += bulklen(len);
  517. }
  518. /* Build the command at protocol level */
  519. cmd = malloc(totlen+1);
  520. if (cmd == NULL)
  521. return -1;
  522. pos = sprintf(cmd,"*%d\r\n",argc);
  523. for (j = 0; j < argc; j++) {
  524. len = argvlen ? argvlen[j] : strlen(argv[j]);
  525. pos += sprintf(cmd+pos,"$%zu\r\n",len);
  526. memcpy(cmd+pos,argv[j],len);
  527. pos += len;
  528. cmd[pos++] = '\r';
  529. cmd[pos++] = '\n';
  530. }
  531. assert(pos == totlen);
  532. cmd[pos] = '\0';
  533. *target = cmd;
  534. return totlen;
  535. }
  536. void redisFreeCommand(char *cmd) {
  537. free(cmd);
  538. }
  539. void __redisSetError(redisContext *c, int type, const char *str) {
  540. size_t len;
  541. c->err = type;
  542. if (str != NULL) {
  543. len = strlen(str);
  544. len = len < (sizeof(c->errstr)-1) ? len : (sizeof(c->errstr)-1);
  545. memcpy(c->errstr,str,len);
  546. c->errstr[len] = '\0';
  547. } else {
  548. /* Only REDIS_ERR_IO may lack a description! */
  549. assert(type == REDIS_ERR_IO);
  550. strerror_r(errno, c->errstr, sizeof(c->errstr));
  551. }
  552. }
  553. redisReader *redisReaderCreate(void) {
  554. return redisReaderCreateWithFunctions(&defaultFunctions);
  555. }
  556. static redisContext *redisContextInit(void) {
  557. redisContext *c;
  558. c = calloc(1,sizeof(redisContext));
  559. if (c == NULL)
  560. return NULL;
  561. c->obuf = sdsempty();
  562. c->reader = redisReaderCreate();
  563. if (c->obuf == NULL || c->reader == NULL) {
  564. redisFree(c);
  565. return NULL;
  566. }
  567. return c;
  568. }
  569. void redisFree(redisContext *c) {
  570. if (c == NULL)
  571. return;
  572. if (c->fd > 0)
  573. close(c->fd);
  574. sdsfree(c->obuf);
  575. redisReaderFree(c->reader);
  576. free(c->tcp.host);
  577. free(c->tcp.source_addr);
  578. free(c->unix_sock.path);
  579. free(c->timeout);
  580. free(c->saddr);
  581. free(c);
  582. }
  583. int redisFreeKeepFd(redisContext *c) {
  584. int fd = c->fd;
  585. c->fd = -1;
  586. redisFree(c);
  587. return fd;
  588. }
  589. int redisReconnect(redisContext *c) {
  590. c->err = 0;
  591. memset(c->errstr, '\0', strlen(c->errstr));
  592. if (c->fd > 0) {
  593. close(c->fd);
  594. }
  595. sdsfree(c->obuf);
  596. redisReaderFree(c->reader);
  597. c->obuf = sdsempty();
  598. c->reader = redisReaderCreate();
  599. if (c->connection_type == REDIS_CONN_TCP) {
  600. return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
  601. c->timeout, c->tcp.source_addr);
  602. } else if (c->connection_type == REDIS_CONN_UNIX) {
  603. return redisContextConnectUnix(c, c->unix_sock.path, c->timeout);
  604. } else {
  605. /* Something bad happened here and shouldn't have. There isn't
  606. enough information in the context to reconnect. */
  607. __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect");
  608. }
  609. return REDIS_ERR;
  610. }
  611. /* Connect to a Redis instance. On error the field error in the returned
  612. * context will be set to the return value of the error function.
  613. * When no set of reply functions is given, the default set will be used. */
  614. redisContext *redisConnect(const char *ip, int port) {
  615. redisContext *c;
  616. c = redisContextInit();
  617. if (c == NULL)
  618. return NULL;
  619. c->flags |= REDIS_BLOCK;
  620. redisContextConnectTcp(c,ip,port,NULL);
  621. return c;
  622. }
  623. redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) {
  624. redisContext *c;
  625. c = redisContextInit();
  626. if (c == NULL)
  627. return NULL;
  628. c->flags |= REDIS_BLOCK;
  629. redisContextConnectTcp(c,ip,port,&tv);
  630. return c;
  631. }
  632. redisContext *redisConnectNonBlock(const char *ip, int port) {
  633. redisContext *c;
  634. c = redisContextInit();
  635. if (c == NULL)
  636. return NULL;
  637. c->flags &= ~REDIS_BLOCK;
  638. redisContextConnectTcp(c,ip,port,NULL);
  639. return c;
  640. }
  641. redisContext *redisConnectBindNonBlock(const char *ip, int port,
  642. const char *source_addr) {
  643. redisContext *c = redisContextInit();
  644. if (c == NULL)
  645. return NULL;
  646. c->flags &= ~REDIS_BLOCK;
  647. redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
  648. return c;
  649. }
  650. redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
  651. const char *source_addr) {
  652. redisContext *c = redisContextInit();
  653. if (c == NULL)
  654. return NULL;
  655. c->flags &= ~REDIS_BLOCK;
  656. c->flags |= REDIS_REUSEADDR;
  657. redisContextConnectBindTcp(c,ip,port,NULL,source_addr);
  658. return c;
  659. }
  660. redisContext *redisConnectUnix(const char *path) {
  661. redisContext *c;
  662. c = redisContextInit();
  663. if (c == NULL)
  664. return NULL;
  665. c->flags |= REDIS_BLOCK;
  666. redisContextConnectUnix(c,path,NULL);
  667. return c;
  668. }
  669. redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) {
  670. redisContext *c;
  671. c = redisContextInit();
  672. if (c == NULL)
  673. return NULL;
  674. c->flags |= REDIS_BLOCK;
  675. redisContextConnectUnix(c,path,&tv);
  676. return c;
  677. }
  678. redisContext *redisConnectUnixNonBlock(const char *path) {
  679. redisContext *c;
  680. c = redisContextInit();
  681. if (c == NULL)
  682. return NULL;
  683. c->flags &= ~REDIS_BLOCK;
  684. redisContextConnectUnix(c,path,NULL);
  685. return c;
  686. }
  687. redisContext *redisConnectFd(int fd) {
  688. redisContext *c;
  689. c = redisContextInit();
  690. if (c == NULL)
  691. return NULL;
  692. c->fd = fd;
  693. c->flags |= REDIS_BLOCK | REDIS_CONNECTED;
  694. return c;
  695. }
  696. /* Set read/write timeout on a blocking socket. */
  697. int redisSetTimeout(redisContext *c, const struct timeval tv) {
  698. if (c->flags & REDIS_BLOCK)
  699. return redisContextSetTimeout(c,tv);
  700. return REDIS_ERR;
  701. }
  702. /* Enable connection KeepAlive. */
  703. int redisEnableKeepAlive(redisContext *c) {
  704. if (redisKeepAlive(c, REDIS_KEEPALIVE_INTERVAL) != REDIS_OK)
  705. return REDIS_ERR;
  706. return REDIS_OK;
  707. }
  708. /* Use this function to handle a read event on the descriptor. It will try
  709. * and read some bytes from the socket and feed them to the reply parser.
  710. *
  711. * After this function is called, you may use redisGetReplyFromReader to
  712. * see if there is a reply available. */
  713. int redisBufferRead(redisContext *c) {
  714. char buf[1024*16];
  715. int nread;
  716. /* Return early when the context has seen an error. */
  717. if (c->err)
  718. return REDIS_ERR;
  719. nread = read(c->fd,buf,sizeof(buf));
  720. if (nread == -1) {
  721. if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
  722. /* Try again later */
  723. } else {
  724. __redisSetError(c,REDIS_ERR_IO,NULL);
  725. return REDIS_ERR;
  726. }
  727. } else if (nread == 0) {
  728. __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection");
  729. return REDIS_ERR;
  730. } else {
  731. if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {
  732. __redisSetError(c,c->reader->err,c->reader->errstr);
  733. return REDIS_ERR;
  734. }
  735. }
  736. return REDIS_OK;
  737. }
  738. /* Write the output buffer to the socket.
  739. *
  740. * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
  741. * successfully written to the socket. When the buffer is empty after the
  742. * write operation, "done" is set to 1 (if given).
  743. *
  744. * Returns REDIS_ERR if an error occurred trying to write and sets
  745. * c->errstr to hold the appropriate error string.
  746. */
  747. int redisBufferWrite(redisContext *c, int *done) {
  748. int nwritten;
  749. /* Return early when the context has seen an error. */
  750. if (c->err)
  751. return REDIS_ERR;
  752. if (sdslen(c->obuf) > 0) {
  753. nwritten = write(c->fd,c->obuf,sdslen(c->obuf));
  754. if (nwritten == -1) {
  755. if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) {
  756. /* Try again later */
  757. } else {
  758. __redisSetError(c,REDIS_ERR_IO,NULL);
  759. return REDIS_ERR;
  760. }
  761. } else if (nwritten > 0) {
  762. if (nwritten == (signed)sdslen(c->obuf)) {
  763. sdsfree(c->obuf);
  764. c->obuf = sdsempty();
  765. } else {
  766. sdsrange(c->obuf,nwritten,-1);
  767. }
  768. }
  769. }
  770. if (done != NULL) *done = (sdslen(c->obuf) == 0);
  771. return REDIS_OK;
  772. }
  773. /* Internal helper function to try and get a reply from the reader,
  774. * or set an error in the context otherwise. */
  775. int redisGetReplyFromReader(redisContext *c, void **reply) {
  776. if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) {
  777. __redisSetError(c,c->reader->err,c->reader->errstr);
  778. return REDIS_ERR;
  779. }
  780. return REDIS_OK;
  781. }
  782. int redisGetReply(redisContext *c, void **reply) {
  783. int wdone = 0;
  784. void *aux = NULL;
  785. /* Try to read pending replies */
  786. if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
  787. return REDIS_ERR;
  788. /* For the blocking context, flush output buffer and read reply */
  789. if (aux == NULL && c->flags & REDIS_BLOCK) {
  790. /* Write until done */
  791. do {
  792. if (redisBufferWrite(c,&wdone) == REDIS_ERR)
  793. return REDIS_ERR;
  794. } while (!wdone);
  795. /* Read until there is a reply */
  796. do {
  797. if (redisBufferRead(c) == REDIS_ERR)
  798. return REDIS_ERR;
  799. if (redisGetReplyFromReader(c,&aux) == REDIS_ERR)
  800. return REDIS_ERR;
  801. } while (aux == NULL);
  802. }
  803. /* Set reply object */
  804. if (reply != NULL) *reply = aux;
  805. return REDIS_OK;
  806. }
  807. /* Helper function for the redisAppendCommand* family of functions.
  808. *
  809. * Write a formatted command to the output buffer. When this family
  810. * is used, you need to call redisGetReply yourself to retrieve
  811. * the reply (or replies in pub/sub).
  812. */
  813. int __redisAppendCommand(redisContext *c, const char *cmd, size_t len) {
  814. sds newbuf;
  815. newbuf = sdscatlen(c->obuf,cmd,len);
  816. if (newbuf == NULL) {
  817. __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
  818. return REDIS_ERR;
  819. }
  820. c->obuf = newbuf;
  821. return REDIS_OK;
  822. }
  823. int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len) {
  824. if (__redisAppendCommand(c, cmd, len) != REDIS_OK) {
  825. return REDIS_ERR;
  826. }
  827. return REDIS_OK;
  828. }
  829. int redisvAppendCommand(redisContext *c, const char *format, va_list ap) {
  830. char *cmd;
  831. int len;
  832. len = redisvFormatCommand(&cmd,format,ap);
  833. if (len == -1) {
  834. __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
  835. return REDIS_ERR;
  836. } else if (len == -2) {
  837. __redisSetError(c,REDIS_ERR_OTHER,"Invalid format string");
  838. return REDIS_ERR;
  839. }
  840. if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
  841. free(cmd);
  842. return REDIS_ERR;
  843. }
  844. free(cmd);
  845. return REDIS_OK;
  846. }
  847. int redisAppendCommand(redisContext *c, const char *format, ...) {
  848. va_list ap;
  849. int ret;
  850. va_start(ap,format);
  851. ret = redisvAppendCommand(c,format,ap);
  852. va_end(ap);
  853. return ret;
  854. }
  855. int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
  856. sds cmd;
  857. int len;
  858. len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen);
  859. if (len == -1) {
  860. __redisSetError(c,REDIS_ERR_OOM,"Out of memory");
  861. return REDIS_ERR;
  862. }
  863. if (__redisAppendCommand(c,cmd,len) != REDIS_OK) {
  864. sdsfree(cmd);
  865. return REDIS_ERR;
  866. }
  867. sdsfree(cmd);
  868. return REDIS_OK;
  869. }
  870. /* Helper function for the redisCommand* family of functions.
  871. *
  872. * Write a formatted command to the output buffer. If the given context is
  873. * blocking, immediately read the reply into the "reply" pointer. When the
  874. * context is non-blocking, the "reply" pointer will not be used and the
  875. * command is simply appended to the write buffer.
  876. *
  877. * Returns the reply when a reply was successfully retrieved. Returns NULL
  878. * otherwise. When NULL is returned in a blocking context, the error field
  879. * in the context will be set.
  880. */
  881. static void *__redisBlockForReply(redisContext *c) {
  882. void *reply;
  883. if (c->flags & REDIS_BLOCK) {
  884. if (redisGetReply(c,&reply) != REDIS_OK)
  885. return NULL;
  886. return reply;
  887. }
  888. return NULL;
  889. }
  890. void *redisvCommand(redisContext *c, const char *format, va_list ap) {
  891. if (redisvAppendCommand(c,format,ap) != REDIS_OK)
  892. return NULL;
  893. return __redisBlockForReply(c);
  894. }
  895. void *redisCommand(redisContext *c, const char *format, ...) {
  896. va_list ap;
  897. va_start(ap,format);
  898. void *reply = redisvCommand(c,format,ap);
  899. va_end(ap);
  900. return reply;
  901. }
  902. void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) {
  903. if (redisAppendCommandArgv(c,argc,argv,argvlen) != REDIS_OK)
  904. return NULL;
  905. return __redisBlockForReply(c);
  906. }