hiredis.c 35 KB

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