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