1 /* 2 * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * * Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * * Neither the name of Redis nor the names of its contributors may be used 14 * to endorse or promote products derived from this software without 15 * specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "redis.h" 31 #include <sys/uio.h> 32 33 static void setProtocolError(redisClient *c, int pos); 34 35 /* To evaluate the output buffer size of a client we need to get size of 36 * allocated objects, however we can't used zmalloc_size() directly on sds 37 * strings because of the trick they use to work (the header is before the 38 * returned pointer), so we use this helper function. */ 39 size_t zmalloc_size_sds(sds s) { 40 return zmalloc_size(s-sizeof(struct sdshdr)); 41 } 42 43 void *dupClientReplyValue(void *o) { 44 incrRefCount((robj*)o); 45 return o; 46 } 47 48 int listMatchObjects(void *a, void *b) { 49 return equalStringObjects(a,b); 50 } 51 52 redisClient *createClient(int fd) { 53 redisClient *c = zmalloc(sizeof(redisClient)); 54 55 /* passing -1 as fd it is possible to create a non connected client. 56 * This is useful since all the Redis commands needs to be executed 57 * in the context of a client. When commands are executed in other 58 * contexts (for instance a Lua script) we need a non connected client. */ 59 if (fd != -1) { 60 anetNonBlock(NULL,fd); 61 anetEnableTcpNoDelay(NULL,fd); 62 if (server.tcpkeepalive) 63 anetKeepAlive(NULL,fd,server.tcpkeepalive); 64 if (aeCreateFileEvent(server.el,fd,AE_READABLE, 65 readQueryFromClient, c) == AE_ERR) 66 { 67 close(fd); 68 zfree(c); 69 return NULL; 70 } 71 } 72 73 selectDb(c,0); 74 c->fd = fd; 75 c->name = NULL; 76 c->bufpos = 0; 77 c->querybuf = sdsempty(); 78 c->querybuf_peak = 0; 79 c->reqtype = 0; 80 c->argc = 0; 81 c->argv = NULL; 82 c->cmd = c->lastcmd = NULL; 83 c->multibulklen = 0; 84 c->bulklen = -1; 85 c->sentlen = 0; 86 c->flags = 0; 87 c->ctime = c->lastinteraction = server.unixtime; 88 c->authenticated = 0; 89 c->replstate = REDIS_REPL_NONE; 90 c->reploff = 0; 91 c->slave_listening_port = 0; 92 c->reply = listCreate(); 93 c->reply_bytes = 0; 94 c->obuf_soft_limit_reached_time = 0; 95 listSetFreeMethod(c->reply,decrRefCountVoid); 96 listSetDupMethod(c->reply,dupClientReplyValue); 97 c->bpop.keys = dictCreate(&setDictType,NULL); 98 c->bpop.timeout = 0; 99 c->bpop.target = NULL; 100 c->io_keys = listCreate(); 101 c->watched_keys = listCreate(); 102 listSetFreeMethod(c->io_keys,decrRefCountVoid); 103 c->pubsub_channels = dictCreate(&setDictType,NULL); 104 c->pubsub_patterns = listCreate(); 105 listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid); 106 listSetMatchMethod(c->pubsub_patterns,listMatchObjects); 107 if (fd != -1) listAddNodeTail(server.clients,c); 108 initClientMultiState(c); 109 return c; 110 } 111 112 /* This function is called every time we are going to transmit new data 113 * to the client. The behavior is the following: 114 * 115 * If the client should receive new data (normal clients will) the function 116 * returns REDIS_OK, and make sure to install the write handler in our event 117 * loop so that when the socket is writable new data gets written. 118 * 119 * If the client should not receive new data, because it is a fake client 120 * or a slave, or because the setup of the write handler failed, the function 121 * returns REDIS_ERR. 122 * 123 * Typically gets called every time a reply is built, before adding more 124 * data to the clients output buffers. If the function returns REDIS_ERR no 125 * data should be appended to the output buffers. */ 126 int prepareClientToWrite(redisClient *c) { 127 if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK; 128 if (c->fd <= 0) return REDIS_ERR; /* Fake client */ 129 if (c->bufpos == 0 && listLength(c->reply) == 0 && 130 (c->replstate == REDIS_REPL_NONE || 131 c->replstate == REDIS_REPL_ONLINE) && 132 aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, 133 sendReplyToClient, c) == AE_ERR) return REDIS_ERR; 134 return REDIS_OK; 135 } 136 137 /* Create a duplicate of the last object in the reply list when 138 * it is not exclusively owned by the reply list. */ 139 robj *dupLastObjectIfNeeded(list *reply) { 140 robj *new, *cur; 141 listNode *ln; 142 redisAssert(listLength(reply) > 0); 143 ln = listLast(reply); 144 cur = listNodeValue(ln); 145 if (cur->refcount > 1) { 146 new = dupStringObject(cur); 147 decrRefCount(cur); 148 listNodeValue(ln) = new; 149 } 150 return listNodeValue(ln); 151 } 152 153 /* ----------------------------------------------------------------------------- 154 * Low level functions to add more data to output buffers. 155 * -------------------------------------------------------------------------- */ 156 157 int _addReplyToBuffer(redisClient *c, char *s, size_t len) { 158 size_t available = sizeof(c->buf)-c->bufpos; 159 160 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return REDIS_OK; 161 162 /* If there already are entries in the reply list, we cannot 163 * add anything more to the static buffer. */ 164 if (listLength(c->reply) > 0) return REDIS_ERR; 165 166 /* Check that the buffer has enough space available for this string. */ 167 if (len > available) return REDIS_ERR; 168 169 memcpy(c->buf+c->bufpos,s,len); 170 c->bufpos+=len; 171 return REDIS_OK; 172 } 173 174 void _addReplyObjectToList(redisClient *c, robj *o) { 175 robj *tail; 176 177 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 178 179 if (listLength(c->reply) == 0) { 180 incrRefCount(o); 181 listAddNodeTail(c->reply,o); 182 c->reply_bytes += zmalloc_size_sds(o->ptr); 183 } else { 184 tail = listNodeValue(listLast(c->reply)); 185 186 /* Append to this object when possible. */ 187 if (tail->ptr != NULL && 188 sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES) 189 { 190 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 191 tail = dupLastObjectIfNeeded(c->reply); 192 tail->ptr = sdscatlen(tail->ptr,o->ptr,sdslen(o->ptr)); 193 c->reply_bytes += zmalloc_size_sds(tail->ptr); 194 } else { 195 incrRefCount(o); 196 listAddNodeTail(c->reply,o); 197 c->reply_bytes += zmalloc_size_sds(o->ptr); 198 } 199 } 200 asyncCloseClientOnOutputBufferLimitReached(c); 201 } 202 203 /* This method takes responsibility over the sds. When it is no longer 204 * needed it will be free'd, otherwise it ends up in a robj. */ 205 void _addReplySdsToList(redisClient *c, sds s) { 206 robj *tail; 207 208 if (c->flags & REDIS_CLOSE_AFTER_REPLY) { 209 sdsfree(s); 210 return; 211 } 212 213 if (listLength(c->reply) == 0) { 214 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 215 c->reply_bytes += zmalloc_size_sds(s); 216 } else { 217 tail = listNodeValue(listLast(c->reply)); 218 219 /* Append to this object when possible. */ 220 if (tail->ptr != NULL && 221 sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES) 222 { 223 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 224 tail = dupLastObjectIfNeeded(c->reply); 225 tail->ptr = sdscatlen(tail->ptr,s,sdslen(s)); 226 c->reply_bytes += zmalloc_size_sds(tail->ptr); 227 sdsfree(s); 228 } else { 229 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 230 c->reply_bytes += zmalloc_size_sds(s); 231 } 232 } 233 asyncCloseClientOnOutputBufferLimitReached(c); 234 } 235 236 void _addReplyStringToList(redisClient *c, char *s, size_t len) { 237 robj *tail; 238 239 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 240 241 if (listLength(c->reply) == 0) { 242 robj *o = createStringObject(s,len); 243 244 listAddNodeTail(c->reply,o); 245 c->reply_bytes += zmalloc_size_sds(o->ptr); 246 } else { 247 tail = listNodeValue(listLast(c->reply)); 248 249 /* Append to this object when possible. */ 250 if (tail->ptr != NULL && 251 sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES) 252 { 253 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 254 tail = dupLastObjectIfNeeded(c->reply); 255 tail->ptr = sdscatlen(tail->ptr,s,len); 256 c->reply_bytes += zmalloc_size_sds(tail->ptr); 257 } else { 258 robj *o = createStringObject(s,len); 259 260 listAddNodeTail(c->reply,o); 261 c->reply_bytes += zmalloc_size_sds(o->ptr); 262 } 263 } 264 asyncCloseClientOnOutputBufferLimitReached(c); 265 } 266 267 /* ----------------------------------------------------------------------------- 268 * Higher level functions to queue data on the client output buffer. 269 * The following functions are the ones that commands implementations will call. 270 * -------------------------------------------------------------------------- */ 271 272 void addReply(redisClient *c, robj *obj) { 273 if (prepareClientToWrite(c) != REDIS_OK) return; 274 275 /* This is an important place where we can avoid copy-on-write 276 * when there is a saving child running, avoiding touching the 277 * refcount field of the object if it's not needed. 278 * 279 * If the encoding is RAW and there is room in the static buffer 280 * we'll be able to send the object to the client without 281 * messing with its page. */ 282 if (obj->encoding == REDIS_ENCODING_RAW) { 283 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 284 _addReplyObjectToList(c,obj); 285 } else if (obj->encoding == REDIS_ENCODING_INT) { 286 /* Optimization: if there is room in the static buffer for 32 bytes 287 * (more than the max chars a 64 bit integer can take as string) we 288 * avoid decoding the object and go for the lower level approach. */ 289 if (listLength(c->reply) == 0 && (sizeof(c->buf) - c->bufpos) >= 32) { 290 char buf[32]; 291 int len; 292 293 len = ll2string(buf,sizeof(buf),(long)obj->ptr); 294 if (_addReplyToBuffer(c,buf,len) == REDIS_OK) 295 return; 296 /* else... continue with the normal code path, but should never 297 * happen actually since we verified there is room. */ 298 } 299 obj = getDecodedObject(obj); 300 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 301 _addReplyObjectToList(c,obj); 302 decrRefCount(obj); 303 } else { 304 redisPanic("Wrong obj->encoding in addReply()"); 305 } 306 } 307 308 void addReplySds(redisClient *c, sds s) { 309 if (prepareClientToWrite(c) != REDIS_OK) { 310 /* The caller expects the sds to be free'd. */ 311 sdsfree(s); 312 return; 313 } 314 if (_addReplyToBuffer(c,s,sdslen(s)) == REDIS_OK) { 315 sdsfree(s); 316 } else { 317 /* This method free's the sds when it is no longer needed. */ 318 _addReplySdsToList(c,s); 319 } 320 } 321 322 void addReplyString(redisClient *c, char *s, size_t len) { 323 if (prepareClientToWrite(c) != REDIS_OK) return; 324 if (_addReplyToBuffer(c,s,len) != REDIS_OK) 325 _addReplyStringToList(c,s,len); 326 } 327 328 void addReplyErrorLength(redisClient *c, char *s, size_t len) { 329 addReplyString(c,"-ERR ",5); 330 addReplyString(c,s,len); 331 addReplyString(c,"\r\n",2); 332 } 333 334 void addReplyError(redisClient *c, char *err) { 335 addReplyErrorLength(c,err,strlen(err)); 336 } 337 338 void addReplyErrorFormat(redisClient *c, const char *fmt, ...) { 339 size_t l, j; 340 va_list ap; 341 va_start(ap,fmt); 342 sds s = sdscatvprintf(sdsempty(),fmt,ap); 343 va_end(ap); 344 /* Make sure there are no newlines in the string, otherwise invalid protocol 345 * is emitted. */ 346 l = sdslen(s); 347 for (j = 0; j < l; j++) { 348 if (s[j] == '\r' || s[j] == '\n') s[j] = ' '; 349 } 350 addReplyErrorLength(c,s,sdslen(s)); 351 sdsfree(s); 352 } 353 354 void addReplyStatusLength(redisClient *c, char *s, size_t len) { 355 addReplyString(c,"+",1); 356 addReplyString(c,s,len); 357 addReplyString(c,"\r\n",2); 358 } 359 360 void addReplyStatus(redisClient *c, char *status) { 361 addReplyStatusLength(c,status,strlen(status)); 362 } 363 364 void addReplyStatusFormat(redisClient *c, const char *fmt, ...) { 365 va_list ap; 366 va_start(ap,fmt); 367 sds s = sdscatvprintf(sdsempty(),fmt,ap); 368 va_end(ap); 369 addReplyStatusLength(c,s,sdslen(s)); 370 sdsfree(s); 371 } 372 373 /* Adds an empty object to the reply list that will contain the multi bulk 374 * length, which is not known when this function is called. */ 375 void *addDeferredMultiBulkLength(redisClient *c) { 376 /* Note that we install the write event here even if the object is not 377 * ready to be sent, since we are sure that before returning to the 378 * event loop setDeferredMultiBulkLength() will be called. */ 379 if (prepareClientToWrite(c) != REDIS_OK) return NULL; 380 listAddNodeTail(c->reply,createObject(REDIS_STRING,NULL)); 381 return listLast(c->reply); 382 } 383 384 /* Populate the length object and try gluing it to the next chunk. */ 385 void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { 386 listNode *ln = (listNode*)node; 387 robj *len, *next; 388 389 /* Abort when *node is NULL (see addDeferredMultiBulkLength). */ 390 if (node == NULL) return; 391 392 len = listNodeValue(ln); 393 len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length); 394 c->reply_bytes += zmalloc_size_sds(len->ptr); 395 if (ln->next != NULL) { 396 next = listNodeValue(ln->next); 397 398 /* Only glue when the next node is non-NULL (an sds in this case) */ 399 if (next->ptr != NULL) { 400 c->reply_bytes -= zmalloc_size_sds(len->ptr); 401 c->reply_bytes -= zmalloc_size_sds(next->ptr); 402 len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr)); 403 c->reply_bytes += zmalloc_size_sds(len->ptr); 404 listDelNode(c->reply,ln->next); 405 } 406 } 407 asyncCloseClientOnOutputBufferLimitReached(c); 408 } 409 410 /* Add a double as a bulk reply */ 411 void addReplyDouble(redisClient *c, double d) { 412 char dbuf[128], sbuf[128]; 413 int dlen, slen; 414 dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d); 415 slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf); 416 addReplyString(c,sbuf,slen); 417 } 418 419 /* Add a long long as integer reply or bulk len / multi bulk count. 420 * Basically this is used to output <prefix><long long><crlf>. */ 421 void addReplyLongLongWithPrefix(redisClient *c, long long ll, char prefix) { 422 char buf[128]; 423 int len; 424 425 /* Things like $3\r\n or *2\r\n are emitted very often by the protocol 426 * so we have a few shared objects to use if the integer is small 427 * like it is most of the times. */ 428 if (prefix == '*' && ll < REDIS_SHARED_BULKHDR_LEN) { 429 addReply(c,shared.mbulkhdr[ll]); 430 return; 431 } else if (prefix == '$' && ll < REDIS_SHARED_BULKHDR_LEN) { 432 addReply(c,shared.bulkhdr[ll]); 433 return; 434 } 435 436 buf[0] = prefix; 437 len = ll2string(buf+1,sizeof(buf)-1,ll); 438 buf[len+1] = '\r'; 439 buf[len+2] = '\n'; 440 addReplyString(c,buf,len+3); 441 } 442 443 void addReplyLongLong(redisClient *c, long long ll) { 444 if (ll == 0) 445 addReply(c,shared.czero); 446 else if (ll == 1) 447 addReply(c,shared.cone); 448 else 449 addReplyLongLongWithPrefix(c,ll,':'); 450 } 451 452 void addReplyMultiBulkLen(redisClient *c, long length) { 453 addReplyLongLongWithPrefix(c,length,'*'); 454 } 455 456 /* Create the length prefix of a bulk reply, example: $2234 */ 457 void addReplyBulkLen(redisClient *c, robj *obj) { 458 size_t len; 459 460 if (obj->encoding == REDIS_ENCODING_RAW) { 461 len = sdslen(obj->ptr); 462 } else { 463 long n = (long)obj->ptr; 464 465 /* Compute how many bytes will take this integer as a radix 10 string */ 466 len = 1; 467 if (n < 0) { 468 len++; 469 n = -n; 470 } 471 while((n = n/10) != 0) { 472 len++; 473 } 474 } 475 addReplyLongLongWithPrefix(c,len,'$'); 476 } 477 478 /* Add a Redis Object as a bulk reply */ 479 void addReplyBulk(redisClient *c, robj *obj) { 480 addReplyBulkLen(c,obj); 481 addReply(c,obj); 482 addReply(c,shared.crlf); 483 } 484 485 /* Add a C buffer as bulk reply */ 486 void addReplyBulkCBuffer(redisClient *c, void *p, size_t len) { 487 addReplyLongLongWithPrefix(c,len,'$'); 488 addReplyString(c,p,len); 489 addReply(c,shared.crlf); 490 } 491 492 /* Add a C nul term string as bulk reply */ 493 void addReplyBulkCString(redisClient *c, char *s) { 494 if (s == NULL) { 495 addReply(c,shared.nullbulk); 496 } else { 497 addReplyBulkCBuffer(c,s,strlen(s)); 498 } 499 } 500 501 /* Add a long long as a bulk reply */ 502 void addReplyBulkLongLong(redisClient *c, long long ll) { 503 char buf[64]; 504 int len; 505 506 len = ll2string(buf,64,ll); 507 addReplyBulkCBuffer(c,buf,len); 508 } 509 510 /* Copy 'src' client output buffers into 'dst' client output buffers. 511 * The function takes care of freeing the old output buffers of the 512 * destination client. */ 513 void copyClientOutputBuffer(redisClient *dst, redisClient *src) { 514 listRelease(dst->reply); 515 dst->reply = listDup(src->reply); 516 memcpy(dst->buf,src->buf,src->bufpos); 517 dst->bufpos = src->bufpos; 518 dst->reply_bytes = src->reply_bytes; 519 } 520 521 static void acceptCommonHandler(int fd, int flags) { 522 redisClient *c; 523 if ((c = createClient(fd)) == NULL) { 524 redisLog(REDIS_WARNING, 525 "Error registering fd event for the new client: %s (fd=%d)", 526 strerror(errno),fd); 527 close(fd); /* May be already closed, just ignore errors */ 528 return; 529 } 530 /* If maxclient directive is set and this is one client more... close the 531 * connection. Note that we create the client instead to check before 532 * for this condition, since now the socket is already set in non-blocking 533 * mode and we can send an error for free using the Kernel I/O */ 534 if (listLength(server.clients) > server.maxclients) { 535 char *err = "-ERR max number of clients reached\r\n"; 536 537 /* That's a best effort error message, don't check write errors */ 538 if (write(c->fd,err,strlen(err)) == -1) { 539 /* Nothing to do, Just to avoid the warning... */ 540 } 541 server.stat_rejected_conn++; 542 freeClient(c); 543 return; 544 } 545 server.stat_numconnections++; 546 c->flags |= flags; 547 } 548 549 void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 550 int cport, cfd; 551 char cip[128]; 552 REDIS_NOTUSED(el); 553 REDIS_NOTUSED(mask); 554 REDIS_NOTUSED(privdata); 555 556 cfd = anetTcpAccept(server.neterr, fd, cip, &cport); 557 if (cfd == AE_ERR) { 558 redisLog(REDIS_WARNING,"Accepting client connection: %s", server.neterr); 559 return; 560 } 561 redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport); 562 acceptCommonHandler(cfd,0); 563 } 564 565 void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 566 int cfd; 567 REDIS_NOTUSED(el); 568 REDIS_NOTUSED(mask); 569 REDIS_NOTUSED(privdata); 570 571 cfd = anetUnixAccept(server.neterr, fd); 572 if (cfd == AE_ERR) { 573 redisLog(REDIS_WARNING,"Accepting client connection: %s", server.neterr); 574 return; 575 } 576 redisLog(REDIS_VERBOSE,"Accepted connection to %s", server.unixsocket); 577 acceptCommonHandler(cfd,REDIS_UNIX_SOCKET); 578 } 579 580 581 static void freeClientArgv(redisClient *c) { 582 int j; 583 for (j = 0; j < c->argc; j++) 584 decrRefCount(c->argv[j]); 585 c->argc = 0; 586 c->cmd = NULL; 587 } 588 589 /* Close all the slaves connections. This is useful in chained replication 590 * when we resync with our own master and want to force all our slaves to 591 * resync with us as well. */ 592 void disconnectSlaves(void) { 593 while (listLength(server.slaves)) { 594 listNode *ln = listFirst(server.slaves); 595 freeClient((redisClient*)ln->value); 596 } 597 } 598 599 /* This function is called when the slave lose the connection with the 600 * master into an unexpected way. */ 601 void replicationHandleMasterDisconnection(void) { 602 server.master = NULL; 603 server.repl_state = REDIS_REPL_CONNECT; 604 server.repl_down_since = server.unixtime; 605 /* We lost connection with our master, force our slaves to resync 606 * with us as well to load the new data set. 607 * 608 * If server.masterhost is NULL the user called SLAVEOF NO ONE so 609 * slave resync is not needed. */ 610 if (server.masterhost != NULL) disconnectSlaves(); 611 } 612 613 void freeClient(redisClient *c) { 614 listNode *ln; 615 616 /* If this is marked as current client unset it */ 617 if (server.current_client == c) server.current_client = NULL; 618 619 /* If it is our master that's beging disconnected we should make sure 620 * to cache the state to try a partial resynchronization later. 621 * 622 * Note that before doing this we make sure that the client is not in 623 * some unexpected state, by checking its flags. */ 624 if (server.master && 625 (c->flags & REDIS_MASTER) && 626 !(c->flags & (REDIS_CLOSE_AFTER_REPLY| 627 REDIS_CLOSE_ASAP| 628 REDIS_BLOCKED| 629 REDIS_UNBLOCKED))) 630 { 631 replicationCacheMaster(c); 632 return; 633 } 634 635 /* Note that if the client we are freeing is blocked into a blocking 636 * call, we have to set querybuf to NULL *before* to call 637 * unblockClientWaitingData() to avoid processInputBuffer() will get 638 * called. Also it is important to remove the file events after 639 * this, because this call adds the READABLE event. */ 640 sdsfree(c->querybuf); 641 c->querybuf = NULL; 642 if (c->flags & REDIS_BLOCKED) 643 unblockClientWaitingData(c); 644 dictRelease(c->bpop.keys); 645 646 /* UNWATCH all the keys */ 647 unwatchAllKeys(c); 648 listRelease(c->watched_keys); 649 /* Unsubscribe from all the pubsub channels */ 650 pubsubUnsubscribeAllChannels(c,0); 651 pubsubUnsubscribeAllPatterns(c,0); 652 dictRelease(c->pubsub_channels); 653 listRelease(c->pubsub_patterns); 654 /* Close socket, unregister events, and remove list of replies and 655 * accumulated arguments. */ 656 if (c->fd != -1) { 657 aeDeleteFileEvent(server.el,c->fd,AE_READABLE); 658 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 659 close(c->fd); 660 } 661 listRelease(c->reply); 662 freeClientArgv(c); 663 /* Remove from the list of clients */ 664 if (c->fd != -1) { 665 ln = listSearchKey(server.clients,c); 666 redisAssert(ln != NULL); 667 listDelNode(server.clients,ln); 668 } 669 /* When client was just unblocked because of a blocking operation, 670 * remove it from the list with unblocked clients. */ 671 if (c->flags & REDIS_UNBLOCKED) { 672 ln = listSearchKey(server.unblocked_clients,c); 673 redisAssert(ln != NULL); 674 listDelNode(server.unblocked_clients,ln); 675 } 676 listRelease(c->io_keys); 677 /* Master/slave cleanup. 678 * Case 1: we lost the connection with a slave. */ 679 if (c->flags & REDIS_SLAVE) { 680 if (c->replstate == REDIS_REPL_SEND_BULK && c->repldbfd != -1) 681 close(c->repldbfd); 682 list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves; 683 ln = listSearchKey(l,c); 684 redisAssert(ln != NULL); 685 listDelNode(l,ln); 686 /* We need to remember the time when we started to have zero 687 * attached slaves, as after some time we'll free the replication 688 * backlog. */ 689 if (c->flags & REDIS_SLAVE && listLength(server.slaves) == 0) 690 server.repl_no_slaves_since = server.unixtime; 691 } 692 693 /* Case 2: we lost the connection with the master. */ 694 if (c->flags & REDIS_MASTER) replicationHandleMasterDisconnection(); 695 696 /* If this client was scheduled for async freeing we need to remove it 697 * from the queue. */ 698 if (c->flags & REDIS_CLOSE_ASAP) { 699 ln = listSearchKey(server.clients_to_close,c); 700 redisAssert(ln != NULL); 701 listDelNode(server.clients_to_close,ln); 702 } 703 704 /* Release memory */ 705 if (c->name) decrRefCount(c->name); 706 zfree(c->argv); 707 freeClientMultiState(c); 708 zfree(c); 709 } 710 711 /* Schedule a client to free it at a safe time in the serverCron() function. 712 * This function is useful when we need to terminate a client but we are in 713 * a context where calling freeClient() is not possible, because the client 714 * should be valid for the continuation of the flow of the program. */ 715 void freeClientAsync(redisClient *c) { 716 if (c->flags & REDIS_CLOSE_ASAP) return; 717 c->flags |= REDIS_CLOSE_ASAP; 718 listAddNodeTail(server.clients_to_close,c); 719 } 720 721 void freeClientsInAsyncFreeQueue(void) { 722 while (listLength(server.clients_to_close)) { 723 listNode *ln = listFirst(server.clients_to_close); 724 redisClient *c = listNodeValue(ln); 725 726 c->flags &= ~REDIS_CLOSE_ASAP; 727 freeClient(c); 728 listDelNode(server.clients_to_close,ln); 729 } 730 } 731 732 void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) { 733 redisClient *c = privdata; 734 int nwritten = 0, totwritten = 0, objlen; 735 size_t objmem; 736 robj *o; 737 REDIS_NOTUSED(el); 738 REDIS_NOTUSED(mask); 739 740 while(c->bufpos > 0 || listLength(c->reply)) { 741 if (c->bufpos > 0) { 742 if (c->flags & REDIS_MASTER) { 743 /* Don't reply to a master */ 744 nwritten = c->bufpos - c->sentlen; 745 } else { 746 nwritten = write(fd,c->buf+c->sentlen,c->bufpos-c->sentlen); 747 if (nwritten <= 0) break; 748 } 749 c->sentlen += nwritten; 750 totwritten += nwritten; 751 752 /* If the buffer was sent, set bufpos to zero to continue with 753 * the remainder of the reply. */ 754 if (c->sentlen == c->bufpos) { 755 c->bufpos = 0; 756 c->sentlen = 0; 757 } 758 } else { 759 o = listNodeValue(listFirst(c->reply)); 760 objlen = sdslen(o->ptr); 761 objmem = zmalloc_size_sds(o->ptr); 762 763 if (objlen == 0) { 764 listDelNode(c->reply,listFirst(c->reply)); 765 continue; 766 } 767 768 if (c->flags & REDIS_MASTER) { 769 /* Don't reply to a master */ 770 nwritten = objlen - c->sentlen; 771 } else { 772 nwritten = write(fd, ((char*)o->ptr)+c->sentlen,objlen-c->sentlen); 773 if (nwritten <= 0) break; 774 } 775 c->sentlen += nwritten; 776 totwritten += nwritten; 777 778 /* If we fully sent the object on head go to the next one */ 779 if (c->sentlen == objlen) { 780 listDelNode(c->reply,listFirst(c->reply)); 781 c->sentlen = 0; 782 c->reply_bytes -= objmem; 783 } 784 } 785 /* Note that we avoid to send more than REDIS_MAX_WRITE_PER_EVENT 786 * bytes, in a single threaded server it's a good idea to serve 787 * other clients as well, even if a very large request comes from 788 * super fast link that is always able to accept data (in real world 789 * scenario think about 'KEYS *' against the loopback interface). 790 * 791 * However if we are over the maxmemory limit we ignore that and 792 * just deliver as much data as it is possible to deliver. */ 793 if (totwritten > REDIS_MAX_WRITE_PER_EVENT && 794 (server.maxmemory == 0 || 795 zmalloc_used_memory() < server.maxmemory)) break; 796 } 797 if (nwritten == -1) { 798 if (errno == EAGAIN) { 799 nwritten = 0; 800 } else { 801 redisLog(REDIS_VERBOSE, 802 "Error writing to client: %s", strerror(errno)); 803 freeClient(c); 804 return; 805 } 806 } 807 if (totwritten > 0) c->lastinteraction = server.unixtime; 808 if (c->bufpos == 0 && listLength(c->reply) == 0) { 809 c->sentlen = 0; 810 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 811 812 /* Close connection after entire reply has been sent. */ 813 if (c->flags & REDIS_CLOSE_AFTER_REPLY) freeClient(c); 814 } 815 } 816 817 /* resetClient prepare the client to process the next command */ 818 void resetClient(redisClient *c) { 819 redisCommandProc *prevcmd = c->cmd ? c->cmd->proc : NULL; 820 821 freeClientArgv(c); 822 c->reqtype = 0; 823 c->multibulklen = 0; 824 c->bulklen = -1; 825 /* We clear the ASKING flag as well if we are not inside a MULTI, and 826 * if what we just executed is not the ASKING command itself. */ 827 if (!(c->flags & REDIS_MULTI) && prevcmd != askingCommand) 828 c->flags &= (~REDIS_ASKING); 829 } 830 831 int processInlineBuffer(redisClient *c) { 832 char *newline = strstr(c->querybuf,"\r\n"); 833 int argc, j; 834 sds *argv; 835 size_t querylen; 836 837 /* Nothing to do without a \r\n */ 838 if (newline == NULL) { 839 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 840 addReplyError(c,"Protocol error: too big inline request"); 841 setProtocolError(c,0); 842 } 843 return REDIS_ERR; 844 } 845 846 /* Split the input buffer up to the \r\n */ 847 querylen = newline-(c->querybuf); 848 argv = sdssplitlen(c->querybuf,querylen," ",1,&argc); 849 850 /* Leave data after the first line of the query in the buffer */ 851 c->querybuf = sdsrange(c->querybuf,querylen+2,-1); 852 853 /* Setup argv array on client structure */ 854 if (c->argv) zfree(c->argv); 855 c->argv = zmalloc(sizeof(robj*)*argc); 856 857 /* Create redis objects for all arguments. */ 858 for (c->argc = 0, j = 0; j < argc; j++) { 859 if (sdslen(argv[j])) { 860 c->argv[c->argc] = createObject(REDIS_STRING,argv[j]); 861 c->argc++; 862 } else { 863 sdsfree(argv[j]); 864 } 865 } 866 zfree(argv); 867 return REDIS_OK; 868 } 869 870 /* Helper function. Trims query buffer to make the function that processes 871 * multi bulk requests idempotent. */ 872 static void setProtocolError(redisClient *c, int pos) { 873 if (server.verbosity >= REDIS_VERBOSE) { 874 sds client = getClientInfoString(c); 875 redisLog(REDIS_VERBOSE, 876 "Protocol error from client: %s", client); 877 sdsfree(client); 878 } 879 c->flags |= REDIS_CLOSE_AFTER_REPLY; 880 c->querybuf = sdsrange(c->querybuf,pos,-1); 881 } 882 883 int processMultibulkBuffer(redisClient *c) { 884 char *newline = NULL; 885 int pos = 0, ok; 886 long long ll; 887 888 if (c->multibulklen == 0) { 889 /* The client should have been reset */ 890 redisAssertWithInfo(c,NULL,c->argc == 0); 891 892 /* Multi bulk length cannot be read without a \r\n */ 893 newline = strchr(c->querybuf,'\r'); 894 if (newline == NULL) { 895 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 896 addReplyError(c,"Protocol error: too big mbulk count string"); 897 setProtocolError(c,0); 898 } 899 return REDIS_ERR; 900 } 901 902 /* Buffer should also contain \n */ 903 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 904 return REDIS_ERR; 905 906 /* We know for sure there is a whole line since newline != NULL, 907 * so go ahead and find out the multi bulk length. */ 908 redisAssertWithInfo(c,NULL,c->querybuf[0] == '*'); 909 ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll); 910 if (!ok || ll > 1024*1024) { 911 addReplyError(c,"Protocol error: invalid multibulk length"); 912 setProtocolError(c,pos); 913 return REDIS_ERR; 914 } 915 916 pos = (newline-c->querybuf)+2; 917 if (ll <= 0) { 918 c->querybuf = sdsrange(c->querybuf,pos,-1); 919 return REDIS_OK; 920 } 921 922 c->multibulklen = ll; 923 924 /* Setup argv array on client structure */ 925 if (c->argv) zfree(c->argv); 926 c->argv = zmalloc(sizeof(robj*)*c->multibulklen); 927 } 928 929 redisAssertWithInfo(c,NULL,c->multibulklen > 0); 930 while(c->multibulklen) { 931 /* Read bulk length if unknown */ 932 if (c->bulklen == -1) { 933 newline = strchr(c->querybuf+pos,'\r'); 934 if (newline == NULL) { 935 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 936 addReplyError(c,"Protocol error: too big bulk count string"); 937 setProtocolError(c,0); 938 } 939 break; 940 } 941 942 /* Buffer should also contain \n */ 943 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 944 break; 945 946 if (c->querybuf[pos] != '$') { 947 addReplyErrorFormat(c, 948 "Protocol error: expected '$', got '%c'", 949 c->querybuf[pos]); 950 setProtocolError(c,pos); 951 return REDIS_ERR; 952 } 953 954 ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll); 955 if (!ok || ll < 0 || ll > 512*1024*1024) { 956 addReplyError(c,"Protocol error: invalid bulk length"); 957 setProtocolError(c,pos); 958 return REDIS_ERR; 959 } 960 961 pos += newline-(c->querybuf+pos)+2; 962 if (ll >= REDIS_MBULK_BIG_ARG) { 963 /* If we are going to read a large object from network 964 * try to make it likely that it will start at c->querybuf 965 * boundary so that we can optimized object creation 966 * avoiding a large copy of data. */ 967 c->querybuf = sdsrange(c->querybuf,pos,-1); 968 pos = 0; 969 /* Hint the sds library about the amount of bytes this string is 970 * going to contain. */ 971 c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2); 972 } 973 c->bulklen = ll; 974 } 975 976 /* Read bulk argument */ 977 if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) { 978 /* Not enough data (+2 == trailing \r\n) */ 979 break; 980 } else { 981 /* Optimization: if the buffer contains JUST our bulk element 982 * instead of creating a new object by *copying* the sds we 983 * just use the current sds string. */ 984 if (pos == 0 && 985 c->bulklen >= REDIS_MBULK_BIG_ARG && 986 (signed) sdslen(c->querybuf) == c->bulklen+2) 987 { 988 c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf); 989 sdsIncrLen(c->querybuf,-2); /* remove CRLF */ 990 c->querybuf = sdsempty(); 991 /* Assume that if we saw a fat argument we'll see another one 992 * likely... */ 993 c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2); 994 pos = 0; 995 } else { 996 c->argv[c->argc++] = 997 createStringObject(c->querybuf+pos,c->bulklen); 998 pos += c->bulklen+2; 999 } 1000 c->bulklen = -1; 1001 c->multibulklen--; 1002 } 1003 } 1004 1005 /* Trim to pos */ 1006 if (pos) c->querybuf = sdsrange(c->querybuf,pos,-1); 1007 1008 /* We're done when c->multibulk == 0 */ 1009 if (c->multibulklen == 0) return REDIS_OK; 1010 1011 /* Still not read to process the command */ 1012 return REDIS_ERR; 1013 } 1014 1015 void processInputBuffer(redisClient *c) { 1016 /* Keep processing while there is something in the input buffer */ 1017 while(sdslen(c->querybuf)) { 1018 /* Immediately abort if the client is in the middle of something. */ 1019 if (c->flags & REDIS_BLOCKED) return; 1020 1021 /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is 1022 * written to the client. Make sure to not let the reply grow after 1023 * this flag has been set (i.e. don't process more commands). */ 1024 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 1025 1026 /* Determine request type when unknown. */ 1027 if (!c->reqtype) { 1028 if (c->querybuf[0] == '*') { 1029 c->reqtype = REDIS_REQ_MULTIBULK; 1030 } else { 1031 c->reqtype = REDIS_REQ_INLINE; 1032 } 1033 } 1034 1035 if (c->reqtype == REDIS_REQ_INLINE) { 1036 if (processInlineBuffer(c) != REDIS_OK) break; 1037 } else if (c->reqtype == REDIS_REQ_MULTIBULK) { 1038 if (processMultibulkBuffer(c) != REDIS_OK) break; 1039 } else { 1040 redisPanic("Unknown request type"); 1041 } 1042 1043 /* Multibulk processing could see a <= 0 length. */ 1044 if (c->argc == 0) { 1045 resetClient(c); 1046 } else { 1047 /* Only reset the client when the command was executed. */ 1048 if (processCommand(c) == REDIS_OK) 1049 resetClient(c); 1050 } 1051 } 1052 } 1053 1054 void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { 1055 redisClient *c = (redisClient*) privdata; 1056 int nread, readlen; 1057 size_t qblen; 1058 REDIS_NOTUSED(el); 1059 REDIS_NOTUSED(mask); 1060 1061 server.current_client = c; 1062 readlen = REDIS_IOBUF_LEN; 1063 /* If this is a multi bulk request, and we are processing a bulk reply 1064 * that is large enough, try to maximize the probability that the query 1065 * buffer contains exactly the SDS string representing the object, even 1066 * at the risk of requiring more read(2) calls. This way the function 1067 * processMultiBulkBuffer() can avoid copying buffers to create the 1068 * Redis Object representing the argument. */ 1069 if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1 1070 && c->bulklen >= REDIS_MBULK_BIG_ARG) 1071 { 1072 int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf); 1073 1074 if (remaining < readlen) readlen = remaining; 1075 } 1076 1077 qblen = sdslen(c->querybuf); 1078 if (c->querybuf_peak < qblen) c->querybuf_peak = qblen; 1079 c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); 1080 nread = read(fd, c->querybuf+qblen, readlen); 1081 if (nread == -1) { 1082 if (errno == EAGAIN) { 1083 nread = 0; 1084 } else { 1085 redisLog(REDIS_VERBOSE, "Reading from client: %s",strerror(errno)); 1086 freeClient(c); 1087 return; 1088 } 1089 } else if (nread == 0) { 1090 redisLog(REDIS_VERBOSE, "Client closed connection"); 1091 freeClient(c); 1092 return; 1093 } 1094 if (nread) { 1095 sdsIncrLen(c->querybuf,nread); 1096 c->lastinteraction = server.unixtime; 1097 if (c->flags & REDIS_MASTER) c->reploff += nread; 1098 } else { 1099 server.current_client = NULL; 1100 return; 1101 } 1102 if (sdslen(c->querybuf) > server.client_max_querybuf_len) { 1103 sds ci = getClientInfoString(c), bytes = sdsempty(); 1104 1105 bytes = sdscatrepr(bytes,c->querybuf,64); 1106 redisLog(REDIS_WARNING,"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)", ci, bytes); 1107 sdsfree(ci); 1108 sdsfree(bytes); 1109 freeClient(c); 1110 return; 1111 } 1112 processInputBuffer(c); 1113 server.current_client = NULL; 1114 } 1115 1116 void getClientsMaxBuffers(unsigned long *longest_output_list, 1117 unsigned long *biggest_input_buffer) { 1118 redisClient *c; 1119 listNode *ln; 1120 listIter li; 1121 unsigned long lol = 0, bib = 0; 1122 1123 listRewind(server.clients,&li); 1124 while ((ln = listNext(&li)) != NULL) { 1125 c = listNodeValue(ln); 1126 1127 if (listLength(c->reply) > lol) lol = listLength(c->reply); 1128 if (sdslen(c->querybuf) > bib) bib = sdslen(c->querybuf); 1129 } 1130 *longest_output_list = lol; 1131 *biggest_input_buffer = bib; 1132 } 1133 1134 /* Turn a Redis client into an sds string representing its state. */ 1135 sds getClientInfoString(redisClient *client) { 1136 char ip[32], flags[16], events[3], *p; 1137 int port = 0; /* initialized to zero for the unix socket case. */ 1138 int emask; 1139 1140 if (!(client->flags & REDIS_UNIX_SOCKET)) 1141 anetPeerToString(client->fd,ip,&port); 1142 p = flags; 1143 if (client->flags & REDIS_SLAVE) { 1144 if (client->flags & REDIS_MONITOR) 1145 *p++ = 'O'; 1146 else 1147 *p++ = 'S'; 1148 } 1149 if (client->flags & REDIS_MASTER) *p++ = 'M'; 1150 if (client->flags & REDIS_MULTI) *p++ = 'x'; 1151 if (client->flags & REDIS_BLOCKED) *p++ = 'b'; 1152 if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; 1153 if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; 1154 if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; 1155 if (client->flags & REDIS_CLOSE_ASAP) *p++ = 'A'; 1156 if (client->flags & REDIS_UNIX_SOCKET) *p++ = 'U'; 1157 if (p == flags) *p++ = 'N'; 1158 *p++ = '\0'; 1159 1160 emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd); 1161 p = events; 1162 if (emask & AE_READABLE) *p++ = 'r'; 1163 if (emask & AE_WRITABLE) *p++ = 'w'; 1164 *p = '\0'; 1165 return sdscatprintf(sdsempty(), 1166 "addr=%s:%d fd=%d name=%s age=%ld idle=%ld flags=%s db=%d sub=%d psub=%d multi=%d qbuf=%lu qbuf-free=%lu obl=%lu oll=%lu omem=%lu events=%s cmd=%s", 1167 (client->flags & REDIS_UNIX_SOCKET) ? server.unixsocket : ip, 1168 port, 1169 client->fd, 1170 client->name ? (char*)client->name->ptr : "", 1171 (long)(server.unixtime - client->ctime), 1172 (long)(server.unixtime - client->lastinteraction), 1173 flags, 1174 client->db->id, 1175 (int) dictSize(client->pubsub_channels), 1176 (int) listLength(client->pubsub_patterns), 1177 (client->flags & REDIS_MULTI) ? client->mstate.count : -1, 1178 (unsigned long) sdslen(client->querybuf), 1179 (unsigned long) sdsavail(client->querybuf), 1180 (unsigned long) client->bufpos, 1181 (unsigned long) listLength(client->reply), 1182 getClientOutputBufferMemoryUsage(client), 1183 events, 1184 client->lastcmd ? client->lastcmd->name : "NULL"); 1185 } 1186 1187 sds getAllClientsInfoString(void) { 1188 listNode *ln; 1189 listIter li; 1190 redisClient *client; 1191 sds o = sdsempty(); 1192 1193 listRewind(server.clients,&li); 1194 while ((ln = listNext(&li)) != NULL) { 1195 sds cs; 1196 1197 client = listNodeValue(ln); 1198 cs = getClientInfoString(client); 1199 o = sdscatsds(o,cs); 1200 sdsfree(cs); 1201 o = sdscatlen(o,"\n",1); 1202 } 1203 return o; 1204 } 1205 1206 void clientCommand(redisClient *c) { 1207 listNode *ln; 1208 listIter li; 1209 redisClient *client; 1210 1211 if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { 1212 sds o = getAllClientsInfoString(); 1213 addReplyBulkCBuffer(c,o,sdslen(o)); 1214 sdsfree(o); 1215 } else if (!strcasecmp(c->argv[1]->ptr,"kill") && c->argc == 3) { 1216 listRewind(server.clients,&li); 1217 while ((ln = listNext(&li)) != NULL) { 1218 char ip[32], addr[64]; 1219 int port; 1220 1221 client = listNodeValue(ln); 1222 if (anetPeerToString(client->fd,ip,&port) == -1) continue; 1223 snprintf(addr,sizeof(addr),"%s:%d",ip,port); 1224 if (strcmp(addr,c->argv[2]->ptr) == 0) { 1225 addReply(c,shared.ok); 1226 if (c == client) { 1227 client->flags |= REDIS_CLOSE_AFTER_REPLY; 1228 } else { 1229 freeClient(client); 1230 } 1231 return; 1232 } 1233 } 1234 addReplyError(c,"No such client"); 1235 } else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { 1236 int j, len = sdslen(c->argv[2]->ptr); 1237 char *p = c->argv[2]->ptr; 1238 1239 /* Setting the client name to an empty string actually removes 1240 * the current name. */ 1241 if (len == 0) { 1242 if (c->name) decrRefCount(c->name); 1243 c->name = NULL; 1244 addReply(c,shared.ok); 1245 return; 1246 } 1247 1248 /* Otherwise check if the charset is ok. We need to do this otherwise 1249 * CLIENT LIST format will break. You should always be able to 1250 * split by space to get the different fields. */ 1251 for (j = 0; j < len; j++) { 1252 if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */ 1253 addReplyError(c, 1254 "Client names cannot contain spaces, " 1255 "newlines or special characters."); 1256 return; 1257 } 1258 } 1259 if (c->name) decrRefCount(c->name); 1260 c->name = c->argv[2]; 1261 incrRefCount(c->name); 1262 addReply(c,shared.ok); 1263 } else if (!strcasecmp(c->argv[1]->ptr,"getname") && c->argc == 2) { 1264 if (c->name) 1265 addReplyBulk(c,c->name); 1266 else 1267 addReply(c,shared.nullbulk); 1268 } else { 1269 addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port | GETNAME | SETNAME connection-name)"); 1270 } 1271 } 1272 1273 /* Rewrite the command vector of the client. All the new objects ref count 1274 * is incremented. The old command vector is freed, and the old objects 1275 * ref count is decremented. */ 1276 void rewriteClientCommandVector(redisClient *c, int argc, ...) { 1277 va_list ap; 1278 int j; 1279 robj **argv; /* The new argument vector */ 1280 1281 argv = zmalloc(sizeof(robj*)*argc); 1282 va_start(ap,argc); 1283 for (j = 0; j < argc; j++) { 1284 robj *a; 1285 1286 a = va_arg(ap, robj*); 1287 argv[j] = a; 1288 incrRefCount(a); 1289 } 1290 /* We free the objects in the original vector at the end, so we are 1291 * sure that if the same objects are reused in the new vector the 1292 * refcount gets incremented before it gets decremented. */ 1293 for (j = 0; j < c->argc; j++) decrRefCount(c->argv[j]); 1294 zfree(c->argv); 1295 /* Replace argv and argc with our new versions. */ 1296 c->argv = argv; 1297 c->argc = argc; 1298 c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr); 1299 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1300 va_end(ap); 1301 } 1302 1303 /* Rewrite a single item in the command vector. 1304 * The new val ref count is incremented, and the old decremented. */ 1305 void rewriteClientCommandArgument(redisClient *c, int i, robj *newval) { 1306 robj *oldval; 1307 1308 redisAssertWithInfo(c,NULL,i < c->argc); 1309 oldval = c->argv[i]; 1310 c->argv[i] = newval; 1311 incrRefCount(newval); 1312 decrRefCount(oldval); 1313 1314 /* If this is the command name make sure to fix c->cmd. */ 1315 if (i == 0) { 1316 c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr); 1317 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1318 } 1319 } 1320 1321 /* This function returns the number of bytes that Redis is virtually 1322 * using to store the reply still not read by the client. 1323 * It is "virtual" since the reply output list may contain objects that 1324 * are shared and are not really using additional memory. 1325 * 1326 * The function returns the total sum of the length of all the objects 1327 * stored in the output list, plus the memory used to allocate every 1328 * list node. The static reply buffer is not taken into account since it 1329 * is allocated anyway. 1330 * 1331 * Note: this function is very fast so can be called as many time as 1332 * the caller wishes. The main usage of this function currently is 1333 * enforcing the client output length limits. */ 1334 unsigned long getClientOutputBufferMemoryUsage(redisClient *c) { 1335 unsigned long list_item_size = sizeof(listNode)+sizeof(robj); 1336 1337 return c->reply_bytes + (list_item_size*listLength(c->reply)); 1338 } 1339 1340 /* Get the class of a client, used in order to enforce limits to different 1341 * classes of clients. 1342 * 1343 * The function will return one of the following: 1344 * REDIS_CLIENT_LIMIT_CLASS_NORMAL -> Normal client 1345 * REDIS_CLIENT_LIMIT_CLASS_SLAVE -> Slave or client executing MONITOR command 1346 * REDIS_CLIENT_LIMIT_CLASS_PUBSUB -> Client subscribed to Pub/Sub channels 1347 */ 1348 int getClientLimitClass(redisClient *c) { 1349 if (c->flags & REDIS_SLAVE) return REDIS_CLIENT_LIMIT_CLASS_SLAVE; 1350 if (dictSize(c->pubsub_channels) || listLength(c->pubsub_patterns)) 1351 return REDIS_CLIENT_LIMIT_CLASS_PUBSUB; 1352 return REDIS_CLIENT_LIMIT_CLASS_NORMAL; 1353 } 1354 1355 int getClientLimitClassByName(char *name) { 1356 if (!strcasecmp(name,"normal")) return REDIS_CLIENT_LIMIT_CLASS_NORMAL; 1357 else if (!strcasecmp(name,"slave")) return REDIS_CLIENT_LIMIT_CLASS_SLAVE; 1358 else if (!strcasecmp(name,"pubsub")) return REDIS_CLIENT_LIMIT_CLASS_PUBSUB; 1359 else return -1; 1360 } 1361 1362 char *getClientLimitClassName(int class) { 1363 switch(class) { 1364 case REDIS_CLIENT_LIMIT_CLASS_NORMAL: return "normal"; 1365 case REDIS_CLIENT_LIMIT_CLASS_SLAVE: return "slave"; 1366 case REDIS_CLIENT_LIMIT_CLASS_PUBSUB: return "pubsub"; 1367 default: return NULL; 1368 } 1369 } 1370 1371 /* The function checks if the client reached output buffer soft or hard 1372 * limit, and also update the state needed to check the soft limit as 1373 * a side effect. 1374 * 1375 * Return value: non-zero if the client reached the soft or the hard limit. 1376 * Otherwise zero is returned. */ 1377 int checkClientOutputBufferLimits(redisClient *c) { 1378 int soft = 0, hard = 0, class; 1379 unsigned long used_mem = getClientOutputBufferMemoryUsage(c); 1380 1381 class = getClientLimitClass(c); 1382 if (server.client_obuf_limits[class].hard_limit_bytes && 1383 used_mem >= server.client_obuf_limits[class].hard_limit_bytes) 1384 hard = 1; 1385 if (server.client_obuf_limits[class].soft_limit_bytes && 1386 used_mem >= server.client_obuf_limits[class].soft_limit_bytes) 1387 soft = 1; 1388 1389 /* We need to check if the soft limit is reached continuously for the 1390 * specified amount of seconds. */ 1391 if (soft) { 1392 if (c->obuf_soft_limit_reached_time == 0) { 1393 c->obuf_soft_limit_reached_time = server.unixtime; 1394 soft = 0; /* First time we see the soft limit reached */ 1395 } else { 1396 time_t elapsed = server.unixtime - c->obuf_soft_limit_reached_time; 1397 1398 if (elapsed <= 1399 server.client_obuf_limits[class].soft_limit_seconds) { 1400 soft = 0; /* The client still did not reached the max number of 1401 seconds for the soft limit to be considered 1402 reached. */ 1403 } 1404 } 1405 } else { 1406 c->obuf_soft_limit_reached_time = 0; 1407 } 1408 return soft || hard; 1409 } 1410 1411 /* Asynchronously close a client if soft or hard limit is reached on the 1412 * output buffer size. The caller can check if the client will be closed 1413 * checking if the client REDIS_CLOSE_ASAP flag is set. 1414 * 1415 * Note: we need to close the client asynchronously because this function is 1416 * called from contexts where the client can't be freed safely, i.e. from the 1417 * lower level functions pushing data inside the client output buffers. */ 1418 void asyncCloseClientOnOutputBufferLimitReached(redisClient *c) { 1419 redisAssert(c->reply_bytes < ULONG_MAX-(1024*64)); 1420 if (c->reply_bytes == 0 || c->flags & REDIS_CLOSE_ASAP) return; 1421 if (checkClientOutputBufferLimits(c)) { 1422 sds client = getClientInfoString(c); 1423 1424 freeClientAsync(c); 1425 redisLog(REDIS_WARNING,"Client %s scheduled to be closed ASAP for overcoming of output buffer limits.", client); 1426 sdsfree(client); 1427 } 1428 } 1429 1430 /* Helper function used by freeMemoryIfNeeded() in order to flush slaves 1431 * output buffers without returning control to the event loop. */ 1432 void flushSlavesOutputBuffers(void) { 1433 listIter li; 1434 listNode *ln; 1435 1436 listRewind(server.slaves,&li); 1437 while((ln = listNext(&li))) { 1438 redisClient *slave = listNodeValue(ln); 1439 int events; 1440 1441 events = aeGetFileEvents(server.el,slave->fd); 1442 if (events & AE_WRITABLE && 1443 slave->replstate == REDIS_REPL_ONLINE && 1444 listLength(slave->reply)) 1445 { 1446 sendReplyToClient(server.el,slave->fd,slave,0); 1447 } 1448 } 1449 } 1450