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 #include <math.h> 33 34 static void setProtocolError(redisClient *c, int pos); 35 36 /* To evaluate the output buffer size of a client we need to get size of 37 * allocated objects, however we can't used zmalloc_size() directly on sds 38 * strings because of the trick they use to work (the header is before the 39 * returned pointer), so we use this helper function. */ 40 size_t zmalloc_size_sds(sds s) { 41 return zmalloc_size(s-sizeof(struct sdshdr)); 42 } 43 44 /* Return the amount of memory used by the sds string at object->ptr 45 * for a string object. */ 46 size_t getStringObjectSdsUsedMemory(robj *o) { 47 redisAssertWithInfo(NULL,o,o->type == REDIS_STRING); 48 switch(o->encoding) { 49 case REDIS_ENCODING_RAW: return zmalloc_size_sds(o->ptr); 50 case REDIS_ENCODING_EMBSTR: return sdslen(o->ptr); 51 default: return 0; /* Just integer encoding for now. */ 52 } 53 } 54 55 void *dupClientReplyValue(void *o) { 56 incrRefCount((robj*)o); 57 return o; 58 } 59 60 int listMatchObjects(void *a, void *b) { 61 return equalStringObjects(a,b); 62 } 63 64 redisClient *createClient(int fd) { 65 redisClient *c = zmalloc(sizeof(redisClient)); 66 67 /* passing -1 as fd it is possible to create a non connected client. 68 * This is useful since all the Redis commands needs to be executed 69 * in the context of a client. When commands are executed in other 70 * contexts (for instance a Lua script) we need a non connected client. */ 71 if (fd != -1) { 72 anetNonBlock(NULL,fd); 73 anetEnableTcpNoDelay(NULL,fd); 74 if (server.tcpkeepalive) 75 anetKeepAlive(NULL,fd,server.tcpkeepalive); 76 if (aeCreateFileEvent(server.el,fd,AE_READABLE, 77 readQueryFromClient, c) == AE_ERR) 78 { 79 close(fd); 80 zfree(c); 81 return NULL; 82 } 83 } 84 85 selectDb(c,0); 86 c->id = server.next_client_id++; 87 c->fd = fd; 88 c->name = NULL; 89 c->bufpos = 0; 90 c->querybuf = sdsempty(); 91 c->querybuf_peak = 0; 92 c->reqtype = 0; 93 c->argc = 0; 94 c->argv = NULL; 95 c->cmd = c->lastcmd = NULL; 96 c->multibulklen = 0; 97 c->bulklen = -1; 98 c->sentlen = 0; 99 c->flags = 0; 100 c->ctime = c->lastinteraction = server.unixtime; 101 c->authenticated = 0; 102 c->replstate = REDIS_REPL_NONE; 103 c->repl_put_online_on_ack = 0; 104 c->reploff = 0; 105 c->repl_ack_off = 0; 106 c->repl_ack_time = 0; 107 c->slave_listening_port = 0; 108 c->reply = listCreate(); 109 c->reply_bytes = 0; 110 c->obuf_soft_limit_reached_time = 0; 111 listSetFreeMethod(c->reply,decrRefCountVoid); 112 listSetDupMethod(c->reply,dupClientReplyValue); 113 c->btype = REDIS_BLOCKED_NONE; 114 c->bpop.timeout = 0; 115 c->bpop.keys = dictCreate(&setDictType,NULL); 116 c->bpop.target = NULL; 117 c->bpop.numreplicas = 0; 118 c->bpop.reploffset = 0; 119 c->woff = 0; 120 c->watched_keys = listCreate(); 121 c->pubsub_channels = dictCreate(&setDictType,NULL); 122 c->pubsub_patterns = listCreate(); 123 c->peerid = NULL; 124 listSetFreeMethod(c->pubsub_patterns,decrRefCountVoid); 125 listSetMatchMethod(c->pubsub_patterns,listMatchObjects); 126 if (fd != -1) listAddNodeTail(server.clients,c); 127 initClientMultiState(c); 128 return c; 129 } 130 131 /* This function is called every time we are going to transmit new data 132 * to the client. The behavior is the following: 133 * 134 * If the client should receive new data (normal clients will) the function 135 * returns REDIS_OK, and make sure to install the write handler in our event 136 * loop so that when the socket is writable new data gets written. 137 * 138 * If the client should not receive new data, because it is a fake client, 139 * a master, a slave not yet online, or because the setup of the write handler 140 * failed, the function returns REDIS_ERR. 141 * 142 * Typically gets called every time a reply is built, before adding more 143 * data to the clients output buffers. If the function returns REDIS_ERR no 144 * data should be appended to the output buffers. */ 145 int prepareClientToWrite(redisClient *c) { 146 if (c->flags & REDIS_LUA_CLIENT) return REDIS_OK; 147 if ((c->flags & REDIS_MASTER) && 148 !(c->flags & REDIS_MASTER_FORCE_REPLY)) return REDIS_ERR; 149 if (c->fd <= 0) return REDIS_ERR; /* Fake client */ 150 if (c->bufpos == 0 && listLength(c->reply) == 0 && 151 (c->replstate == REDIS_REPL_NONE || 152 c->replstate == REDIS_REPL_ONLINE) && 153 aeCreateFileEvent(server.el, c->fd, AE_WRITABLE, 154 sendReplyToClient, c) == AE_ERR) return REDIS_ERR; 155 return REDIS_OK; 156 } 157 158 /* Create a duplicate of the last object in the reply list when 159 * it is not exclusively owned by the reply list. */ 160 robj *dupLastObjectIfNeeded(list *reply) { 161 robj *new, *cur; 162 listNode *ln; 163 redisAssert(listLength(reply) > 0); 164 ln = listLast(reply); 165 cur = listNodeValue(ln); 166 if (cur->refcount > 1) { 167 new = dupStringObject(cur); 168 decrRefCount(cur); 169 listNodeValue(ln) = new; 170 } 171 return listNodeValue(ln); 172 } 173 174 /* ----------------------------------------------------------------------------- 175 * Low level functions to add more data to output buffers. 176 * -------------------------------------------------------------------------- */ 177 178 int _addReplyToBuffer(redisClient *c, const char *s, size_t len) { 179 size_t available = sizeof(c->buf)-c->bufpos; 180 181 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return REDIS_OK; 182 183 /* If there already are entries in the reply list, we cannot 184 * add anything more to the static buffer. */ 185 if (listLength(c->reply) > 0) return REDIS_ERR; 186 187 /* Check that the buffer has enough space available for this string. */ 188 if (len > available) return REDIS_ERR; 189 190 memcpy(c->buf+c->bufpos,s,len); 191 c->bufpos+=len; 192 return REDIS_OK; 193 } 194 195 void _addReplyObjectToList(redisClient *c, robj *o) { 196 robj *tail; 197 198 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 199 200 if (listLength(c->reply) == 0) { 201 incrRefCount(o); 202 listAddNodeTail(c->reply,o); 203 c->reply_bytes += getStringObjectSdsUsedMemory(o); 204 } else { 205 tail = listNodeValue(listLast(c->reply)); 206 207 /* Append to this object when possible. */ 208 if (tail->ptr != NULL && 209 tail->encoding == REDIS_ENCODING_RAW && 210 sdslen(tail->ptr)+sdslen(o->ptr) <= REDIS_REPLY_CHUNK_BYTES) 211 { 212 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 213 tail = dupLastObjectIfNeeded(c->reply); 214 tail->ptr = sdscatlen(tail->ptr,o->ptr,sdslen(o->ptr)); 215 c->reply_bytes += zmalloc_size_sds(tail->ptr); 216 } else { 217 incrRefCount(o); 218 listAddNodeTail(c->reply,o); 219 c->reply_bytes += getStringObjectSdsUsedMemory(o); 220 } 221 } 222 asyncCloseClientOnOutputBufferLimitReached(c); 223 } 224 225 /* This method takes responsibility over the sds. When it is no longer 226 * needed it will be free'd, otherwise it ends up in a robj. */ 227 void _addReplySdsToList(redisClient *c, sds s) { 228 robj *tail; 229 230 if (c->flags & REDIS_CLOSE_AFTER_REPLY) { 231 sdsfree(s); 232 return; 233 } 234 235 if (listLength(c->reply) == 0) { 236 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 237 c->reply_bytes += zmalloc_size_sds(s); 238 } else { 239 tail = listNodeValue(listLast(c->reply)); 240 241 /* Append to this object when possible. */ 242 if (tail->ptr != NULL && tail->encoding == REDIS_ENCODING_RAW && 243 sdslen(tail->ptr)+sdslen(s) <= REDIS_REPLY_CHUNK_BYTES) 244 { 245 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 246 tail = dupLastObjectIfNeeded(c->reply); 247 tail->ptr = sdscatlen(tail->ptr,s,sdslen(s)); 248 c->reply_bytes += zmalloc_size_sds(tail->ptr); 249 sdsfree(s); 250 } else { 251 listAddNodeTail(c->reply,createObject(REDIS_STRING,s)); 252 c->reply_bytes += zmalloc_size_sds(s); 253 } 254 } 255 asyncCloseClientOnOutputBufferLimitReached(c); 256 } 257 258 void _addReplyStringToList(redisClient *c, const char *s, size_t len) { 259 robj *tail; 260 261 if (c->flags & REDIS_CLOSE_AFTER_REPLY) return; 262 263 if (listLength(c->reply) == 0) { 264 robj *o = createStringObject(s,len); 265 266 listAddNodeTail(c->reply,o); 267 c->reply_bytes += getStringObjectSdsUsedMemory(o); 268 } else { 269 tail = listNodeValue(listLast(c->reply)); 270 271 /* Append to this object when possible. */ 272 if (tail->ptr != NULL && tail->encoding == REDIS_ENCODING_RAW && 273 sdslen(tail->ptr)+len <= REDIS_REPLY_CHUNK_BYTES) 274 { 275 c->reply_bytes -= zmalloc_size_sds(tail->ptr); 276 tail = dupLastObjectIfNeeded(c->reply); 277 tail->ptr = sdscatlen(tail->ptr,s,len); 278 c->reply_bytes += zmalloc_size_sds(tail->ptr); 279 } else { 280 robj *o = createStringObject(s,len); 281 282 listAddNodeTail(c->reply,o); 283 c->reply_bytes += getStringObjectSdsUsedMemory(o); 284 } 285 } 286 asyncCloseClientOnOutputBufferLimitReached(c); 287 } 288 289 /* ----------------------------------------------------------------------------- 290 * Higher level functions to queue data on the client output buffer. 291 * The following functions are the ones that commands implementations will call. 292 * -------------------------------------------------------------------------- */ 293 294 void addReply(redisClient *c, robj *obj) { 295 if (prepareClientToWrite(c) != REDIS_OK) return; 296 297 /* This is an important place where we can avoid copy-on-write 298 * when there is a saving child running, avoiding touching the 299 * refcount field of the object if it's not needed. 300 * 301 * If the encoding is RAW and there is room in the static buffer 302 * we'll be able to send the object to the client without 303 * messing with its page. */ 304 if (sdsEncodedObject(obj)) { 305 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 306 _addReplyObjectToList(c,obj); 307 } else if (obj->encoding == REDIS_ENCODING_INT) { 308 /* Optimization: if there is room in the static buffer for 32 bytes 309 * (more than the max chars a 64 bit integer can take as string) we 310 * avoid decoding the object and go for the lower level approach. */ 311 if (listLength(c->reply) == 0 && (sizeof(c->buf) - c->bufpos) >= 32) { 312 char buf[32]; 313 int len; 314 315 len = ll2string(buf,sizeof(buf),(long)obj->ptr); 316 if (_addReplyToBuffer(c,buf,len) == REDIS_OK) 317 return; 318 /* else... continue with the normal code path, but should never 319 * happen actually since we verified there is room. */ 320 } 321 obj = getDecodedObject(obj); 322 if (_addReplyToBuffer(c,obj->ptr,sdslen(obj->ptr)) != REDIS_OK) 323 _addReplyObjectToList(c,obj); 324 decrRefCount(obj); 325 } else { 326 redisPanic("Wrong obj->encoding in addReply()"); 327 } 328 } 329 330 void addReplySds(redisClient *c, sds s) { 331 if (prepareClientToWrite(c) != REDIS_OK) { 332 /* The caller expects the sds to be free'd. */ 333 sdsfree(s); 334 return; 335 } 336 if (_addReplyToBuffer(c,s,sdslen(s)) == REDIS_OK) { 337 sdsfree(s); 338 } else { 339 /* This method free's the sds when it is no longer needed. */ 340 _addReplySdsToList(c,s); 341 } 342 } 343 344 void addReplyString(redisClient *c, const char *s, size_t len) { 345 if (prepareClientToWrite(c) != REDIS_OK) return; 346 if (_addReplyToBuffer(c,s,len) != REDIS_OK) 347 _addReplyStringToList(c,s,len); 348 } 349 350 void addReplyErrorLength(redisClient *c, const char *s, size_t len) { 351 addReplyString(c,"-ERR ",5); 352 addReplyString(c,s,len); 353 addReplyString(c,"\r\n",2); 354 } 355 356 void addReplyError(redisClient *c, const char *err) { 357 addReplyErrorLength(c,err,strlen(err)); 358 } 359 360 void addReplyErrorFormat(redisClient *c, const char *fmt, ...) { 361 size_t l, j; 362 va_list ap; 363 va_start(ap,fmt); 364 sds s = sdscatvprintf(sdsempty(),fmt,ap); 365 va_end(ap); 366 /* Make sure there are no newlines in the string, otherwise invalid protocol 367 * is emitted. */ 368 l = sdslen(s); 369 for (j = 0; j < l; j++) { 370 if (s[j] == '\r' || s[j] == '\n') s[j] = ' '; 371 } 372 addReplyErrorLength(c,s,sdslen(s)); 373 sdsfree(s); 374 } 375 376 void addReplyStatusLength(redisClient *c, const char *s, size_t len) { 377 addReplyString(c,"+",1); 378 addReplyString(c,s,len); 379 addReplyString(c,"\r\n",2); 380 } 381 382 void addReplyStatus(redisClient *c, const char *status) { 383 addReplyStatusLength(c,status,strlen(status)); 384 } 385 386 void addReplyStatusFormat(redisClient *c, const char *fmt, ...) { 387 va_list ap; 388 va_start(ap,fmt); 389 sds s = sdscatvprintf(sdsempty(),fmt,ap); 390 va_end(ap); 391 addReplyStatusLength(c,s,sdslen(s)); 392 sdsfree(s); 393 } 394 395 /* Adds an empty object to the reply list that will contain the multi bulk 396 * length, which is not known when this function is called. */ 397 void *addDeferredMultiBulkLength(redisClient *c) { 398 /* Note that we install the write event here even if the object is not 399 * ready to be sent, since we are sure that before returning to the 400 * event loop setDeferredMultiBulkLength() will be called. */ 401 if (prepareClientToWrite(c) != REDIS_OK) return NULL; 402 listAddNodeTail(c->reply,createObject(REDIS_STRING,NULL)); 403 return listLast(c->reply); 404 } 405 406 /* Populate the length object and try gluing it to the next chunk. */ 407 void setDeferredMultiBulkLength(redisClient *c, void *node, long length) { 408 listNode *ln = (listNode*)node; 409 robj *len, *next; 410 411 /* Abort when *node is NULL (see addDeferredMultiBulkLength). */ 412 if (node == NULL) return; 413 414 len = listNodeValue(ln); 415 len->ptr = sdscatprintf(sdsempty(),"*%ld\r\n",length); 416 len->encoding = REDIS_ENCODING_RAW; /* in case it was an EMBSTR. */ 417 c->reply_bytes += zmalloc_size_sds(len->ptr); 418 if (ln->next != NULL) { 419 next = listNodeValue(ln->next); 420 421 /* Only glue when the next node is non-NULL (an sds in this case) */ 422 if (next->ptr != NULL) { 423 c->reply_bytes -= zmalloc_size_sds(len->ptr); 424 c->reply_bytes -= getStringObjectSdsUsedMemory(next); 425 len->ptr = sdscatlen(len->ptr,next->ptr,sdslen(next->ptr)); 426 c->reply_bytes += zmalloc_size_sds(len->ptr); 427 listDelNode(c->reply,ln->next); 428 } 429 } 430 asyncCloseClientOnOutputBufferLimitReached(c); 431 } 432 433 /* Add a double as a bulk reply */ 434 void addReplyDouble(redisClient *c, double d) { 435 char dbuf[128], sbuf[128]; 436 int dlen, slen; 437 if (isinf(d)) { 438 /* Libc in odd systems (Hi Solaris!) will format infinite in a 439 * different way, so better to handle it in an explicit way. */ 440 addReplyBulkCString(c, d > 0 ? "inf" : "-inf"); 441 } else { 442 dlen = snprintf(dbuf,sizeof(dbuf),"%.17g",d); 443 slen = snprintf(sbuf,sizeof(sbuf),"$%d\r\n%s\r\n",dlen,dbuf); 444 addReplyString(c,sbuf,slen); 445 } 446 } 447 448 /* Add a long long as integer reply or bulk len / multi bulk count. 449 * Basically this is used to output <prefix><long long><crlf>. */ 450 void addReplyLongLongWithPrefix(redisClient *c, long long ll, char prefix) { 451 char buf[128]; 452 int len; 453 454 /* Things like $3\r\n or *2\r\n are emitted very often by the protocol 455 * so we have a few shared objects to use if the integer is small 456 * like it is most of the times. */ 457 if (prefix == '*' && ll < REDIS_SHARED_BULKHDR_LEN) { 458 addReply(c,shared.mbulkhdr[ll]); 459 return; 460 } else if (prefix == '$' && ll < REDIS_SHARED_BULKHDR_LEN) { 461 addReply(c,shared.bulkhdr[ll]); 462 return; 463 } 464 465 buf[0] = prefix; 466 len = ll2string(buf+1,sizeof(buf)-1,ll); 467 buf[len+1] = '\r'; 468 buf[len+2] = '\n'; 469 addReplyString(c,buf,len+3); 470 } 471 472 void addReplyLongLong(redisClient *c, long long ll) { 473 if (ll == 0) 474 addReply(c,shared.czero); 475 else if (ll == 1) 476 addReply(c,shared.cone); 477 else 478 addReplyLongLongWithPrefix(c,ll,':'); 479 } 480 481 void addReplyMultiBulkLen(redisClient *c, long length) { 482 if (length < REDIS_SHARED_BULKHDR_LEN) 483 addReply(c,shared.mbulkhdr[length]); 484 else 485 addReplyLongLongWithPrefix(c,length,'*'); 486 } 487 488 /* Create the length prefix of a bulk reply, example: $2234 */ 489 void addReplyBulkLen(redisClient *c, robj *obj) { 490 size_t len; 491 492 if (sdsEncodedObject(obj)) { 493 len = sdslen(obj->ptr); 494 } else { 495 long n = (long)obj->ptr; 496 497 /* Compute how many bytes will take this integer as a radix 10 string */ 498 len = 1; 499 if (n < 0) { 500 len++; 501 n = -n; 502 } 503 while((n = n/10) != 0) { 504 len++; 505 } 506 } 507 508 if (len < REDIS_SHARED_BULKHDR_LEN) 509 addReply(c,shared.bulkhdr[len]); 510 else 511 addReplyLongLongWithPrefix(c,len,'$'); 512 } 513 514 /* Add a Redis Object as a bulk reply */ 515 void addReplyBulk(redisClient *c, robj *obj) { 516 addReplyBulkLen(c,obj); 517 addReply(c,obj); 518 addReply(c,shared.crlf); 519 } 520 521 /* Add a C buffer as bulk reply */ 522 void addReplyBulkCBuffer(redisClient *c, const void *p, size_t len) { 523 addReplyLongLongWithPrefix(c,len,'$'); 524 addReplyString(c,p,len); 525 addReply(c,shared.crlf); 526 } 527 528 /* Add sds to reply (takes ownership of sds and frees it) */ 529 void addReplyBulkSds(redisClient *c, sds s) { 530 addReplySds(c,sdscatfmt(sdsempty(),"$%u\r\n", 531 (unsigned long)sdslen(s))); 532 addReplySds(c,s); 533 addReply(c,shared.crlf); 534 } 535 536 /* Add a C nul term string as bulk reply */ 537 void addReplyBulkCString(redisClient *c, const char *s) { 538 if (s == NULL) { 539 addReply(c,shared.nullbulk); 540 } else { 541 addReplyBulkCBuffer(c,s,strlen(s)); 542 } 543 } 544 545 /* Add a long long as a bulk reply */ 546 void addReplyBulkLongLong(redisClient *c, long long ll) { 547 char buf[64]; 548 int len; 549 550 len = ll2string(buf,64,ll); 551 addReplyBulkCBuffer(c,buf,len); 552 } 553 554 /* Copy 'src' client output buffers into 'dst' client output buffers. 555 * The function takes care of freeing the old output buffers of the 556 * destination client. */ 557 void copyClientOutputBuffer(redisClient *dst, redisClient *src) { 558 listRelease(dst->reply); 559 dst->reply = listDup(src->reply); 560 memcpy(dst->buf,src->buf,src->bufpos); 561 dst->bufpos = src->bufpos; 562 dst->reply_bytes = src->reply_bytes; 563 } 564 565 #define MAX_ACCEPTS_PER_CALL 1000 566 static void acceptCommonHandler(int fd, int flags) { 567 redisClient *c; 568 if ((c = createClient(fd)) == NULL) { 569 redisLog(REDIS_WARNING, 570 "Error registering fd event for the new client: %s (fd=%d)", 571 strerror(errno),fd); 572 close(fd); /* May be already closed, just ignore errors */ 573 return; 574 } 575 /* If maxclient directive is set and this is one client more... close the 576 * connection. Note that we create the client instead to check before 577 * for this condition, since now the socket is already set in non-blocking 578 * mode and we can send an error for free using the Kernel I/O */ 579 if (listLength(server.clients) > server.maxclients) { 580 char *err = "-ERR max number of clients reached\r\n"; 581 582 /* That's a best effort error message, don't check write errors */ 583 if (write(c->fd,err,strlen(err)) == -1) { 584 /* Nothing to do, Just to avoid the warning... */ 585 } 586 server.stat_rejected_conn++; 587 freeClient(c); 588 return; 589 } 590 server.stat_numconnections++; 591 c->flags |= flags; 592 } 593 594 void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 595 int cport, cfd, max = MAX_ACCEPTS_PER_CALL; 596 char cip[REDIS_IP_STR_LEN]; 597 REDIS_NOTUSED(el); 598 REDIS_NOTUSED(mask); 599 REDIS_NOTUSED(privdata); 600 601 while(max--) { 602 cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport); 603 if (cfd == ANET_ERR) { 604 if (errno != EWOULDBLOCK) 605 redisLog(REDIS_WARNING, 606 "Accepting client connection: %s", server.neterr); 607 return; 608 } 609 redisLog(REDIS_VERBOSE,"Accepted %s:%d", cip, cport); 610 acceptCommonHandler(cfd,0); 611 } 612 } 613 614 void acceptUnixHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 615 int cfd, max = MAX_ACCEPTS_PER_CALL; 616 REDIS_NOTUSED(el); 617 REDIS_NOTUSED(mask); 618 REDIS_NOTUSED(privdata); 619 620 while(max--) { 621 cfd = anetUnixAccept(server.neterr, fd); 622 if (cfd == ANET_ERR) { 623 if (errno != EWOULDBLOCK) 624 redisLog(REDIS_WARNING, 625 "Accepting client connection: %s", server.neterr); 626 return; 627 } 628 redisLog(REDIS_VERBOSE,"Accepted connection to %s", server.unixsocket); 629 acceptCommonHandler(cfd,REDIS_UNIX_SOCKET); 630 } 631 } 632 633 static void freeClientArgv(redisClient *c) { 634 int j; 635 for (j = 0; j < c->argc; j++) 636 decrRefCount(c->argv[j]); 637 c->argc = 0; 638 c->cmd = NULL; 639 } 640 641 /* Close all the slaves connections. This is useful in chained replication 642 * when we resync with our own master and want to force all our slaves to 643 * resync with us as well. */ 644 void disconnectSlaves(void) { 645 while (listLength(server.slaves)) { 646 listNode *ln = listFirst(server.slaves); 647 freeClient((redisClient*)ln->value); 648 } 649 } 650 651 /* This function is called when the slave lose the connection with the 652 * master into an unexpected way. */ 653 void replicationHandleMasterDisconnection(void) { 654 server.master = NULL; 655 server.repl_state = REDIS_REPL_CONNECT; 656 server.repl_down_since = server.unixtime; 657 /* We lost connection with our master, force our slaves to resync 658 * with us as well to load the new data set. 659 * 660 * If server.masterhost is NULL the user called SLAVEOF NO ONE so 661 * slave resync is not needed. */ 662 if (server.masterhost != NULL) disconnectSlaves(); 663 } 664 665 void freeClient(redisClient *c) { 666 listNode *ln; 667 668 /* If this is marked as current client unset it */ 669 if (server.current_client == c) server.current_client = NULL; 670 671 /* If it is our master that's beging disconnected we should make sure 672 * to cache the state to try a partial resynchronization later. 673 * 674 * Note that before doing this we make sure that the client is not in 675 * some unexpected state, by checking its flags. */ 676 if (server.master && c->flags & REDIS_MASTER) { 677 redisLog(REDIS_WARNING,"Connection with master lost."); 678 if (!(c->flags & (REDIS_CLOSE_AFTER_REPLY| 679 REDIS_CLOSE_ASAP| 680 REDIS_BLOCKED| 681 REDIS_UNBLOCKED))) 682 { 683 replicationCacheMaster(c); 684 return; 685 } 686 } 687 688 /* Log link disconnection with slave */ 689 if ((c->flags & REDIS_SLAVE) && !(c->flags & REDIS_MONITOR)) { 690 redisLog(REDIS_WARNING,"Connection with slave %s lost.", 691 replicationGetSlaveName(c)); 692 } 693 694 /* Free the query buffer */ 695 sdsfree(c->querybuf); 696 c->querybuf = NULL; 697 698 /* Deallocate structures used to block on blocking ops. */ 699 if (c->flags & REDIS_BLOCKED) unblockClient(c); 700 dictRelease(c->bpop.keys); 701 702 /* UNWATCH all the keys */ 703 unwatchAllKeys(c); 704 listRelease(c->watched_keys); 705 706 /* Unsubscribe from all the pubsub channels */ 707 pubsubUnsubscribeAllChannels(c,0); 708 pubsubUnsubscribeAllPatterns(c,0); 709 dictRelease(c->pubsub_channels); 710 listRelease(c->pubsub_patterns); 711 712 /* Close socket, unregister events, and remove list of replies and 713 * accumulated arguments. */ 714 if (c->fd != -1) { 715 aeDeleteFileEvent(server.el,c->fd,AE_READABLE); 716 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 717 close(c->fd); 718 } 719 listRelease(c->reply); 720 freeClientArgv(c); 721 722 /* Remove from the list of clients */ 723 if (c->fd != -1) { 724 ln = listSearchKey(server.clients,c); 725 redisAssert(ln != NULL); 726 listDelNode(server.clients,ln); 727 } 728 729 /* When client was just unblocked because of a blocking operation, 730 * remove it from the list of unblocked clients. */ 731 if (c->flags & REDIS_UNBLOCKED) { 732 ln = listSearchKey(server.unblocked_clients,c); 733 redisAssert(ln != NULL); 734 listDelNode(server.unblocked_clients,ln); 735 } 736 737 /* Master/slave cleanup Case 1: 738 * we lost the connection with a slave. */ 739 if (c->flags & REDIS_SLAVE) { 740 if (c->replstate == REDIS_REPL_SEND_BULK) { 741 if (c->repldbfd != -1) close(c->repldbfd); 742 if (c->replpreamble) sdsfree(c->replpreamble); 743 } 744 list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves; 745 ln = listSearchKey(l,c); 746 redisAssert(ln != NULL); 747 listDelNode(l,ln); 748 /* We need to remember the time when we started to have zero 749 * attached slaves, as after some time we'll free the replication 750 * backlog. */ 751 if (c->flags & REDIS_SLAVE && listLength(server.slaves) == 0) 752 server.repl_no_slaves_since = server.unixtime; 753 refreshGoodSlavesCount(); 754 } 755 756 /* Master/slave cleanup Case 2: 757 * we lost the connection with the master. */ 758 if (c->flags & REDIS_MASTER) replicationHandleMasterDisconnection(); 759 760 /* If this client was scheduled for async freeing we need to remove it 761 * from the queue. */ 762 if (c->flags & REDIS_CLOSE_ASAP) { 763 ln = listSearchKey(server.clients_to_close,c); 764 redisAssert(ln != NULL); 765 listDelNode(server.clients_to_close,ln); 766 } 767 768 /* Release other dynamically allocated client structure fields, 769 * and finally release the client structure itself. */ 770 if (c->name) decrRefCount(c->name); 771 zfree(c->argv); 772 freeClientMultiState(c); 773 sdsfree(c->peerid); 774 zfree(c); 775 } 776 777 /* Schedule a client to free it at a safe time in the serverCron() function. 778 * This function is useful when we need to terminate a client but we are in 779 * a context where calling freeClient() is not possible, because the client 780 * should be valid for the continuation of the flow of the program. */ 781 void freeClientAsync(redisClient *c) { 782 if (c->flags & REDIS_CLOSE_ASAP) return; 783 c->flags |= REDIS_CLOSE_ASAP; 784 listAddNodeTail(server.clients_to_close,c); 785 } 786 787 void freeClientsInAsyncFreeQueue(void) { 788 while (listLength(server.clients_to_close)) { 789 listNode *ln = listFirst(server.clients_to_close); 790 redisClient *c = listNodeValue(ln); 791 792 c->flags &= ~REDIS_CLOSE_ASAP; 793 freeClient(c); 794 listDelNode(server.clients_to_close,ln); 795 } 796 } 797 798 void sendReplyToClient(aeEventLoop *el, int fd, void *privdata, int mask) { 799 redisClient *c = privdata; 800 ssize_t nwritten = 0, totwritten = 0; 801 size_t objlen; 802 size_t objmem; 803 robj *o; 804 REDIS_NOTUSED(el); 805 REDIS_NOTUSED(mask); 806 807 while(c->bufpos > 0 || listLength(c->reply)) { 808 if (c->bufpos > 0) { 809 nwritten = write(fd,c->buf+c->sentlen,c->bufpos-c->sentlen); 810 if (nwritten <= 0) break; 811 c->sentlen += nwritten; 812 totwritten += nwritten; 813 814 /* If the buffer was sent, set bufpos to zero to continue with 815 * the remainder of the reply. */ 816 if ((int)c->sentlen == c->bufpos) { 817 c->bufpos = 0; 818 c->sentlen = 0; 819 } 820 } else { 821 o = listNodeValue(listFirst(c->reply)); 822 objlen = sdslen(o->ptr); 823 objmem = getStringObjectSdsUsedMemory(o); 824 825 if (objlen == 0) { 826 listDelNode(c->reply,listFirst(c->reply)); 827 c->reply_bytes -= objmem; 828 continue; 829 } 830 831 nwritten = write(fd, ((char*)o->ptr)+c->sentlen,objlen-c->sentlen); 832 if (nwritten <= 0) break; 833 c->sentlen += nwritten; 834 totwritten += nwritten; 835 836 /* If we fully sent the object on head go to the next one */ 837 if (c->sentlen == objlen) { 838 listDelNode(c->reply,listFirst(c->reply)); 839 c->sentlen = 0; 840 c->reply_bytes -= objmem; 841 } 842 } 843 /* Note that we avoid to send more than REDIS_MAX_WRITE_PER_EVENT 844 * bytes, in a single threaded server it's a good idea to serve 845 * other clients as well, even if a very large request comes from 846 * super fast link that is always able to accept data (in real world 847 * scenario think about 'KEYS *' against the loopback interface). 848 * 849 * However if we are over the maxmemory limit we ignore that and 850 * just deliver as much data as it is possible to deliver. */ 851 server.stat_net_output_bytes += totwritten; 852 if (totwritten > REDIS_MAX_WRITE_PER_EVENT && 853 (server.maxmemory == 0 || 854 zmalloc_used_memory() < server.maxmemory)) break; 855 } 856 if (nwritten == -1) { 857 if (errno == EAGAIN) { 858 nwritten = 0; 859 } else { 860 redisLog(REDIS_VERBOSE, 861 "Error writing to client: %s", strerror(errno)); 862 freeClient(c); 863 return; 864 } 865 } 866 if (totwritten > 0) { 867 /* For clients representing masters we don't count sending data 868 * as an interaction, since we always send REPLCONF ACK commands 869 * that take some time to just fill the socket output buffer. 870 * We just rely on data / pings received for timeout detection. */ 871 if (!(c->flags & REDIS_MASTER)) c->lastinteraction = server.unixtime; 872 } 873 if (c->bufpos == 0 && listLength(c->reply) == 0) { 874 c->sentlen = 0; 875 aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE); 876 877 /* Close connection after entire reply has been sent. */ 878 if (c->flags & REDIS_CLOSE_AFTER_REPLY) freeClient(c); 879 } 880 } 881 882 /* resetClient prepare the client to process the next command */ 883 void resetClient(redisClient *c) { 884 redisCommandProc *prevcmd = c->cmd ? c->cmd->proc : NULL; 885 886 freeClientArgv(c); 887 c->reqtype = 0; 888 c->multibulklen = 0; 889 c->bulklen = -1; 890 /* We clear the ASKING flag as well if we are not inside a MULTI, and 891 * if what we just executed is not the ASKING command itself. */ 892 if (!(c->flags & REDIS_MULTI) && prevcmd != askingCommand) 893 c->flags &= (~REDIS_ASKING); 894 } 895 896 int processInlineBuffer(redisClient *c) { 897 char *newline; 898 int argc, j; 899 sds *argv, aux; 900 size_t querylen; 901 902 /* Search for end of line */ 903 newline = strchr(c->querybuf,'\n'); 904 905 /* Nothing to do without a \r\n */ 906 if (newline == NULL) { 907 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 908 addReplyError(c,"Protocol error: too big inline request"); 909 setProtocolError(c,0); 910 } 911 return REDIS_ERR; 912 } 913 914 /* Handle the \r\n case. */ 915 if (newline && newline != c->querybuf && *(newline-1) == '\r') 916 newline--; 917 918 /* Split the input buffer up to the \r\n */ 919 querylen = newline-(c->querybuf); 920 aux = sdsnewlen(c->querybuf,querylen); 921 argv = sdssplitargs(aux,&argc); 922 sdsfree(aux); 923 if (argv == NULL) { 924 addReplyError(c,"Protocol error: unbalanced quotes in request"); 925 setProtocolError(c,0); 926 return REDIS_ERR; 927 } 928 929 /* Newline from slaves can be used to refresh the last ACK time. 930 * This is useful for a slave to ping back while loading a big 931 * RDB file. */ 932 if (querylen == 0 && c->flags & REDIS_SLAVE) 933 c->repl_ack_time = server.unixtime; 934 935 /* Leave data after the first line of the query in the buffer */ 936 sdsrange(c->querybuf,querylen+2,-1); 937 938 /* Setup argv array on client structure */ 939 if (argc) { 940 if (c->argv) zfree(c->argv); 941 c->argv = zmalloc(sizeof(robj*)*argc); 942 } 943 944 /* Create redis objects for all arguments. */ 945 for (c->argc = 0, j = 0; j < argc; j++) { 946 if (sdslen(argv[j])) { 947 c->argv[c->argc] = createObject(REDIS_STRING,argv[j]); 948 c->argc++; 949 } else { 950 sdsfree(argv[j]); 951 } 952 } 953 zfree(argv); 954 return REDIS_OK; 955 } 956 957 /* Helper function. Trims query buffer to make the function that processes 958 * multi bulk requests idempotent. */ 959 static void setProtocolError(redisClient *c, int pos) { 960 if (server.verbosity >= REDIS_VERBOSE) { 961 sds client = catClientInfoString(sdsempty(),c); 962 redisLog(REDIS_VERBOSE, 963 "Protocol error from client: %s", client); 964 sdsfree(client); 965 } 966 c->flags |= REDIS_CLOSE_AFTER_REPLY; 967 sdsrange(c->querybuf,pos,-1); 968 } 969 970 int processMultibulkBuffer(redisClient *c) { 971 char *newline = NULL; 972 int pos = 0, ok; 973 long long ll; 974 975 if (c->multibulklen == 0) { 976 /* The client should have been reset */ 977 redisAssertWithInfo(c,NULL,c->argc == 0); 978 979 /* Multi bulk length cannot be read without a \r\n */ 980 newline = strchr(c->querybuf,'\r'); 981 if (newline == NULL) { 982 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 983 addReplyError(c,"Protocol error: too big mbulk count string"); 984 setProtocolError(c,0); 985 } 986 return REDIS_ERR; 987 } 988 989 /* Buffer should also contain \n */ 990 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 991 return REDIS_ERR; 992 993 /* We know for sure there is a whole line since newline != NULL, 994 * so go ahead and find out the multi bulk length. */ 995 redisAssertWithInfo(c,NULL,c->querybuf[0] == '*'); 996 ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll); 997 if (!ok || ll > 1024*1024) { 998 addReplyError(c,"Protocol error: invalid multibulk length"); 999 setProtocolError(c,pos); 1000 return REDIS_ERR; 1001 } 1002 1003 pos = (newline-c->querybuf)+2; 1004 if (ll <= 0) { 1005 sdsrange(c->querybuf,pos,-1); 1006 return REDIS_OK; 1007 } 1008 1009 c->multibulklen = ll; 1010 1011 /* Setup argv array on client structure */ 1012 if (c->argv) zfree(c->argv); 1013 c->argv = zmalloc(sizeof(robj*)*c->multibulklen); 1014 } 1015 1016 redisAssertWithInfo(c,NULL,c->multibulklen > 0); 1017 while(c->multibulklen) { 1018 /* Read bulk length if unknown */ 1019 if (c->bulklen == -1) { 1020 newline = strchr(c->querybuf+pos,'\r'); 1021 if (newline == NULL) { 1022 if (sdslen(c->querybuf) > REDIS_INLINE_MAX_SIZE) { 1023 addReplyError(c, 1024 "Protocol error: too big bulk count string"); 1025 setProtocolError(c,0); 1026 return REDIS_ERR; 1027 } 1028 break; 1029 } 1030 1031 /* Buffer should also contain \n */ 1032 if (newline-(c->querybuf) > ((signed)sdslen(c->querybuf)-2)) 1033 break; 1034 1035 if (c->querybuf[pos] != '$') { 1036 addReplyErrorFormat(c, 1037 "Protocol error: expected '$', got '%c'", 1038 c->querybuf[pos]); 1039 setProtocolError(c,pos); 1040 return REDIS_ERR; 1041 } 1042 1043 ok = string2ll(c->querybuf+pos+1,newline-(c->querybuf+pos+1),&ll); 1044 if (!ok || ll < 0 || ll > 512*1024*1024) { 1045 addReplyError(c,"Protocol error: invalid bulk length"); 1046 setProtocolError(c,pos); 1047 return REDIS_ERR; 1048 } 1049 1050 pos += newline-(c->querybuf+pos)+2; 1051 if (ll >= REDIS_MBULK_BIG_ARG) { 1052 size_t qblen; 1053 1054 /* If we are going to read a large object from network 1055 * try to make it likely that it will start at c->querybuf 1056 * boundary so that we can optimize object creation 1057 * avoiding a large copy of data. */ 1058 sdsrange(c->querybuf,pos,-1); 1059 pos = 0; 1060 qblen = sdslen(c->querybuf); 1061 /* Hint the sds library about the amount of bytes this string is 1062 * going to contain. */ 1063 if (qblen < (size_t)ll+2) 1064 c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2-qblen); 1065 } 1066 c->bulklen = ll; 1067 } 1068 1069 /* Read bulk argument */ 1070 if (sdslen(c->querybuf)-pos < (unsigned)(c->bulklen+2)) { 1071 /* Not enough data (+2 == trailing \r\n) */ 1072 break; 1073 } else { 1074 /* Optimization: if the buffer contains JUST our bulk element 1075 * instead of creating a new object by *copying* the sds we 1076 * just use the current sds string. */ 1077 if (pos == 0 && 1078 c->bulklen >= REDIS_MBULK_BIG_ARG && 1079 (signed) sdslen(c->querybuf) == c->bulklen+2) 1080 { 1081 c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf); 1082 sdsIncrLen(c->querybuf,-2); /* remove CRLF */ 1083 c->querybuf = sdsempty(); 1084 /* Assume that if we saw a fat argument we'll see another one 1085 * likely... */ 1086 c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2); 1087 pos = 0; 1088 } else { 1089 c->argv[c->argc++] = 1090 createStringObject(c->querybuf+pos,c->bulklen); 1091 pos += c->bulklen+2; 1092 } 1093 c->bulklen = -1; 1094 c->multibulklen--; 1095 } 1096 } 1097 1098 /* Trim to pos */ 1099 if (pos) sdsrange(c->querybuf,pos,-1); 1100 1101 /* We're done when c->multibulk == 0 */ 1102 if (c->multibulklen == 0) return REDIS_OK; 1103 1104 /* Still not read to process the command */ 1105 return REDIS_ERR; 1106 } 1107 1108 void processInputBuffer(redisClient *c) { 1109 server.current_client = c; 1110 /* Keep processing while there is something in the input buffer */ 1111 while(sdslen(c->querybuf)) { 1112 /* Return if clients are paused. */ 1113 if (!(c->flags & REDIS_SLAVE) && clientsArePaused()) break; 1114 1115 /* Immediately abort if the client is in the middle of something. */ 1116 if (c->flags & REDIS_BLOCKED) break; 1117 1118 /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is 1119 * written to the client. Make sure to not let the reply grow after 1120 * this flag has been set (i.e. don't process more commands). */ 1121 if (c->flags & REDIS_CLOSE_AFTER_REPLY) break; 1122 1123 /* Determine request type when unknown. */ 1124 if (!c->reqtype) { 1125 if (c->querybuf[0] == '*') { 1126 c->reqtype = REDIS_REQ_MULTIBULK; 1127 } else { 1128 c->reqtype = REDIS_REQ_INLINE; 1129 } 1130 } 1131 1132 if (c->reqtype == REDIS_REQ_INLINE) { 1133 if (processInlineBuffer(c) != REDIS_OK) break; 1134 } else if (c->reqtype == REDIS_REQ_MULTIBULK) { 1135 if (processMultibulkBuffer(c) != REDIS_OK) break; 1136 } else { 1137 redisPanic("Unknown request type"); 1138 } 1139 1140 /* Multibulk processing could see a <= 0 length. */ 1141 if (c->argc == 0) { 1142 resetClient(c); 1143 } else { 1144 /* Only reset the client when the command was executed. */ 1145 if (processCommand(c) == REDIS_OK) 1146 resetClient(c); 1147 } 1148 } 1149 server.current_client = NULL; 1150 } 1151 1152 void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { 1153 redisClient *c = (redisClient*) privdata; 1154 int nread, readlen; 1155 size_t qblen; 1156 REDIS_NOTUSED(el); 1157 REDIS_NOTUSED(mask); 1158 1159 readlen = REDIS_IOBUF_LEN; 1160 /* If this is a multi bulk request, and we are processing a bulk reply 1161 * that is large enough, try to maximize the probability that the query 1162 * buffer contains exactly the SDS string representing the object, even 1163 * at the risk of requiring more read(2) calls. This way the function 1164 * processMultiBulkBuffer() can avoid copying buffers to create the 1165 * Redis Object representing the argument. */ 1166 if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1 1167 && c->bulklen >= REDIS_MBULK_BIG_ARG) 1168 { 1169 int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf); 1170 1171 if (remaining < readlen) readlen = remaining; 1172 } 1173 1174 qblen = sdslen(c->querybuf); 1175 if (c->querybuf_peak < qblen) c->querybuf_peak = qblen; 1176 c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); 1177 nread = read(fd, c->querybuf+qblen, readlen); 1178 if (nread == -1) { 1179 if (errno == EAGAIN) { 1180 return; 1181 } else { 1182 redisLog(REDIS_VERBOSE, "Reading from client: %s",strerror(errno)); 1183 freeClient(c); 1184 return; 1185 } 1186 } else if (nread == 0) { 1187 redisLog(REDIS_VERBOSE, "Client closed connection"); 1188 freeClient(c); 1189 return; 1190 } 1191 1192 sdsIncrLen(c->querybuf,nread); 1193 c->lastinteraction = server.unixtime; 1194 if (c->flags & REDIS_MASTER) c->reploff += nread; 1195 server.stat_net_input_bytes += nread; 1196 if (sdslen(c->querybuf) > server.client_max_querybuf_len) { 1197 sds ci = catClientInfoString(sdsempty(),c), bytes = sdsempty(); 1198 1199 bytes = sdscatrepr(bytes,c->querybuf,64); 1200 redisLog(REDIS_WARNING,"Closing client that reached max query buffer length: %s (qbuf initial bytes: %s)", ci, bytes); 1201 sdsfree(ci); 1202 sdsfree(bytes); 1203 freeClient(c); 1204 return; 1205 } 1206 processInputBuffer(c); 1207 } 1208 1209 void getClientsMaxBuffers(unsigned long *longest_output_list, 1210 unsigned long *biggest_input_buffer) { 1211 redisClient *c; 1212 listNode *ln; 1213 listIter li; 1214 unsigned long lol = 0, bib = 0; 1215 1216 listRewind(server.clients,&li); 1217 while ((ln = listNext(&li)) != NULL) { 1218 c = listNodeValue(ln); 1219 1220 if (listLength(c->reply) > lol) lol = listLength(c->reply); 1221 if (sdslen(c->querybuf) > bib) bib = sdslen(c->querybuf); 1222 } 1223 *longest_output_list = lol; 1224 *biggest_input_buffer = bib; 1225 } 1226 1227 /* A Redis "Peer ID" is a colon separated ip:port pair. 1228 * For IPv4 it's in the form x.y.z.k:port, example: "127.0.0.1:1234". 1229 * For IPv6 addresses we use [] around the IP part, like in "[::1]:1234". 1230 * For Unix sockets we use path:0, like in "/tmp/redis:0". 1231 * 1232 * A Peer ID always fits inside a buffer of REDIS_PEER_ID_LEN bytes, including 1233 * the null term. 1234 * 1235 * On failure the function still populates 'peerid' with the "?:0" string 1236 * in case you want to relax error checking or need to display something 1237 * anyway (see anetPeerToString implementation for more info). */ 1238 void genClientPeerId(redisClient *client, char *peerid, 1239 size_t peerid_len) { 1240 if (client->flags & REDIS_UNIX_SOCKET) { 1241 /* Unix socket client. */ 1242 snprintf(peerid,peerid_len,"%s:0",server.unixsocket); 1243 } else { 1244 /* TCP client. */ 1245 anetFormatPeer(client->fd,peerid,peerid_len); 1246 } 1247 } 1248 1249 /* This function returns the client peer id, by creating and caching it 1250 * if client->peerid is NULL, otherwise returning the cached value. 1251 * The Peer ID never changes during the life of the client, however it 1252 * is expensive to compute. */ 1253 char *getClientPeerId(redisClient *c) { 1254 char peerid[REDIS_PEER_ID_LEN]; 1255 1256 if (c->peerid == NULL) { 1257 genClientPeerId(c,peerid,sizeof(peerid)); 1258 c->peerid = sdsnew(peerid); 1259 } 1260 return c->peerid; 1261 } 1262 1263 /* Concatenate a string representing the state of a client in an human 1264 * readable format, into the sds string 's'. */ 1265 sds catClientInfoString(sds s, redisClient *client) { 1266 char flags[16], events[3], *p; 1267 int emask; 1268 1269 p = flags; 1270 if (client->flags & REDIS_SLAVE) { 1271 if (client->flags & REDIS_MONITOR) 1272 *p++ = 'O'; 1273 else 1274 *p++ = 'S'; 1275 } 1276 if (client->flags & REDIS_MASTER) *p++ = 'M'; 1277 if (client->flags & REDIS_MULTI) *p++ = 'x'; 1278 if (client->flags & REDIS_BLOCKED) *p++ = 'b'; 1279 if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; 1280 if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; 1281 if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; 1282 if (client->flags & REDIS_CLOSE_ASAP) *p++ = 'A'; 1283 if (client->flags & REDIS_UNIX_SOCKET) *p++ = 'U'; 1284 if (client->flags & REDIS_READONLY) *p++ = 'r'; 1285 if (p == flags) *p++ = 'N'; 1286 *p++ = '\0'; 1287 1288 emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd); 1289 p = events; 1290 if (emask & AE_READABLE) *p++ = 'r'; 1291 if (emask & AE_WRITABLE) *p++ = 'w'; 1292 *p = '\0'; 1293 return sdscatfmt(s, 1294 "id=%U addr=%s fd=%i name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i multi=%i qbuf=%U qbuf-free=%U obl=%U oll=%U omem=%U events=%s cmd=%s", 1295 (unsigned long long) client->id, 1296 getClientPeerId(client), 1297 client->fd, 1298 client->name ? (char*)client->name->ptr : "", 1299 (long long)(server.unixtime - client->ctime), 1300 (long long)(server.unixtime - client->lastinteraction), 1301 flags, 1302 client->db->id, 1303 (int) dictSize(client->pubsub_channels), 1304 (int) listLength(client->pubsub_patterns), 1305 (client->flags & REDIS_MULTI) ? client->mstate.count : -1, 1306 (unsigned long long) sdslen(client->querybuf), 1307 (unsigned long long) sdsavail(client->querybuf), 1308 (unsigned long long) client->bufpos, 1309 (unsigned long long) listLength(client->reply), 1310 (unsigned long long) getClientOutputBufferMemoryUsage(client), 1311 events, 1312 client->lastcmd ? client->lastcmd->name : "NULL"); 1313 } 1314 1315 sds getAllClientsInfoString(void) { 1316 listNode *ln; 1317 listIter li; 1318 redisClient *client; 1319 sds o = sdsempty(); 1320 1321 o = sdsMakeRoomFor(o,200*listLength(server.clients)); 1322 listRewind(server.clients,&li); 1323 while ((ln = listNext(&li)) != NULL) { 1324 client = listNodeValue(ln); 1325 o = catClientInfoString(o,client); 1326 o = sdscatlen(o,"\n",1); 1327 } 1328 return o; 1329 } 1330 1331 void clientCommand(redisClient *c) { 1332 listNode *ln; 1333 listIter li; 1334 redisClient *client; 1335 1336 if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { 1337 /* CLIENT LIST */ 1338 sds o = getAllClientsInfoString(); 1339 addReplyBulkCBuffer(c,o,sdslen(o)); 1340 sdsfree(o); 1341 } else if (!strcasecmp(c->argv[1]->ptr,"kill")) { 1342 /* CLIENT KILL <ip:port> 1343 * CLIENT KILL <option> [value] ... <option> [value] */ 1344 char *addr = NULL; 1345 int type = -1; 1346 uint64_t id = 0; 1347 int skipme = 1; 1348 int killed = 0, close_this_client = 0; 1349 1350 if (c->argc == 3) { 1351 /* Old style syntax: CLIENT KILL <addr> */ 1352 addr = c->argv[2]->ptr; 1353 skipme = 0; /* With the old form, you can kill yourself. */ 1354 } else if (c->argc > 3) { 1355 int i = 2; /* Next option index. */ 1356 1357 /* New style syntax: parse options. */ 1358 while(i < c->argc) { 1359 int moreargs = c->argc > i+1; 1360 1361 if (!strcasecmp(c->argv[i]->ptr,"id") && moreargs) { 1362 long long tmp; 1363 1364 if (getLongLongFromObjectOrReply(c,c->argv[i+1],&tmp,NULL) 1365 != REDIS_OK) return; 1366 id = tmp; 1367 } else if (!strcasecmp(c->argv[i]->ptr,"type") && moreargs) { 1368 type = getClientTypeByName(c->argv[i+1]->ptr); 1369 if (type == -1) { 1370 addReplyErrorFormat(c,"Unknown client type '%s'", 1371 (char*) c->argv[i+1]->ptr); 1372 return; 1373 } 1374 } else if (!strcasecmp(c->argv[i]->ptr,"addr") && moreargs) { 1375 addr = c->argv[i+1]->ptr; 1376 } else if (!strcasecmp(c->argv[i]->ptr,"skipme") && moreargs) { 1377 if (!strcasecmp(c->argv[i+1]->ptr,"yes")) { 1378 skipme = 1; 1379 } else if (!strcasecmp(c->argv[i+1]->ptr,"no")) { 1380 skipme = 0; 1381 } else { 1382 addReply(c,shared.syntaxerr); 1383 return; 1384 } 1385 } else { 1386 addReply(c,shared.syntaxerr); 1387 return; 1388 } 1389 i += 2; 1390 } 1391 } else { 1392 addReply(c,shared.syntaxerr); 1393 return; 1394 } 1395 1396 /* Iterate clients killing all the matching clients. */ 1397 listRewind(server.clients,&li); 1398 while ((ln = listNext(&li)) != NULL) { 1399 client = listNodeValue(ln); 1400 if (addr && strcmp(getClientPeerId(client),addr) != 0) continue; 1401 if (type != -1 && 1402 (client->flags & REDIS_MASTER || 1403 getClientType(client) != type)) continue; 1404 if (id != 0 && client->id != id) continue; 1405 if (c == client && skipme) continue; 1406 1407 /* Kill it. */ 1408 if (c == client) { 1409 close_this_client = 1; 1410 } else { 1411 freeClient(client); 1412 } 1413 killed++; 1414 } 1415 1416 /* Reply according to old/new format. */ 1417 if (c->argc == 3) { 1418 if (killed == 0) 1419 addReplyError(c,"No such client"); 1420 else 1421 addReply(c,shared.ok); 1422 } else { 1423 addReplyLongLong(c,killed); 1424 } 1425 1426 /* If this client has to be closed, flag it as CLOSE_AFTER_REPLY 1427 * only after we queued the reply to its output buffers. */ 1428 if (close_this_client) c->flags |= REDIS_CLOSE_AFTER_REPLY; 1429 } else if (!strcasecmp(c->argv[1]->ptr,"setname") && c->argc == 3) { 1430 int j, len = sdslen(c->argv[2]->ptr); 1431 char *p = c->argv[2]->ptr; 1432 1433 /* Setting the client name to an empty string actually removes 1434 * the current name. */ 1435 if (len == 0) { 1436 if (c->name) decrRefCount(c->name); 1437 c->name = NULL; 1438 addReply(c,shared.ok); 1439 return; 1440 } 1441 1442 /* Otherwise check if the charset is ok. We need to do this otherwise 1443 * CLIENT LIST format will break. You should always be able to 1444 * split by space to get the different fields. */ 1445 for (j = 0; j < len; j++) { 1446 if (p[j] < '!' || p[j] > '~') { /* ASCII is assumed. */ 1447 addReplyError(c, 1448 "Client names cannot contain spaces, " 1449 "newlines or special characters."); 1450 return; 1451 } 1452 } 1453 if (c->name) decrRefCount(c->name); 1454 c->name = c->argv[2]; 1455 incrRefCount(c->name); 1456 addReply(c,shared.ok); 1457 } else if (!strcasecmp(c->argv[1]->ptr,"getname") && c->argc == 2) { 1458 if (c->name) 1459 addReplyBulk(c,c->name); 1460 else 1461 addReply(c,shared.nullbulk); 1462 } else if (!strcasecmp(c->argv[1]->ptr,"pause") && c->argc == 3) { 1463 long long duration; 1464 1465 if (getTimeoutFromObjectOrReply(c,c->argv[2],&duration,UNIT_MILLISECONDS) 1466 != REDIS_OK) return; 1467 pauseClients(duration); 1468 addReply(c,shared.ok); 1469 } else { 1470 addReplyError(c, "Syntax error, try CLIENT (LIST | KILL ip:port | GETNAME | SETNAME connection-name)"); 1471 } 1472 } 1473 1474 /* Rewrite the command vector of the client. All the new objects ref count 1475 * is incremented. The old command vector is freed, and the old objects 1476 * ref count is decremented. */ 1477 void rewriteClientCommandVector(redisClient *c, int argc, ...) { 1478 va_list ap; 1479 int j; 1480 robj **argv; /* The new argument vector */ 1481 1482 argv = zmalloc(sizeof(robj*)*argc); 1483 va_start(ap,argc); 1484 for (j = 0; j < argc; j++) { 1485 robj *a; 1486 1487 a = va_arg(ap, robj*); 1488 argv[j] = a; 1489 incrRefCount(a); 1490 } 1491 /* We free the objects in the original vector at the end, so we are 1492 * sure that if the same objects are reused in the new vector the 1493 * refcount gets incremented before it gets decremented. */ 1494 for (j = 0; j < c->argc; j++) decrRefCount(c->argv[j]); 1495 zfree(c->argv); 1496 /* Replace argv and argc with our new versions. */ 1497 c->argv = argv; 1498 c->argc = argc; 1499 c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr); 1500 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1501 va_end(ap); 1502 } 1503 1504 /* Rewrite a single item in the command vector. 1505 * The new val ref count is incremented, and the old decremented. */ 1506 void rewriteClientCommandArgument(redisClient *c, int i, robj *newval) { 1507 robj *oldval; 1508 1509 redisAssertWithInfo(c,NULL,i < c->argc); 1510 oldval = c->argv[i]; 1511 c->argv[i] = newval; 1512 incrRefCount(newval); 1513 decrRefCount(oldval); 1514 1515 /* If this is the command name make sure to fix c->cmd. */ 1516 if (i == 0) { 1517 c->cmd = lookupCommandOrOriginal(c->argv[0]->ptr); 1518 redisAssertWithInfo(c,NULL,c->cmd != NULL); 1519 } 1520 } 1521 1522 /* This function returns the number of bytes that Redis is virtually 1523 * using to store the reply still not read by the client. 1524 * It is "virtual" since the reply output list may contain objects that 1525 * are shared and are not really using additional memory. 1526 * 1527 * The function returns the total sum of the length of all the objects 1528 * stored in the output list, plus the memory used to allocate every 1529 * list node. The static reply buffer is not taken into account since it 1530 * is allocated anyway. 1531 * 1532 * Note: this function is very fast so can be called as many time as 1533 * the caller wishes. The main usage of this function currently is 1534 * enforcing the client output length limits. */ 1535 unsigned long getClientOutputBufferMemoryUsage(redisClient *c) { 1536 unsigned long list_item_size = sizeof(listNode)+sizeof(robj); 1537 1538 return c->reply_bytes + (list_item_size*listLength(c->reply)); 1539 } 1540 1541 /* Get the class of a client, used in order to enforce limits to different 1542 * classes of clients. 1543 * 1544 * The function will return one of the following: 1545 * REDIS_CLIENT_TYPE_NORMAL -> Normal client 1546 * REDIS_CLIENT_TYPE_SLAVE -> Slave or client executing MONITOR command 1547 * REDIS_CLIENT_TYPE_PUBSUB -> Client subscribed to Pub/Sub channels 1548 */ 1549 int getClientType(redisClient *c) { 1550 if ((c->flags & REDIS_SLAVE) && !(c->flags & REDIS_MONITOR)) 1551 return REDIS_CLIENT_TYPE_SLAVE; 1552 if (c->flags & REDIS_PUBSUB) 1553 return REDIS_CLIENT_TYPE_PUBSUB; 1554 return REDIS_CLIENT_TYPE_NORMAL; 1555 } 1556 1557 int getClientTypeByName(char *name) { 1558 if (!strcasecmp(name,"normal")) return REDIS_CLIENT_TYPE_NORMAL; 1559 else if (!strcasecmp(name,"slave")) return REDIS_CLIENT_TYPE_SLAVE; 1560 else if (!strcasecmp(name,"pubsub")) return REDIS_CLIENT_TYPE_PUBSUB; 1561 else return -1; 1562 } 1563 1564 char *getClientTypeName(int class) { 1565 switch(class) { 1566 case REDIS_CLIENT_TYPE_NORMAL: return "normal"; 1567 case REDIS_CLIENT_TYPE_SLAVE: return "slave"; 1568 case REDIS_CLIENT_TYPE_PUBSUB: return "pubsub"; 1569 default: return NULL; 1570 } 1571 } 1572 1573 /* The function checks if the client reached output buffer soft or hard 1574 * limit, and also update the state needed to check the soft limit as 1575 * a side effect. 1576 * 1577 * Return value: non-zero if the client reached the soft or the hard limit. 1578 * Otherwise zero is returned. */ 1579 int checkClientOutputBufferLimits(redisClient *c) { 1580 int soft = 0, hard = 0, class; 1581 unsigned long used_mem = getClientOutputBufferMemoryUsage(c); 1582 1583 class = getClientType(c); 1584 if (server.client_obuf_limits[class].hard_limit_bytes && 1585 used_mem >= server.client_obuf_limits[class].hard_limit_bytes) 1586 hard = 1; 1587 if (server.client_obuf_limits[class].soft_limit_bytes && 1588 used_mem >= server.client_obuf_limits[class].soft_limit_bytes) 1589 soft = 1; 1590 1591 /* We need to check if the soft limit is reached continuously for the 1592 * specified amount of seconds. */ 1593 if (soft) { 1594 if (c->obuf_soft_limit_reached_time == 0) { 1595 c->obuf_soft_limit_reached_time = server.unixtime; 1596 soft = 0; /* First time we see the soft limit reached */ 1597 } else { 1598 time_t elapsed = server.unixtime - c->obuf_soft_limit_reached_time; 1599 1600 if (elapsed <= 1601 server.client_obuf_limits[class].soft_limit_seconds) { 1602 soft = 0; /* The client still did not reached the max number of 1603 seconds for the soft limit to be considered 1604 reached. */ 1605 } 1606 } 1607 } else { 1608 c->obuf_soft_limit_reached_time = 0; 1609 } 1610 return soft || hard; 1611 } 1612 1613 /* Asynchronously close a client if soft or hard limit is reached on the 1614 * output buffer size. The caller can check if the client will be closed 1615 * checking if the client REDIS_CLOSE_ASAP flag is set. 1616 * 1617 * Note: we need to close the client asynchronously because this function is 1618 * called from contexts where the client can't be freed safely, i.e. from the 1619 * lower level functions pushing data inside the client output buffers. */ 1620 void asyncCloseClientOnOutputBufferLimitReached(redisClient *c) { 1621 redisAssert(c->reply_bytes < SIZE_MAX-(1024*64)); 1622 if (c->reply_bytes == 0 || c->flags & REDIS_CLOSE_ASAP) return; 1623 if (checkClientOutputBufferLimits(c)) { 1624 sds client = catClientInfoString(sdsempty(),c); 1625 1626 freeClientAsync(c); 1627 redisLog(REDIS_WARNING,"Client %s scheduled to be closed ASAP for overcoming of output buffer limits.", client); 1628 sdsfree(client); 1629 } 1630 } 1631 1632 /* Helper function used by freeMemoryIfNeeded() in order to flush slaves 1633 * output buffers without returning control to the event loop. */ 1634 void flushSlavesOutputBuffers(void) { 1635 listIter li; 1636 listNode *ln; 1637 1638 listRewind(server.slaves,&li); 1639 while((ln = listNext(&li))) { 1640 redisClient *slave = listNodeValue(ln); 1641 int events; 1642 1643 events = aeGetFileEvents(server.el,slave->fd); 1644 if (events & AE_WRITABLE && 1645 slave->replstate == REDIS_REPL_ONLINE && 1646 listLength(slave->reply)) 1647 { 1648 sendReplyToClient(server.el,slave->fd,slave,0); 1649 } 1650 } 1651 } 1652 1653 /* Pause clients up to the specified unixtime (in ms). While clients 1654 * are paused no command is processed from clients, so the data set can't 1655 * change during that time. 1656 * 1657 * However while this function pauses normal and Pub/Sub clients, slaves are 1658 * still served, so this function can be used on server upgrades where it is 1659 * required that slaves process the latest bytes from the replication stream 1660 * before being turned to masters. 1661 * 1662 * This function is also internally used by Redis Cluster for the manual 1663 * failover procedure implemented by CLUSTER FAILOVER. 1664 * 1665 * The function always succeed, even if there is already a pause in progress. 1666 * In such a case, the pause is extended if the duration is more than the 1667 * time left for the previous duration. However if the duration is smaller 1668 * than the time left for the previous pause, no change is made to the 1669 * left duration. */ 1670 void pauseClients(mstime_t end) { 1671 if (!server.clients_paused || end > server.clients_pause_end_time) 1672 server.clients_pause_end_time = end; 1673 server.clients_paused = 1; 1674 } 1675 1676 /* Return non-zero if clients are currently paused. As a side effect the 1677 * function checks if the pause time was reached and clear it. */ 1678 int clientsArePaused(void) { 1679 if (server.clients_paused && 1680 server.clients_pause_end_time < server.mstime) 1681 { 1682 listNode *ln; 1683 listIter li; 1684 redisClient *c; 1685 1686 server.clients_paused = 0; 1687 1688 /* Put all the clients in the unblocked clients queue in order to 1689 * force the re-processing of the input buffer if any. */ 1690 listRewind(server.clients,&li); 1691 while ((ln = listNext(&li)) != NULL) { 1692 c = listNodeValue(ln); 1693 1694 /* Don't touch slaves and blocked clients. The latter pending 1695 * requests be processed when unblocked. */ 1696 if (c->flags & (REDIS_SLAVE|REDIS_BLOCKED)) continue; 1697 c->flags |= REDIS_UNBLOCKED; 1698 listAddNodeTail(server.unblocked_clients,c); 1699 } 1700 } 1701 return server.clients_paused; 1702 } 1703 1704 /* This function is called by Redis in order to process a few events from 1705 * time to time while blocked into some not interruptible operation. 1706 * This allows to reply to clients with the -LOADING error while loading the 1707 * data set at startup or after a full resynchronization with the master 1708 * and so forth. 1709 * 1710 * It calls the event loop in order to process a few events. Specifically we 1711 * try to call the event loop for times as long as we receive acknowledge that 1712 * some event was processed, in order to go forward with the accept, read, 1713 * write, close sequence needed to serve a client. 1714 * 1715 * The function returns the total number of events processed. */ 1716 int processEventsWhileBlocked(void) { 1717 int iterations = 4; /* See the function top-comment. */ 1718 int count = 0; 1719 while (iterations--) { 1720 int events = aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT); 1721 if (!events) break; 1722 count += events; 1723 } 1724 return count; 1725 } 1726