hiredis.c 28 KB

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