2
0

hiredis.c 32 KB

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