诸暨麻将添加redis
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

670 linhas
20 KiB

  1. /*
  2. * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
  3. * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * * Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of Redis nor the names of its contributors may be used
  16. * to endorse or promote products derived from this software without
  17. * specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "fmacros.h"
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #ifndef _MSC_VER
  35. #include <unistd.h>
  36. #include <strings.h>
  37. #endif
  38. #include <assert.h>
  39. #include <errno.h>
  40. #include <ctype.h>
  41. #include <limits.h>
  42. #include <math.h>
  43. #include "read.h"
  44. #include "sds.h"
  45. #include "win32.h"
  46. static void __redisReaderSetError(redisReader *r, int type, const char *str) {
  47. size_t len;
  48. if (r->reply != NULL && r->fn && r->fn->freeObject) {
  49. r->fn->freeObject(r->reply);
  50. r->reply = NULL;
  51. }
  52. /* Clear input buffer on errors. */
  53. sdsfree(r->buf);
  54. r->buf = NULL;
  55. r->pos = r->len = 0;
  56. /* Reset task stack. */
  57. r->ridx = -1;
  58. /* Set error. */
  59. r->err = type;
  60. len = strlen(str);
  61. len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);
  62. memcpy(r->errstr,str,len);
  63. r->errstr[len] = '\0';
  64. }
  65. static size_t chrtos(char *buf, size_t size, char byte) {
  66. size_t len = 0;
  67. switch(byte) {
  68. case '\\':
  69. case '"':
  70. len = snprintf(buf,size,"\"\\%c\"",byte);
  71. break;
  72. case '\n': len = snprintf(buf,size,"\"\\n\""); break;
  73. case '\r': len = snprintf(buf,size,"\"\\r\""); break;
  74. case '\t': len = snprintf(buf,size,"\"\\t\""); break;
  75. case '\a': len = snprintf(buf,size,"\"\\a\""); break;
  76. case '\b': len = snprintf(buf,size,"\"\\b\""); break;
  77. default:
  78. if (isprint(byte))
  79. len = snprintf(buf,size,"\"%c\"",byte);
  80. else
  81. len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte);
  82. break;
  83. }
  84. return len;
  85. }
  86. static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {
  87. char cbuf[8], sbuf[128];
  88. chrtos(cbuf,sizeof(cbuf),byte);
  89. snprintf(sbuf,sizeof(sbuf),
  90. "Protocol error, got %s as reply type byte", cbuf);
  91. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);
  92. }
  93. static void __redisReaderSetErrorOOM(redisReader *r) {
  94. __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory");
  95. }
  96. static char *readBytes(redisReader *r, unsigned int bytes) {
  97. char *p;
  98. if (r->len-r->pos >= bytes) {
  99. p = r->buf+r->pos;
  100. r->pos += bytes;
  101. return p;
  102. }
  103. return NULL;
  104. }
  105. /* Find pointer to \r\n. */
  106. static char *seekNewline(char *s, size_t len) {
  107. int pos = 0;
  108. int _len = len-1;
  109. /* Position should be < len-1 because the character at "pos" should be
  110. * followed by a \n. Note that strchr cannot be used because it doesn't
  111. * allow to search a limited length and the buffer that is being searched
  112. * might not have a trailing NULL character. */
  113. while (pos < _len) {
  114. while(pos < _len && s[pos] != '\r') pos++;
  115. if (pos==_len) {
  116. /* Not found. */
  117. return NULL;
  118. } else {
  119. if (s[pos+1] == '\n') {
  120. /* Found. */
  121. return s+pos;
  122. } else {
  123. /* Continue searching. */
  124. pos++;
  125. }
  126. }
  127. }
  128. return NULL;
  129. }
  130. /* Convert a string into a long long. Returns REDIS_OK if the string could be
  131. * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value
  132. * will be set to the parsed value when appropriate.
  133. *
  134. * Note that this function demands that the string strictly represents
  135. * a long long: no spaces or other characters before or after the string
  136. * representing the number are accepted, nor zeroes at the start if not
  137. * for the string "0" representing the zero number.
  138. *
  139. * Because of its strictness, it is safe to use this function to check if
  140. * you can convert a string into a long long, and obtain back the string
  141. * from the number without any loss in the string representation. */
  142. static int string2ll(const char *s, size_t slen, long long *value) {
  143. const char *p = s;
  144. size_t plen = 0;
  145. int negative = 0;
  146. unsigned long long v;
  147. if (plen == slen)
  148. return REDIS_ERR;
  149. /* Special case: first and only digit is 0. */
  150. if (slen == 1 && p[0] == '0') {
  151. if (value != NULL) *value = 0;
  152. return REDIS_OK;
  153. }
  154. if (p[0] == '-') {
  155. negative = 1;
  156. p++; plen++;
  157. /* Abort on only a negative sign. */
  158. if (plen == slen)
  159. return REDIS_ERR;
  160. }
  161. /* First digit should be 1-9, otherwise the string should just be 0. */
  162. if (p[0] >= '1' && p[0] <= '9') {
  163. v = p[0]-'0';
  164. p++; plen++;
  165. } else if (p[0] == '0' && slen == 1) {
  166. *value = 0;
  167. return REDIS_OK;
  168. } else {
  169. return REDIS_ERR;
  170. }
  171. while (plen < slen && p[0] >= '0' && p[0] <= '9') {
  172. if (v > (ULLONG_MAX / 10)) /* Overflow. */
  173. return REDIS_ERR;
  174. v *= 10;
  175. if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */
  176. return REDIS_ERR;
  177. v += p[0]-'0';
  178. p++; plen++;
  179. }
  180. /* Return if not all bytes were used. */
  181. if (plen < slen)
  182. return REDIS_ERR;
  183. if (negative) {
  184. if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
  185. return REDIS_ERR;
  186. if (value != NULL) *value = -v;
  187. } else {
  188. if (v > LLONG_MAX) /* Overflow. */
  189. return REDIS_ERR;
  190. if (value != NULL) *value = v;
  191. }
  192. return REDIS_OK;
  193. }
  194. static char *readLine(redisReader *r, int *_len) {
  195. char *p, *s;
  196. int len;
  197. p = r->buf+r->pos;
  198. s = seekNewline(p,(r->len-r->pos));
  199. if (s != NULL) {
  200. len = s-(r->buf+r->pos);
  201. r->pos += len+2; /* skip \r\n */
  202. if (_len) *_len = len;
  203. return p;
  204. }
  205. return NULL;
  206. }
  207. static void moveToNextTask(redisReader *r) {
  208. redisReadTask *cur, *prv;
  209. while (r->ridx >= 0) {
  210. /* Return a.s.a.p. when the stack is now empty. */
  211. if (r->ridx == 0) {
  212. r->ridx--;
  213. return;
  214. }
  215. cur = &(r->rstack[r->ridx]);
  216. prv = &(r->rstack[r->ridx-1]);
  217. assert(prv->type == REDIS_REPLY_ARRAY ||
  218. prv->type == REDIS_REPLY_MAP ||
  219. prv->type == REDIS_REPLY_SET);
  220. if (cur->idx == prv->elements-1) {
  221. r->ridx--;
  222. } else {
  223. /* Reset the type because the next item can be anything */
  224. assert(cur->idx < prv->elements);
  225. cur->type = -1;
  226. cur->elements = -1;
  227. cur->idx++;
  228. return;
  229. }
  230. }
  231. }
  232. static int processLineItem(redisReader *r) {
  233. redisReadTask *cur = &(r->rstack[r->ridx]);
  234. void *obj;
  235. char *p;
  236. int len;
  237. if ((p = readLine(r,&len)) != NULL) {
  238. if (cur->type == REDIS_REPLY_INTEGER) {
  239. if (r->fn && r->fn->createInteger) {
  240. long long v;
  241. if (string2ll(p, len, &v) == REDIS_ERR) {
  242. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  243. "Bad integer value");
  244. return REDIS_ERR;
  245. }
  246. obj = r->fn->createInteger(cur,v);
  247. } else {
  248. obj = (void*)REDIS_REPLY_INTEGER;
  249. }
  250. } else if (cur->type == REDIS_REPLY_DOUBLE) {
  251. if (r->fn && r->fn->createDouble) {
  252. char buf[326], *eptr;
  253. double d;
  254. if ((size_t)len >= sizeof(buf)) {
  255. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  256. "Double value is too large");
  257. return REDIS_ERR;
  258. }
  259. memcpy(buf,p,len);
  260. buf[len] = '\0';
  261. if (strcasecmp(buf,",inf") == 0) {
  262. d = INFINITY; /* Positive infinite. */
  263. } else if (strcasecmp(buf,",-inf") == 0) {
  264. d = -INFINITY; /* Negative infinite. */
  265. } else {
  266. d = strtod((char*)buf,&eptr);
  267. if (buf[0] == '\0' || eptr[0] != '\0' || isnan(d)) {
  268. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  269. "Bad double value");
  270. return REDIS_ERR;
  271. }
  272. }
  273. obj = r->fn->createDouble(cur,d,buf,len);
  274. } else {
  275. obj = (void*)REDIS_REPLY_DOUBLE;
  276. }
  277. } else if (cur->type == REDIS_REPLY_NIL) {
  278. if (r->fn && r->fn->createNil)
  279. obj = r->fn->createNil(cur);
  280. else
  281. obj = (void*)REDIS_REPLY_NIL;
  282. } else if (cur->type == REDIS_REPLY_BOOL) {
  283. int bval = p[0] == 't' || p[0] == 'T';
  284. if (r->fn && r->fn->createBool)
  285. obj = r->fn->createBool(cur,bval);
  286. else
  287. obj = (void*)REDIS_REPLY_BOOL;
  288. } else {
  289. /* Type will be error or status. */
  290. if (r->fn && r->fn->createString)
  291. obj = r->fn->createString(cur,p,len);
  292. else
  293. obj = (void*)(size_t)(cur->type);
  294. }
  295. if (obj == NULL) {
  296. __redisReaderSetErrorOOM(r);
  297. return REDIS_ERR;
  298. }
  299. /* Set reply if this is the root object. */
  300. if (r->ridx == 0) r->reply = obj;
  301. moveToNextTask(r);
  302. return REDIS_OK;
  303. }
  304. return REDIS_ERR;
  305. }
  306. static int processBulkItem(redisReader *r) {
  307. redisReadTask *cur = &(r->rstack[r->ridx]);
  308. void *obj = NULL;
  309. char *p, *s;
  310. long long len;
  311. unsigned long bytelen;
  312. int success = 0;
  313. p = r->buf+r->pos;
  314. s = seekNewline(p,r->len-r->pos);
  315. if (s != NULL) {
  316. p = r->buf+r->pos;
  317. bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
  318. if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) {
  319. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  320. "Bad bulk string length");
  321. return REDIS_ERR;
  322. }
  323. if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) {
  324. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  325. "Bulk string length out of range");
  326. return REDIS_ERR;
  327. }
  328. if (len == -1) {
  329. /* The nil object can always be created. */
  330. if (r->fn && r->fn->createNil)
  331. obj = r->fn->createNil(cur);
  332. else
  333. obj = (void*)REDIS_REPLY_NIL;
  334. success = 1;
  335. } else {
  336. /* Only continue when the buffer contains the entire bulk item. */
  337. bytelen += len+2; /* include \r\n */
  338. if (r->pos+bytelen <= r->len) {
  339. if (r->fn && r->fn->createString)
  340. obj = r->fn->createString(cur,s+2,len);
  341. else
  342. obj = (void*)REDIS_REPLY_STRING;
  343. success = 1;
  344. }
  345. }
  346. /* Proceed when obj was created. */
  347. if (success) {
  348. if (obj == NULL) {
  349. __redisReaderSetErrorOOM(r);
  350. return REDIS_ERR;
  351. }
  352. r->pos += bytelen;
  353. /* Set reply if this is the root object. */
  354. if (r->ridx == 0) r->reply = obj;
  355. moveToNextTask(r);
  356. return REDIS_OK;
  357. }
  358. }
  359. return REDIS_ERR;
  360. }
  361. /* Process the array, map and set types. */
  362. static int processAggregateItem(redisReader *r) {
  363. redisReadTask *cur = &(r->rstack[r->ridx]);
  364. void *obj;
  365. char *p;
  366. long long elements;
  367. int root = 0, len;
  368. /* Set error for nested multi bulks with depth > 7 */
  369. if (r->ridx == 8) {
  370. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  371. "No support for nested multi bulk replies with depth > 7");
  372. return REDIS_ERR;
  373. }
  374. if ((p = readLine(r,&len)) != NULL) {
  375. if (string2ll(p, len, &elements) == REDIS_ERR) {
  376. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  377. "Bad multi-bulk length");
  378. return REDIS_ERR;
  379. }
  380. root = (r->ridx == 0);
  381. if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX)) {
  382. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  383. "Multi-bulk length out of range");
  384. return REDIS_ERR;
  385. }
  386. if (elements == -1) {
  387. if (r->fn && r->fn->createNil)
  388. obj = r->fn->createNil(cur);
  389. else
  390. obj = (void*)REDIS_REPLY_NIL;
  391. if (obj == NULL) {
  392. __redisReaderSetErrorOOM(r);
  393. return REDIS_ERR;
  394. }
  395. moveToNextTask(r);
  396. } else {
  397. if (cur->type == REDIS_REPLY_MAP) elements *= 2;
  398. if (r->fn && r->fn->createArray)
  399. obj = r->fn->createArray(cur,elements);
  400. else
  401. obj = (void*)(long)cur->type;
  402. if (obj == NULL) {
  403. __redisReaderSetErrorOOM(r);
  404. return REDIS_ERR;
  405. }
  406. /* Modify task stack when there are more than 0 elements. */
  407. if (elements > 0) {
  408. cur->elements = elements;
  409. cur->obj = obj;
  410. r->ridx++;
  411. r->rstack[r->ridx].type = -1;
  412. r->rstack[r->ridx].elements = -1;
  413. r->rstack[r->ridx].idx = 0;
  414. r->rstack[r->ridx].obj = NULL;
  415. r->rstack[r->ridx].parent = cur;
  416. r->rstack[r->ridx].privdata = r->privdata;
  417. } else {
  418. moveToNextTask(r);
  419. }
  420. }
  421. /* Set reply if this is the root object. */
  422. if (root) r->reply = obj;
  423. return REDIS_OK;
  424. }
  425. return REDIS_ERR;
  426. }
  427. static int processItem(redisReader *r) {
  428. redisReadTask *cur = &(r->rstack[r->ridx]);
  429. char *p;
  430. /* check if we need to read type */
  431. if (cur->type < 0) {
  432. if ((p = readBytes(r,1)) != NULL) {
  433. switch (p[0]) {
  434. case '-':
  435. cur->type = REDIS_REPLY_ERROR;
  436. break;
  437. case '+':
  438. cur->type = REDIS_REPLY_STATUS;
  439. break;
  440. case ':':
  441. cur->type = REDIS_REPLY_INTEGER;
  442. break;
  443. case ',':
  444. cur->type = REDIS_REPLY_DOUBLE;
  445. break;
  446. case '_':
  447. cur->type = REDIS_REPLY_NIL;
  448. break;
  449. case '$':
  450. cur->type = REDIS_REPLY_STRING;
  451. break;
  452. case '*':
  453. cur->type = REDIS_REPLY_ARRAY;
  454. break;
  455. case '%':
  456. cur->type = REDIS_REPLY_MAP;
  457. break;
  458. case '~':
  459. cur->type = REDIS_REPLY_SET;
  460. break;
  461. case '#':
  462. cur->type = REDIS_REPLY_BOOL;
  463. break;
  464. default:
  465. __redisReaderSetErrorProtocolByte(r,*p);
  466. return REDIS_ERR;
  467. }
  468. } else {
  469. /* could not consume 1 byte */
  470. return REDIS_ERR;
  471. }
  472. }
  473. /* process typed item */
  474. switch(cur->type) {
  475. case REDIS_REPLY_ERROR:
  476. case REDIS_REPLY_STATUS:
  477. case REDIS_REPLY_INTEGER:
  478. case REDIS_REPLY_DOUBLE:
  479. case REDIS_REPLY_NIL:
  480. case REDIS_REPLY_BOOL:
  481. return processLineItem(r);
  482. case REDIS_REPLY_STRING:
  483. return processBulkItem(r);
  484. case REDIS_REPLY_ARRAY:
  485. case REDIS_REPLY_MAP:
  486. case REDIS_REPLY_SET:
  487. return processAggregateItem(r);
  488. default:
  489. assert(NULL);
  490. return REDIS_ERR; /* Avoid warning. */
  491. }
  492. }
  493. redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) {
  494. redisReader *r;
  495. r = calloc(1,sizeof(redisReader));
  496. if (r == NULL)
  497. return NULL;
  498. r->fn = fn;
  499. r->buf = sdsempty();
  500. r->maxbuf = REDIS_READER_MAX_BUF;
  501. if (r->buf == NULL) {
  502. free(r);
  503. return NULL;
  504. }
  505. r->ridx = -1;
  506. return r;
  507. }
  508. void redisReaderFree(redisReader *r) {
  509. if (r == NULL)
  510. return;
  511. if (r->reply != NULL && r->fn && r->fn->freeObject)
  512. r->fn->freeObject(r->reply);
  513. sdsfree(r->buf);
  514. free(r);
  515. }
  516. int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
  517. sds newbuf;
  518. /* Return early when this reader is in an erroneous state. */
  519. if (r->err)
  520. return REDIS_ERR;
  521. /* Copy the provided buffer. */
  522. if (buf != NULL && len >= 1) {
  523. /* Destroy internal buffer when it is empty and is quite large. */
  524. if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
  525. sdsfree(r->buf);
  526. r->buf = sdsempty();
  527. r->pos = 0;
  528. /* r->buf should not be NULL since we just free'd a larger one. */
  529. assert(r->buf != NULL);
  530. }
  531. newbuf = sdscatlen(r->buf,buf,len);
  532. if (newbuf == NULL) {
  533. __redisReaderSetErrorOOM(r);
  534. return REDIS_ERR;
  535. }
  536. r->buf = newbuf;
  537. r->len = sdslen(r->buf);
  538. }
  539. return REDIS_OK;
  540. }
  541. int redisReaderGetReply(redisReader *r, void **reply) {
  542. /* Default target pointer to NULL. */
  543. if (reply != NULL)
  544. *reply = NULL;
  545. /* Return early when this reader is in an erroneous state. */
  546. if (r->err)
  547. return REDIS_ERR;
  548. /* When the buffer is empty, there will never be a reply. */
  549. if (r->len == 0)
  550. return REDIS_OK;
  551. /* Set first item to process when the stack is empty. */
  552. if (r->ridx == -1) {
  553. r->rstack[0].type = -1;
  554. r->rstack[0].elements = -1;
  555. r->rstack[0].idx = -1;
  556. r->rstack[0].obj = NULL;
  557. r->rstack[0].parent = NULL;
  558. r->rstack[0].privdata = r->privdata;
  559. r->ridx = 0;
  560. }
  561. /* Process items in reply. */
  562. while (r->ridx >= 0)
  563. if (processItem(r) != REDIS_OK)
  564. break;
  565. /* Return ASAP when an error occurred. */
  566. if (r->err)
  567. return REDIS_ERR;
  568. /* Discard part of the buffer when we've consumed at least 1k, to avoid
  569. * doing unnecessary calls to memmove() in sds.c. */
  570. if (r->pos >= 1024) {
  571. sdsrange(r->buf,r->pos,-1);
  572. r->pos = 0;
  573. r->len = sdslen(r->buf);
  574. }
  575. /* Emit a reply when there is one. */
  576. if (r->ridx == -1) {
  577. if (reply != NULL) {
  578. *reply = r->reply;
  579. } else if (r->reply != NULL && r->fn && r->fn->freeObject) {
  580. r->fn->freeObject(r->reply);
  581. }
  582. r->reply = NULL;
  583. }
  584. return REDIS_OK;
  585. }