1 #include "redis.h" 2 #include <sys/uio.h> 3 4 static void setProtocolError(redisClient *c, int pos); 5 6 void *dupClientReplyValue(void *o) { 7 incrRefCount((robj*)o); 8 return o; 9 } 10 11 int listMatchObjects(void *a, void *b) { 12 return equalStringObjects(a,b); 13 } 14 15 redisClient *createClient(int fd) { 16 redisClient *c = zmalloc(sizeof(redisClient)); 17 c->bufpos = 0; 18 19 /* passing -1 as fd it is possible to create a non connected client. 20 * This is useful since all the Redis commands needs to be executed 21 * in the context of a client. When commands are executed in other 22 * contexts (for instance a Lua script) we need a non connected client. */ 23 if (fd != -1) { 24 anetNonBlock(NULL,fd); 25 anetTcpNoDelay(NULL,fd); 26 if (aeCreateFileEvent(server.el,fd,AE_READABLE, 27 readQueryFromClient, c) == AE_ERR) 28 { 29 close(fd); 30 zfree(c); 31 return NULL; 32 } 33 } 34 35 selectDb(c,0); 36 c->fd = fd; 37 c->querybuf = sdsempty(); 38 c->reqtype = 0; 39 c->argc = 0; 40 c->argv = NULL; 41 c->cmd = c->lastcmd = NULL; 42 c->multibulklen = 0; 43 c->bulklen = -1; 44 c->sentlen = 0; 45 c->flags = 0; 46 c->lastinteraction = time(NULL); 47 c->authenticated = 0; 48 c->replstate = REDIS_REPL_NONE; 49 c->reply = listCreate(); 50 listSetFreeMethod(c->reply,decrRefCount); 51 listSetDupMethod(c->reply,dupClientReplyValue); 52 c->bpop.keys = NULL; 53 c->bpop.count = 0; 54 c->bpop.timeout = 0; 55 c->bpop.target = NULL; 56 c->io_keys = listCreate(); 57 c->watched_keys = listCreate(); 58 listSetFreeMethod(c->io_keys,decrRefCount); 59 c->pubsub_channels = dictCreate(&setDictType,NULL); 60 c->pubsub_patterns = listCreate(); 61 listSetFreeMethod(c->pubsub_patterns,decrRefCount); 62 listSetMatchMethod(c->pubsub_patterns,listMatchObjects); 63 if (fd != -1) listAddNodeTail(server.clients,c); 64 initClientMultiState(c); 65 return c; 66 } 67 68 /* Set the event loop to listen for write events on the client's socket. 69 * Typically gets called every time a reply is built. */ 70 int _installWriteEvent(redisClient *c) { 71 if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK; 72 if (c->fd <= 0) return REDIS_ERR; 73 if (c->bufpos == 0 && listLength(c->reply) == 0 && 74 (c->replstate == REDIS_REPL_NONE || 75 c->replstate == REDIS_REPL_ONLINE) && 76 aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, 77 sendReplyToClient, c) == AE_ERR) return REDIS_ERR; 78 return REDIS_OK; 79 } 80 81 /* Create a duplicate of the last object in the reply list when 82 * it is not exclusively owned by the reply list. */ 83 robj *dupLastObjectIfNeeded(list *reply) { 84 robj *new, *cur; 85 listNode *ln; 86 redisAssert(listLength(reply) > 0); 87 ln = listLast(reply); 88 cur = listNodeValue(ln); 89 if (cur->refcount > 1) { 90 new = dupStringObject(cur); 91 decrRefCount(cur); 92 listNodeValue(ln) = new; 93 } 94 return listNodeValue(ln); 95 } 96 97 /* ----------------------------------------------------------------------------- 98 * Low level functions to add more data to output buffers. 99 * -------------------------------------------------------------------------- */ 100 101 int _addReplyToBuffer(redisClient *c, char *s, size_t len) { 102 size_t available = sizeof(c->buf)-c->bufpos; 103 104 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return REDIS_OK; 105 106 /* If there already are entries in the reply list, we cannot 107 * add anything more to the static buffer. */ 108 if (listLength(c->reply) > 0) return REDIS_ERR; 109 110 /* Check that the buffer has enough space available for this string. */ 111 if (len > available) return REDIS_ERR; 112 113 memcpy(c->buf+c->bufpos,s,len); 114 c->bufpos+=len; 115 return REDIS_OK; 116 } 117 118 void _addReplyObjectToList(redisClient *c, robj *o) { 119 robj *tail; 120 121 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 122 123 if (listLength(c->reply) == 0) { 124 incrRefCount(o); 125 listAddNodeTail(c->reply,o); 126 } else { 127 tail = listNodeValue(listLast(c->reply)); 128 129 /* Append to this object when possible. */ 130 if (tail->ptr != NULL && 131 sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES) 132 { 133 tail = dupLastObjectIfNeeded(c->reply); 134 tail->ptr = sdscatlen(tail->ptr,o->ptr,sdslen(o->ptr)); 135 } else { 136 incrRefCount(o); 137 listAddNodeTail(c->reply,o); 138 } 139 } 140 } 141 142 /* This method takes responsibility over the sds. When it is no longer 143 * needed it will be free'd, otherwise it ends up in a robj. */ 144 void _addReplySdsToList(redisClient *c, sds s) { 145 robj *tail; 146 147 if (c->flags & REDIS_CLOSE_AFTER_REPLY) { 148 sdsfree(s); 149 return; 150 } 151 152 if (listLength(c->reply) == 0) { 153 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 154 } else { 155 tail = listNodeValue(listLast(c->reply)); 156 157 /* Append to this object when possible. */ 158 if (tail->ptr != NULL && 159 sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES) 160 { 161 tail = dupLastObjectIfNeeded(c->reply); 162 tail->ptr = sdscatlen(tail->ptr,s,sdslen(s)); 163 sdsfree(s); 164 } else { 165 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 166 } 167 } 168 } 169 170 void _addReplyStringToList(redisClient *c, char *s, size_t len) { 171 robj *tail; 172 173 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 174 175 if (listLength(c->reply) == 0) { 176 listAddNodeTail(c->reply,createStringObject(s,len)); 177 } else { 178 tail = listNodeValue(listLast(c->reply)); 179 180 /* Append to this object when possible. */ 181 if (tail->ptr != NULL && 182 sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES) 183 { 184 tail = dupLastObjectIfNeeded(c->reply); 185 tail->ptr = sdscatlen(tail->ptr,s,len); 186 } else { 187 listAddNodeTail(c->reply,createStringObject(s,len)); 188 } 189 } 190 } 191 192 /* ----------------------------------------------------------------------------- 193 * Higher level functions to queue data on the client output buffer. 194 * The following functions are the ones that commands implementations will call. 195 * -------------------------------------------------------------------------- */ 196 197 void addReply(redisClient *c, robj *obj) { 198 if (_installWriteEvent(c) != REDIS_OK) return; 199 200 /* This is an important place where we can avoid copy-on-write 201 * when there is a saving child running, avoiding touching the 202 * refcount field of the object if it's not needed. 203 * 204 * If the encoding is RAW and there is room in the static buffer 205 * we'll be able to send the object to the client without 206 * messing with its page. */ 207 if (obj->encoding == REDIS_ENCODING_RAW) { 208 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 209 _addReplyObjectToList(c,obj); 210 } else { 211 /* FIXME: convert the long into string and use _addReplyToBuffer() 212 * instead of calling getDecodedObject. As this place in the 213 * code is too performance critical. */ 214 obj = getDecodedObject(obj); 215 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 216 _addReplyObjectToList(c,obj); 217 decrRefCount(obj); 218 } 219 } 220 221 void addReplySds(redisClient *c, sds s) { 222 if (_installWriteEvent(c) != REDIS_OK) { 223 /* The caller expects the sds to be free'd. */ 224 sdsfree(s); 225 return; 226 } 227 if (_addReplyToBuffer(c,s,sdslen(s)) == REDIS_OK) { 228 sdsfree(s); 229 } else { 230 /* This method free's the sds when it is no longer needed. */ 231 _addReplySdsToList(c,s); 232 } 233 } 234 235 void addReplyString(redisClient *c, char *s, size_t len) { 236 if (_installWriteEvent(c) != REDIS_OK) return; 237 if (_addReplyToBuffer(c,s,len) != REDIS_OK) 238 _addReplyStringToList(c,s,len); 239 } 240 241 void _addReplyError(redisClient *c, char *s, size_t len) { 242 addReplyString(c,"-ERR ",5); 243 addReplyString(c,s,len); 244 addReplyString(c,"\r\n",2); 245 } 246 247 void addReplyError(redisClient *c, char *err) { 248 _addReplyError(c,err,strlen(err)); 249 } 250 251 void addReplyErrorFormat(redisClient *c, const char *fmt, ...) { 252 size_t l, j; 253 va_list ap; 254 va_start(ap,fmt); 255 sds s = sdscatvprintf(sdsempty(),fmt,ap); 256 va_end(ap); 257 /* Make sure there are no newlines in the string, otherwise invalid protocol 258 * is emitted. */ 259 l = sdslen(s); 260 for (j = 0; j < l; j++) { 261 if (s[j] == '\r' || s[j] == '\n') s[j] = ' '; 262 } 263 _addReplyError(c,s,sdslen(s)); 264 sdsfree(s); 265 } 266 267 void _addReplyStatus(redisClient *c, char *s, size_t len) { 268 addReplyString(c,"+",1); 269 addReplyString(c,s,len); 270 addReplyString(c,"\r\n",2); 271 } 272 273 void addReplyStatus(redisClient *c, char *status) { 274 _addReplyStatus(c,status,strlen(status)); 275 } 276 277 void addReplyStatusFormat(redisClient *c, const char *fmt, ...) { 278 va_list ap; 279 va_start(ap,fmt); 280 sds s = sdscatvprintf(sdsempty(),fmt,ap); 281 va_end(ap); 282 _addReplyStatus(c,s,sdslen(s)); 283 sdsfree(s); 284 } 285 286 /* Adds an empty object to the reply list that will contain the multi bulk 287 * length, which is not known when this function is called. */ 288 void *addDeferredMultiBulkLength(redisClient *c) { 289 /* Note that we install the write event here even if the object is not 290 * ready to be sent, since we are sure that before returning to the 291 * event loop setDeferredMultiBulkLength() will be called. */ 292 if (_installWriteEvent(c) != REDIS_OK) return NULL; 293 listAddNodeTail(c->reply,createObject(REDIS_STRING,NULL)); 294 return listLast(c->reply); 295 } 296 297 /* Populate the length object and try glueing it to the next chunk. */ 298 void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { 299 listNode *ln = (listNode*)node; 300 robj *len, *next; 301 302 /* Abort when *node is NULL (see addDeferredMultiBulkLength). */ 303 if (node == NULL) return; 304 305 len = listNodeValue(ln); 306 len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length); 307 if (ln->next != NULL) { 308 next = listNodeValue(ln->next); 309 310 /* Only glue when the next node is non-NULL (an sds in this case) */ 311 if (next->ptr != NULL) { 312 len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr)); 313 listDelNode(c->reply,ln->next); 314 } 315 } 316 } 317 318 /* Add a duble as a bulk reply */ 319 void addReplyDouble(redisClient *c, double d) { 320 char dbuf[128], sbuf[128]; 321 int dlen, slen; 322 dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d); 323 slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf); 324 addReplyString(c,sbuf,slen); 325 } 326 327 /* Add a long long as integer reply or bulk len / multi bulk count. 328 * Basically this is used to output <prefix><long long><crlf>. */ 329 void _addReplyLongLong(redisClient *c, long long ll, char prefix) { 330 char buf[128]; 331 int len; 332 buf[0] = prefix; 333 len = ll2string(buf+1,sizeof(buf)-1,ll); 334 buf[len+1] = '\r'; 335 buf[len+2] = '\n'; 336 addReplyString(c,buf,len+3); 337 } 338 339 void addReplyLongLong(redisClient *c, long long ll) { 340 if (ll == 0) 341 addReply(c,shared.czero); 342 else if (ll == 1) 343 addReply(c,shared.cone); 344 else 345 _addReplyLongLong(c,ll,':'); 346 } 347 348 void addReplyMultiBulkLen(redisClient *c, long length) { 349 _addReplyLongLong(c,length,'*'); 350 } 351 352 /* Create the length prefix of a bulk reply, example: $2234 */ 353 void addReplyBulkLen(redisClient *c, robj *obj) { 354 size_t len; 355 356 if (obj->encoding == REDIS_ENCODING_RAW) { 357 len = sdslen(obj->ptr); 358 } else { 359 long n = (long)obj->ptr; 360 361 /* Compute how many bytes will take this integer as a radix 10 string */ 362 len = 1; 363 if (n < 0) { 364 len++; 365 n = -n; 366 } 367 while((n = n/10) != 0) { 368 len++; 369 } 370 } 371 _addReplyLongLong(c,len,'$'); 372 } 373 374 /* Add a Redis Object as a bulk reply */ 375 void addReplyBulk(redisClient *c, robj *obj) { 376 addReplyBulkLen(c,obj); 377 addReply(c,obj); 378 addReply(c,shared.crlf); 379 } 380 381 /* Add a C buffer as bulk reply */ 382 void addReplyBulkCBuffer(redisClient *c, void *p, size_t len) { 383 _addReplyLongLong(c,len,'$'); 384 addReplyString(c,p,len); 385 addReply(c,shared.crlf); 386 } 387 388 /* Add a C nul term string as bulk reply */ 389 void addReplyBulkCString(redisClient *c, char *s) { 390 if (s == NULL) { 391 addReply(c,shared.nullbulk); 392 } else { 393 addReplyBulkCBuffer(c,s,strlen(s)); 394 } 395 } 396 397 /* Add a long long as a bulk reply */ 398 void addReplyBulkLongLong(redisClient *c, long long ll) { 399 char buf[64]; 400 int len; 401 402 len = ll2string(buf,64,ll); 403 addReplyBulkCBuffer(c,buf,len); 404 } 405 406 /* Copy 'src' client output buffers into 'dst' client output buffers. 407 * The function takes care of freeing the old output buffers of the 408 * destination client. */ 409 void copyClientOutputBuffer(redisClient *dst, redisClient *src) { 410 listRelease(dst->reply); 411 dst->reply = listDup(src->reply); 412 memcpy(dst->buf,src->buf,src->bufpos); 413 dst->bufpos = src->bufpos; 414 } 415 416 static void acceptCommonHandler(int fd) { 417 redisClient *c; 418 if ((c = createClient(fd)) == NULL) { 419 redisLog(REDIS_WARNING,"Error allocating resoures for the client"); 420 close(fd); /* May be already closed, just ingore errors */ 421 return; 422 } 423 /* If maxclient directive is set and this is one client more... close the 424 * connection. Note that we create the client instead to check before 425 * for this condition, since now the socket is already set in nonblocking 426 * mode and we can send an error for free using the Kernel I/O */ 427 if (listLength(server.clients) > server.maxclients) { 428 char *err = "-ERR max number of clients reached\r\n"; 429 430 /* That's a best effort error message, don't check write errors */ 431 if (write(c->fd,err,strlen(err)) == -1) { 432 /* Nothing to do, Just to avoid the warning... */ 433 } 434 server.stat_rejected_conn++; 435 freeClient(c); 436 return; 437 } 438 server.stat_numconnections++; 439 } 440 441 void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 442 int cport, cfd; 443 char cip[128]; 444 REDIS_NOTUSED(el); 445 REDIS_NOTUSED(mask); 446 REDIS_NOTUSED(privdata); 447 448 cfd = anetTcpAccept(server.neterr, fd, cip, &cport); 449 if (cfd == AE_ERR) { 450 redisLog(REDIS_WARNING,"Accepting client connection: %s", server.neterr); 451 return; 452 } 453 redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport); 454 acceptCommonHandler(cfd); 455 } 456 457 void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 458 int cfd; 459 REDIS_NOTUSED(el); 460 REDIS_NOTUSED(mask); 461 REDIS_NOTUSED(privdata); 462 463 cfd = anetUnixAccept(server.neterr, fd); 464 if (cfd == AE_ERR) { 465 redisLog(REDIS_WARNING,"Accepting client connection: %s", server.neterr); 466 return; 467 } 468 redisLog(REDIS_VERBOSE,"Accepted connection to %s", server.unixsocket); 469 acceptCommonHandler(cfd); 470 } 471 472 473 static void freeClientArgv(redisClient *c) { 474 int j; 475 for (j = 0; j < c->argc; j++) 476 decrRefCount(c->argv[j]); 477 c->argc = 0; 478 c->cmd = NULL; 479 } 480 481 void freeClient(redisClient *c) { 482 listNode *ln; 483 484 /* Note that if the client we are freeing is blocked into a blocking 485 * call, we have to set querybuf to NULL *before* to call 486 * unblockClientWaitingData() to avoid processInputBuffer() will get 487 * called. Also it is important to remove the file events after 488 * this, because this call adds the READABLE event. */ 489 sdsfree(c->querybuf); 490 c->querybuf = NULL; 491 if (c->flags & REDIS_BLOCKED) 492 unblockClientWaitingData(c); 493 494 /* UNWATCH all the keys */ 495 unwatchAllKeys(c); 496 listRelease(c->watched_keys); 497 /* Unsubscribe from all the pubsub channels */ 498 pubsubUnsubscribeAllChannels(c,0); 499 pubsubUnsubscribeAllPatterns(c,0); 500 dictRelease(c->pubsub_channels); 501 listRelease(c->pubsub_patterns); 502 /* Obvious cleanup */ 503 aeDeleteFileEvent(server.el,c->fd,AE_READABLE); 504 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 505 listRelease(c->reply); 506 freeClientArgv(c); 507 close(c->fd); 508 /* Remove from the list of clients */ 509 ln = listSearchKey(server.clients,c); 510 redisAssert(ln != NULL); 511 listDelNode(server.clients,ln); 512 /* When client was just unblocked because of a blocking operation, 513 * remove it from the list with unblocked clients. */ 514 if (c->flags & REDIS_UNBLOCKED) { 515 ln = listSearchKey(server.unblocked_clients,c); 516 redisAssert(ln != NULL); 517 listDelNode(server.unblocked_clients,ln); 518 } 519 listRelease(c->io_keys); 520 /* Master/slave cleanup. 521 * Case 1: we lost the connection with a slave. */ 522 if (c->flags & REDIS_SLAVE) { 523 if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1) 524 close(c->repldbfd); 525 list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves; 526 ln = listSearchKey(l,c); 527 redisAssert(ln != NULL); 528 listDelNode(l,ln); 529 } 530 531 /* Case 2: we lost the connection with the master. */ 532 if (c->flags & REDIS_MASTER) { 533 server.master = NULL; 534 server.repl_state = REDIS_REPL_CONNECT; 535 server.repl_down_since = time(NULL); 536 /* Since we lost the connection with the master, we should also 537 * close the connection with all our slaves if we have any, so 538 * when we'll resync with the master the other slaves will sync again 539 * with us as well. Note that also when the slave is not connected 540 * to the master it will keep refusing connections by other slaves. 541 * 542 * We do this only if server.masterhost != NULL. If it is NULL this 543 * means the user called SLAVEOF NO ONE and we are freeing our 544 * link with the master, so no need to close link with slaves. */ 545 if (server.masterhost != NULL) { 546 while (listLength(server.slaves)) { 547 ln = listFirst(server.slaves); 548 freeClient((redisClient*)ln->value); 549 } 550 } 551 } 552 /* Release memory */ 553 zfree(c->argv); 554 freeClientMultiState(c); 555 zfree(c); 556 } 557 558 void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) { 559 redisClient *c = privdata; 560 int nwritten = 0, totwritten = 0, objlen; 561 robj *o; 562 REDIS_NOTUSED(el); 563 REDIS_NOTUSED(mask); 564 565 while(c->bufpos > 0 || listLength(c->reply)) { 566 if (c->bufpos > 0) { 567 if (c->flags & REDIS_MASTER) { 568 /* Don't reply to a master */ 569 nwritten = c->bufpos - c->sentlen; 570 } else { 571 nwritten = write(fd,c->buf+c->sentlen,c->bufpos-c->sentlen); 572 if (nwritten <= 0) break; 573 } 574 c->sentlen += nwritten; 575 totwritten += nwritten; 576 577 /* If the buffer was sent, set bufpos to zero to continue with 578 * the remainder of the reply. */ 579 if (c->sentlen == c->bufpos) { 580 c->bufpos = 0; 581 c->sentlen = 0; 582 } 583 } else { 584 o = listNodeValue(listFirst(c->reply)); 585 objlen = sdslen(o->ptr); 586 587 if (objlen == 0) { 588 listDelNode(c->reply,listFirst(c->reply)); 589 continue; 590 } 591 592 if (c->flags & REDIS_MASTER) { 593 /* Don't reply to a master */ 594 nwritten = objlen - c->sentlen; 595 } else { 596 nwritten = write(fd, ((char*)o->ptr)+c->sentlen,objlen-c->sentlen); 597 if (nwritten <= 0) break; 598 } 599 c->sentlen += nwritten; 600 totwritten += nwritten; 601 602 /* If we fully sent the object on head go to the next one */ 603 if (c->sentlen == objlen) { 604 listDelNode(c->reply,listFirst(c->reply)); 605 c->sentlen = 0; 606 } 607 } 608 /* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT 609 * bytes, in a single threaded server it's a good idea to serve 610 * other clients as well, even if a very large request comes from 611 * super fast link that is always able to accept data (in real world 612 * scenario think about 'KEYS *' against the loopback interfae) */ 613 if (totwritten > REDIS_MAX_WRITE_PER_EVENT) break; 614 } 615 if (nwritten == -1) { 616 if (errno == EAGAIN) { 617 nwritten = 0; 618 } else { 619 redisLog(REDIS_VERBOSE, 620 "Error writing to client: %s", strerror(errno)); 621 freeClient(c); 622 return; 623 } 624 } 625 if (totwritten > 0) c->lastinteraction = time(NULL); 626 if (c->bufpos == 0 && listLength(c->reply) == 0) { 627 c->sentlen = 0; 628 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 629 630 /* Close connection after entire reply has been sent. */ 631 if (c->flags & REDIS_CLOSE_AFTER_REPLY) freeClient(c); 632 } 633 } 634 635 /* resetClient prepare the client to process the next command */ 636 void resetClient(redisClient *c) { 637 freeClientArgv(c); 638 c->reqtype = 0; 639 c->multibulklen = 0; 640 c->bulklen = -1; 641 /* We clear the ASKING flag as well if we are not inside a MULTI. */ 642 if (!(c->flags & REDIS_MULTI)) c->flags &= (~REDIS_ASKING); 643 } 644 645 void closeTimedoutClients(void) { 646 redisClient *c; 647 listNode *ln; 648 time_t now = time(NULL); 649 listIter li; 650 651 listRewind(server.clients,&li); 652 while ((ln = listNext(&li)) != NULL) { 653 c = listNodeValue(ln); 654 if (server.maxidletime && 655 !(c->flags & REDIS_SLAVE) && /* no timeout for slaves */ 656 !(c->flags & REDIS_MASTER) && /* no timeout for masters */ 657 !(c->flags & REDIS_BLOCKED) && /* no timeout for BLPOP */ 658 dictSize(c->pubsub_channels) == 0 && /* no timeout for pubsub */ 659 listLength(c->pubsub_patterns) == 0 && 660 (now - c->lastinteraction > server.maxidletime)) 661 { 662 redisLog(REDIS_VERBOSE,"Closing idle client"); 663 freeClient(c); 664 } else if (c->flags & REDIS_BLOCKED) { 665 if (c->bpop.timeout != 0 && c->bpop.timeout < now) { 666 addReply(c,shared.nullmultibulk); 667 unblockClientWaitingData(c); 668 } 669 } 670 } 671 } 672 673 int processInlineBuffer(redisClient *c) { 674 char *newline = strstr(c->querybuf,"\r\n"); 675 int argc, j; 676 sds *argv; 677 size_t querylen; 678 679 /* Nothing to do without a \r\n */ 680 if (newline == NULL) { 681 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 682 addReplyError(c,"Protocol error: too big inline request"); 683 setProtocolError(c,0); 684 } 685 return REDIS_ERR; 686 } 687 688 /* Split the input buffer up to the \r\n */ 689 querylen = newline-(c->querybuf); 690 argv = sdssplitlen(c->querybuf,querylen," ",1,&argc); 691 692 /* Leave data after the first line of the query in the buffer */ 693 c->querybuf = sdsrange(c->querybuf,querylen+2,-1); 694 695 /* Setup argv array on client structure */ 696 if (c->argv) zfree(c->argv); 697 c->argv = zmalloc(sizeof(robj*)*argc); 698 699 /* Create redis objects for all arguments. */ 700 for (c->argc = 0, j = 0; j < argc; j++) { 701 if (sdslen(argv[j])) { 702 c->argv[c->argc] = createObject(REDIS_STRING,argv[j]); 703 c->argc++; 704 } else { 705 sdsfree(argv[j]); 706 } 707 } 708 zfree(argv); 709 return REDIS_OK; 710 } 711 712 /* Helper function. Trims query buffer to make the function that processes 713 * multi bulk requests idempotent. */ 714 static void setProtocolError(redisClient *c, int pos) { 715 if (server.verbosity >= REDIS_VERBOSE) { 716 sds client = getClientInfoString(c); 717 redisLog(REDIS_VERBOSE, 718 "Protocol error from client: %s", client); 719 sdsfree(client); 720 } 721 c->flags |= REDIS_CLOSE_AFTER_REPLY; 722 c->querybuf = sdsrange(c->querybuf,pos,-1); 723 } 724 725 int processMultibulkBuffer(redisClient *c) { 726 char *newline = NULL; 727 int pos = 0, ok; 728 long long ll; 729 730 if (c->multibulklen == 0) { 731 /* The client should have been reset */ 732 redisAssertWithInfo(c,NULL,c->argc == 0); 733 734 /* Multi bulk length cannot be read without a \r\n */ 735 newline = strchr(c->querybuf,'\r'); 736 if (newline == NULL) { 737 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 738 addReplyError(c,"Protocol error: too big mbulk count string"); 739 setProtocolError(c,0); 740 } 741 return REDIS_ERR; 742 } 743 744 /* Buffer should also contain \n */ 745 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 746 return REDIS_ERR; 747 748 /* We know for sure there is a whole line since newline != NULL, 749 * so go ahead and find out the multi bulk length. */ 750 redisAssertWithInfo(c,NULL,c->querybuf[0] == '*'); 751 ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll); 752 if (!ok || ll > 1024*1024) { 753 addReplyError(c,"Protocol error: invalid multibulk length"); 754 setProtocolError(c,pos); 755 return REDIS_ERR; 756 } 757 758 pos = (newline-c->querybuf)+2; 759 if (ll <= 0) { 760 c->querybuf = sdsrange(c->querybuf,pos,-1); 761 return REDIS_OK; 762 } 763 764 c->multibulklen = ll; 765 766 /* Setup argv array on client structure */ 767 if (c->argv) zfree(c->argv); 768 c->argv = zmalloc(sizeof(robj*)*c->multibulklen); 769 } 770 771 redisAssertWithInfo(c,NULL,c->multibulklen > 0); 772 while(c->multibulklen) { 773 /* Read bulk length if unknown */ 774 if (c->bulklen == -1) { 775 newline = strchr(c->querybuf+pos,'\r'); 776 if (newline == NULL) { 777 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 778 addReplyError(c,"Protocol error: too big bulk count string"); 779 setProtocolError(c,0); 780 } 781 break; 782 } 783 784 /* Buffer should also contain \n */ 785 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 786 break; 787 788 if (c->querybuf[pos] != '$') { 789 addReplyErrorFormat(c, 790 "Protocol error: expected '$', got '%c'", 791 c->querybuf[pos]); 792 setProtocolError(c,pos); 793 return REDIS_ERR; 794 } 795 796 ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll); 797 if (!ok || ll < 0 || ll > 512*1024*1024) { 798 addReplyError(c,"Protocol error: invalid bulk length"); 799 setProtocolError(c,pos); 800 return REDIS_ERR; 801 } 802 803 pos += newline-(c->querybuf+pos)+2; 804 if (ll >= REDIS_MBULK_BIG_ARG) { 805 /* If we are going to read a large object from network 806 * try to make it likely that it will start at c->querybuf 807 * boundary so that we can optimized object creation 808 * avoiding a large copy of data. */ 809 c->querybuf = sdsrange(c->querybuf,pos,-1); 810 pos = 0; 811 /* Hint the sds library about the amount of bytes this string is 812 * going to contain. */ 813 c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2); 814 } 815 c->bulklen = ll; 816 } 817 818 /* Read bulk argument */ 819 if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) { 820 /* Not enough data (+2 == trailing \r\n) */ 821 break; 822 } else { 823 /* Optimization: if the buffer contanins JUST our bulk element 824 * instead of creating a new object by *copying* the sds we 825 * just use the current sds string. */ 826 if (pos == 0 && 827 c->bulklen >= REDIS_MBULK_BIG_ARG && 828 (signed) sdslen(c->querybuf) == c->bulklen+2) 829 { 830 c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf); 831 sdsIncrLen(c->querybuf,-2); /* remove CRLF */ 832 c->querybuf = sdsempty(); 833 /* Assume that if we saw a fat argument we'll see another one 834 * likely... */ 835 c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2); 836 pos = 0; 837 } else { 838 c->argv[c->argc++] = 839 createStringObject(c->querybuf+pos,c->bulklen); 840 pos += c->bulklen+2; 841 } 842 c->bulklen = -1; 843 c->multibulklen--; 844 } 845 } 846 847 /* Trim to pos */ 848 if (pos) c->querybuf = sdsrange(c->querybuf,pos,-1); 849 850 /* We're done when c->multibulk == 0 */ 851 if (c->multibulklen == 0) return REDIS_OK; 852 853 /* Still not read to process the command */ 854 return REDIS_ERR; 855 } 856 857 void processInputBuffer(redisClient *c) { 858 /* Keep processing while there is something in the input buffer */ 859 while(sdslen(c->querybuf)) { 860 /* Immediately abort if the client is in the middle of something. */ 861 if (c->flags & REDIS_BLOCKED) return; 862 863 /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is 864 * written to the client. Make sure to not let the reply grow after 865 * this flag has been set (i.e. don't process more commands). */ 866 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 867 868 /* Determine request type when unknown. */ 869 if (!c->reqtype) { 870 if (c->querybuf[0] == '*') { 871 c->reqtype = REDIS_REQ_MULTIBULK; 872 } else { 873 c->reqtype = REDIS_REQ_INLINE; 874 } 875 } 876 877 if (c->reqtype == REDIS_REQ_INLINE) { 878 if (processInlineBuffer(c) != REDIS_OK) break; 879 } else if (c->reqtype == REDIS_REQ_MULTIBULK) { 880 if (processMultibulkBuffer(c) != REDIS_OK) break; 881 } else { 882 redisPanic("Unknown request type"); 883 } 884 885 /* Multibulk processing could see a <= 0 length. */ 886 if (c->argc == 0) { 887 resetClient(c); 888 } else { 889 /* Only reset the client when the command was executed. */ 890 if (processCommand(c) == REDIS_OK) 891 resetClient(c); 892 } 893 } 894 } 895 896 void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { 897 redisClient *c = (redisClient*) privdata; 898 int nread, readlen; 899 size_t qblen; 900 REDIS_NOTUSED(el); 901 REDIS_NOTUSED(mask); 902 903 readlen = REDIS_IOBUF_LEN; 904 /* If this is a multi bulk request, and we are processing a bulk reply 905 * that is large enough, try to maximize the probabilty that the query 906 * buffer contains excatly the SDS string representing the object, even 907 * at the risk of requring more read(2) calls. This way the function 908 * processMultiBulkBuffer() can avoid copying buffers to create the 909 * Redis Object representing the argument. */ 910 if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1 911 && c->bulklen >= REDIS_MBULK_BIG_ARG) 912 { 913 int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf); 914 915 if (remaining < readlen) readlen = remaining; 916 } 917 918 qblen = sdslen(c->querybuf); 919 c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); 920 nread = read(fd, c->querybuf+qblen, readlen); 921 if (nread == -1) { 922 if (errno == EAGAIN) { 923 nread = 0; 924 } else { 925 redisLog(REDIS_VERBOSE, "Reading from client: %s",strerror(errno)); 926 freeClient(c); 927 return; 928 } 929 } else if (nread == 0) { 930 redisLog(REDIS_VERBOSE, "Client closed connection"); 931 freeClient(c); 932 return; 933 } 934 if (nread) { 935 sdsIncrLen(c->querybuf,nread); 936 c->lastinteraction = time(NULL); 937 } else { 938 return; 939 } 940 if (sdslen(c->querybuf) > server.client_max_querybuf_len) { 941 sds ci = getClientInfoString(c), bytes = sdsempty(); 942 943 bytes = sdscatrepr(bytes,c->querybuf,64); 944 redisLog(REDIS_WARNING,"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)", ci, bytes); 945 sdsfree(ci); 946 sdsfree(bytes); 947 freeClient(c); 948 return; 949 } 950 processInputBuffer(c); 951 } 952 953 void getClientsMaxBuffers(unsigned long *longest_output_list, 954 unsigned long *biggest_input_buffer) { 955 redisClient *c; 956 listNode *ln; 957 listIter li; 958 unsigned long lol = 0, bib = 0; 959 960 listRewind(server.clients,&li); 961 while ((ln = listNext(&li)) != NULL) { 962 c = listNodeValue(ln); 963 964 if (listLength(c->reply) > lol) lol = listLength(c->reply); 965 if (sdslen(c->querybuf) > bib) bib = sdslen(c->querybuf); 966 } 967 *longest_output_list = lol; 968 *biggest_input_buffer = bib; 969 } 970 971 /* Turn a Redis client into an sds string representing its state. */ 972 sds getClientInfoString(redisClient *client) { 973 char ip[32], flags[16], events[3], *p; 974 int port; 975 time_t now = time(NULL); 976 int emask; 977 978 if (anetPeerToString(client->fd,ip,&port) == -1) { 979 ip[0] = '?'; 980 ip[1] = '\0'; 981 port = 0; 982 } 983 p = flags; 984 if (client->flags & REDIS_SLAVE) { 985 if (client->flags & REDIS_MONITOR) 986 *p++ = 'O'; 987 else 988 *p++ = 'S'; 989 } 990 if (client->flags & REDIS_MASTER) *p++ = 'M'; 991 if (client->flags & REDIS_MULTI) *p++ = 'x'; 992 if (client->flags & REDIS_BLOCKED) *p++ = 'b'; 993 if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; 994 if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; 995 if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; 996 if (p == flags) *p++ = 'N'; 997 *p++ = '\0'; 998 999 emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd); 1000 p = events; 1001 if (emask & AE_READABLE) *p++ = 'r'; 1002 if (emask & AE_WRITABLE) *p++ = 'w'; 1003 *p = '\0'; 1004 return sdscatprintf(sdsempty(), 1005 "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d qbuf=%lu obl=%lu oll=%lu events=%s cmd=%s", 1006 ip,port,client->fd, 1007 (long)(now - client->lastinteraction), 1008 flags, 1009 client->db->id, 1010 (int) dictSize(client->pubsub_channels), 1011 (int) listLength(client->pubsub_patterns), 1012 (unsigned long) sdslen(client->querybuf), 1013 (unsigned long) client->bufpos, 1014 (unsigned long) listLength(client->reply), 1015 events, 1016 client->lastcmd ? client->lastcmd->name : "NULL"); 1017 } 1018 1019 sds getAllClientsInfoString(void) { 1020 listNode *ln; 1021 listIter li; 1022 redisClient *client; 1023 sds o = sdsempty(); 1024 1025 listRewind(server.clients,&li); 1026 while ((ln = listNext(&li)) != NULL) { 1027 sds cs; 1028 1029 client = listNodeValue(ln); 1030 cs = getClientInfoString(client); 1031 o = sdscatsds(o,cs); 1032 sdsfree(cs); 1033 o = sdscatlen(o,"\n",1); 1034 } 1035 return o; 1036 } 1037 1038 void clientCommand(redisClient *c) { 1039 listNode *ln; 1040 listIter li; 1041 redisClient *client; 1042 1043 if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { 1044 sds o = getAllClientsInfoString(); 1045 addReplyBulkCBuffer(c,o,sdslen(o)); 1046 sdsfree(o); 1047 } else if (!strcasecmp(c->argv[1]->ptr,"kill") && c->argc == 3) { 1048 listRewind(server.clients,&li); 1049 while ((ln = listNext(&li)) != NULL) { 1050 char ip[32], addr[64]; 1051 int port; 1052 1053 client = listNodeValue(ln); 1054 if (anetPeerToString(client->fd,ip,&port) == -1) continue; 1055 snprintf(addr,sizeof(addr),"%s:%d",ip,port); 1056 if (strcmp(addr,c->argv[2]->ptr) == 0) { 1057 addReply(c,shared.ok); 1058 if (c == client) { 1059 client->flags |= REDIS_CLOSE_AFTER_REPLY; 1060 } else { 1061 freeClient(client); 1062 } 1063 return; 1064 } 1065 } 1066 addReplyError(c,"No such client"); 1067 } else { 1068 addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port)"); 1069 } 1070 } 1071 1072 /* Rewrite the command vector of the client. All the new objects ref count 1073 * is incremented. The old command vector is freed, and the old objects 1074 * ref count is decremented. */ 1075 void rewriteClientCommandVector(redisClient *c, int argc, ...) { 1076 va_list ap; 1077 int j; 1078 robj **argv; /* The new argument vector */ 1079 1080 argv = zmalloc(sizeof(robj*)*argc); 1081 va_start(ap,argc); 1082 for (j = 0; j < argc; j++) { 1083 robj *a; 1084 1085 a = va_arg(ap, robj*); 1086 argv[j] = a; 1087 incrRefCount(a); 1088 } 1089 /* We free the objects in the original vector at the end, so we are 1090 * sure that if the same objects are reused in the new vector the 1091 * refcount gets incremented before it gets decremented. */ 1092 for (j = 0; j < c->argc; j++) decrRefCount(c->argv[j]); 1093 zfree(c->argv); 1094 /* Replace argv and argc with our new versions. */ 1095 c->argv = argv; 1096 c->argc = argc; 1097 c->cmd = lookupCommand(c->argv[0]->ptr); 1098 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1099 va_end(ap); 1100 } 1101 1102 /* Rewrite a single item in the command vector. 1103 * The new val ref count is incremented, and the old decremented. */ 1104 void rewriteClientCommandArgument(redisClient *c, int i, robj *newval) { 1105 robj *oldval; 1106 1107 redisAssertWithInfo(c,NULL,i < c->argc); 1108 oldval = c->argv[i]; 1109 c->argv[i] = newval; 1110 incrRefCount(newval); 1111 decrRefCount(oldval); 1112 1113 /* If this is the command name make sure to fix c->cmd. */ 1114 if (i == 0) { 1115 c->cmd = lookupCommand(c->argv[0]->ptr); 1116 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1117 } 1118 } 1119