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