4 void *dupClientReplyValue(void *o
) { 
   5     incrRefCount((robj
*)o
); 
   9 int listMatchObjects(void *a
, void *b
) { 
  10     return equalStringObjects(a
,b
); 
  13 redisClient 
*createClient(int fd
) { 
  14     redisClient 
*c 
= zmalloc(sizeof(redisClient
)); 
  17     anetNonBlock(NULL
,fd
); 
  18     anetTcpNoDelay(NULL
,fd
); 
  20     if (aeCreateFileEvent(server
.el
,fd
,AE_READABLE
, 
  21         readQueryFromClient
, c
) == AE_ERR
) 
  30     c
->querybuf 
= sdsempty(); 
  38     c
->lastinteraction 
= time(NULL
); 
  40     c
->replstate 
= REDIS_REPL_NONE
; 
  41     c
->reply 
= listCreate(); 
  42     listSetFreeMethod(c
->reply
,decrRefCount
); 
  43     listSetDupMethod(c
->reply
,dupClientReplyValue
); 
  44     c
->blocking_keys 
= NULL
; 
  45     c
->blocking_keys_num 
= 0; 
  46     c
->io_keys 
= listCreate(); 
  47     c
->watched_keys 
= listCreate(); 
  48     listSetFreeMethod(c
->io_keys
,decrRefCount
); 
  49     c
->pubsub_channels 
= dictCreate(&setDictType
,NULL
); 
  50     c
->pubsub_patterns 
= listCreate(); 
  51     listSetFreeMethod(c
->pubsub_patterns
,decrRefCount
); 
  52     listSetMatchMethod(c
->pubsub_patterns
,listMatchObjects
); 
  53     listAddNodeTail(server
.clients
,c
); 
  54     initClientMultiState(c
); 
  58 /* Set the event loop to listen for write events on the client's socket. 
  59  * Typically gets called every time a reply is built. */ 
  60 int _installWriteEvent(redisClient 
*c
) { 
  61     /* When CLOSE_AFTER_REPLY is set, no more replies may be added! */ 
  62     redisAssert(!(c
->flags 
& REDIS_CLOSE_AFTER_REPLY
)); 
  64     if (c
->fd 
<= 0) return REDIS_ERR
; 
  65     if (c
->bufpos 
== 0 && listLength(c
->reply
) == 0 && 
  66         (c
->replstate 
== REDIS_REPL_NONE 
|| 
  67          c
->replstate 
== REDIS_REPL_ONLINE
) && 
  68         aeCreateFileEvent(server
.el
, c
->fd
, AE_WRITABLE
, 
  69         sendReplyToClient
, c
) == AE_ERR
) return REDIS_ERR
; 
  73 /* Create a duplicate of the last object in the reply list when 
  74  * it is not exclusively owned by the reply list. */ 
  75 robj 
*dupLastObjectIfNeeded(list 
*reply
) { 
  78     redisAssert(listLength(reply
) > 0); 
  80     cur 
= listNodeValue(ln
); 
  81     if (cur
->refcount 
> 1) { 
  82         new = dupStringObject(cur
); 
  84         listNodeValue(ln
) = new; 
  86     return listNodeValue(ln
); 
  89 int _addReplyToBuffer(redisClient 
*c
, char *s
, size_t len
) { 
  90     size_t available 
= sizeof(c
->buf
)-c
->bufpos
; 
  92     /* If there already are entries in the reply list, we cannot 
  93      * add anything more to the static buffer. */ 
  94     if (listLength(c
->reply
) > 0) return REDIS_ERR
; 
  96     /* Check that the buffer has enough space available for this string. */ 
  97     if (len 
> available
) return REDIS_ERR
; 
  99     memcpy(c
->buf
+c
->bufpos
,s
,len
); 
 104 void _addReplyObjectToList(redisClient 
*c
, robj 
*o
) { 
 106     if (listLength(c
->reply
) == 0) { 
 108         listAddNodeTail(c
->reply
,o
); 
 110         tail 
= listNodeValue(listLast(c
->reply
)); 
 112         /* Append to this object when possible. */ 
 113         if (tail
->ptr 
!= NULL 
&& 
 114             sdslen(tail
->ptr
)+sdslen(o
->ptr
) <= REDIS_REPLY_CHUNK_BYTES
) 
 116             tail 
= dupLastObjectIfNeeded(c
->reply
); 
 117             tail
->ptr 
= sdscatlen(tail
->ptr
,o
->ptr
,sdslen(o
->ptr
)); 
 120             listAddNodeTail(c
->reply
,o
); 
 125 /* This method takes responsibility over the sds. When it is no longer 
 126  * needed it will be free'd, otherwise it ends up in a robj. */ 
 127 void _addReplySdsToList(redisClient 
*c
, sds s
) { 
 129     if (listLength(c
->reply
) == 0) { 
 130         listAddNodeTail(c
->reply
,createObject(REDIS_STRING
,s
)); 
 132         tail 
= listNodeValue(listLast(c
->reply
)); 
 134         /* Append to this object when possible. */ 
 135         if (tail
->ptr 
!= NULL 
&& 
 136             sdslen(tail
->ptr
)+sdslen(s
) <= REDIS_REPLY_CHUNK_BYTES
) 
 138             tail 
= dupLastObjectIfNeeded(c
->reply
); 
 139             tail
->ptr 
= sdscatlen(tail
->ptr
,s
,sdslen(s
)); 
 142             listAddNodeTail(c
->reply
,createObject(REDIS_STRING
,s
)); 
 147 void _addReplyStringToList(redisClient 
*c
, char *s
, size_t len
) { 
 149     if (listLength(c
->reply
) == 0) { 
 150         listAddNodeTail(c
->reply
,createStringObject(s
,len
)); 
 152         tail 
= listNodeValue(listLast(c
->reply
)); 
 154         /* Append to this object when possible. */ 
 155         if (tail
->ptr 
!= NULL 
&& 
 156             sdslen(tail
->ptr
)+len 
<= REDIS_REPLY_CHUNK_BYTES
) 
 158             tail 
= dupLastObjectIfNeeded(c
->reply
); 
 159             tail
->ptr 
= sdscatlen(tail
->ptr
,s
,len
); 
 161             listAddNodeTail(c
->reply
,createStringObject(s
,len
)); 
 166 void addReply(redisClient 
*c
, robj 
*obj
) { 
 167     if (_installWriteEvent(c
) != REDIS_OK
) return; 
 168     redisAssert(!server
.vm_enabled 
|| obj
->storage 
== REDIS_VM_MEMORY
); 
 170     /* This is an important place where we can avoid copy-on-write 
 171      * when there is a saving child running, avoiding touching the 
 172      * refcount field of the object if it's not needed. 
 174      * If the encoding is RAW and there is room in the static buffer 
 175      * we'll be able to send the object to the client without 
 176      * messing with its page. */ 
 177     if (obj
->encoding 
== REDIS_ENCODING_RAW
) { 
 178         if (_addReplyToBuffer(c
,obj
->ptr
,sdslen(obj
->ptr
)) != REDIS_OK
) 
 179             _addReplyObjectToList(c
,obj
); 
 181         obj 
= getDecodedObject(obj
); 
 182         if (_addReplyToBuffer(c
,obj
->ptr
,sdslen(obj
->ptr
)) != REDIS_OK
) 
 183             _addReplyObjectToList(c
,obj
); 
 188 void addReplySds(redisClient 
*c
, sds s
) { 
 189     if (_installWriteEvent(c
) != REDIS_OK
) { 
 190         /* The caller expects the sds to be free'd. */ 
 194     if (_addReplyToBuffer(c
,s
,sdslen(s
)) == REDIS_OK
) { 
 197         /* This method free's the sds when it is no longer needed. */ 
 198         _addReplySdsToList(c
,s
); 
 202 void addReplyString(redisClient 
*c
, char *s
, size_t len
) { 
 203     if (_installWriteEvent(c
) != REDIS_OK
) return; 
 204     if (_addReplyToBuffer(c
,s
,len
) != REDIS_OK
) 
 205         _addReplyStringToList(c
,s
,len
); 
 208 void _addReplyError(redisClient 
*c
, char *s
, size_t len
) { 
 209     addReplyString(c
,"-ERR ",5); 
 210     addReplyString(c
,s
,len
); 
 211     addReplyString(c
,"\r\n",2); 
 214 void addReplyError(redisClient 
*c
, char *err
) { 
 215     _addReplyError(c
,err
,strlen(err
)); 
 218 void addReplyErrorFormat(redisClient 
*c
, const char *fmt
, ...) { 
 221     sds s 
= sdscatvprintf(sdsempty(),fmt
,ap
); 
 223     _addReplyError(c
,s
,sdslen(s
)); 
 227 void _addReplyStatus(redisClient 
*c
, char *s
, size_t len
) { 
 228     addReplyString(c
,"+",1); 
 229     addReplyString(c
,s
,len
); 
 230     addReplyString(c
,"\r\n",2); 
 233 void addReplyStatus(redisClient 
*c
, char *status
) { 
 234     _addReplyStatus(c
,status
,strlen(status
)); 
 237 void addReplyStatusFormat(redisClient 
*c
, const char *fmt
, ...) { 
 240     sds s 
= sdscatvprintf(sdsempty(),fmt
,ap
); 
 242     _addReplyStatus(c
,s
,sdslen(s
)); 
 246 /* Adds an empty object to the reply list that will contain the multi bulk 
 247  * length, which is not known when this function is called. */ 
 248 void *addDeferredMultiBulkLength(redisClient 
*c
) { 
 249     /* Note that we install the write event here even if the object is not 
 250      * ready to be sent, since we are sure that before returning to the 
 251      * event loop setDeferredMultiBulkLength() will be called. */ 
 252     if (_installWriteEvent(c
) != REDIS_OK
) return NULL
; 
 253     listAddNodeTail(c
->reply
,createObject(REDIS_STRING
,NULL
)); 
 254     return listLast(c
->reply
); 
 257 /* Populate the length object and try glueing it to the next chunk. */ 
 258 void setDeferredMultiBulkLength(redisClient 
*c
, void *node
, long length
) { 
 259     listNode 
*ln 
= (listNode
*)node
; 
 262     /* Abort when *node is NULL (see addDeferredMultiBulkLength). */ 
 263     if (node 
== NULL
) return; 
 265     len 
= listNodeValue(ln
); 
 266     len
->ptr 
= sdscatprintf(sdsempty(),"*%ld\r\n",length
); 
 267     if (ln
->next 
!= NULL
) { 
 268         next 
= listNodeValue(ln
->next
); 
 270         /* Only glue when the next node is non-NULL (an sds in this case) */ 
 271         if (next
->ptr 
!= NULL
) { 
 272             len
->ptr 
= sdscatlen(len
->ptr
,next
->ptr
,sdslen(next
->ptr
)); 
 273             listDelNode(c
->reply
,ln
->next
); 
 278 void addReplyDouble(redisClient 
*c
, double d
) { 
 279     char dbuf
[128], sbuf
[128]; 
 281     dlen 
= snprintf(dbuf
,sizeof(dbuf
),"%.17g",d
); 
 282     slen 
= snprintf(sbuf
,sizeof(sbuf
),"$%d\r\n%s\r\n",dlen
,dbuf
); 
 283     addReplyString(c
,sbuf
,slen
); 
 286 void _addReplyLongLong(redisClient 
*c
, long long ll
, char prefix
) { 
 290     len 
= ll2string(buf
+1,sizeof(buf
)-1,ll
); 
 293     addReplyString(c
,buf
,len
+3); 
 296 void addReplyLongLong(redisClient 
*c
, long long ll
) { 
 297     _addReplyLongLong(c
,ll
,':'); 
 300 void addReplyMultiBulkLen(redisClient 
*c
, long length
) { 
 301     _addReplyLongLong(c
,length
,'*'); 
 304 void addReplyBulkLen(redisClient 
*c
, robj 
*obj
) { 
 307     if (obj
->encoding 
== REDIS_ENCODING_RAW
) { 
 308         len 
= sdslen(obj
->ptr
); 
 310         long n 
= (long)obj
->ptr
; 
 312         /* Compute how many bytes will take this integer as a radix 10 string */ 
 318         while((n 
= n
/10) != 0) { 
 322     _addReplyLongLong(c
,len
,'$'); 
 325 void addReplyBulk(redisClient 
*c
, robj 
*obj
) { 
 326     addReplyBulkLen(c
,obj
); 
 328     addReply(c
,shared
.crlf
); 
 331 /* In the CONFIG command we need to add vanilla C string as bulk replies */ 
 332 void addReplyBulkCString(redisClient 
*c
, char *s
) { 
 334         addReply(c
,shared
.nullbulk
); 
 336         robj 
*o 
= createStringObject(s
,strlen(s
)); 
 342 static void acceptCommonHandler(int fd
) { 
 344     if ((c 
= createClient(fd
)) == NULL
) { 
 345         redisLog(REDIS_WARNING
,"Error allocating resoures for the client"); 
 346         close(fd
); /* May be already closed, just ingore errors */ 
 349     /* If maxclient directive is set and this is one client more... close the 
 350      * connection. Note that we create the client instead to check before 
 351      * for this condition, since now the socket is already set in nonblocking 
 352      * mode and we can send an error for free using the Kernel I/O */ 
 353     if (server
.maxclients 
&& listLength(server
.clients
) > server
.maxclients
) { 
 354         char *err 
= "-ERR max number of clients reached\r\n"; 
 356         /* That's a best effort error message, don't check write errors */ 
 357         if (write(c
->fd
,err
,strlen(err
)) == -1) { 
 358             /* Nothing to do, Just to avoid the warning... */ 
 363     server
.stat_numconnections
++; 
 366 void acceptTcpHandler(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
 371     REDIS_NOTUSED(privdata
); 
 373     cfd 
= anetTcpAccept(server
.neterr
, fd
, cip
, &cport
); 
 375         redisLog(REDIS_VERBOSE
,"Accepting client connection: %s", server
.neterr
); 
 378     redisLog(REDIS_VERBOSE
,"Accepted %s:%d", cip
, cport
); 
 379     acceptCommonHandler(cfd
); 
 382 void acceptUnixHandler(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
 386     REDIS_NOTUSED(privdata
); 
 388     cfd 
= anetUnixAccept(server
.neterr
, fd
); 
 390         redisLog(REDIS_VERBOSE
,"Accepting client connection: %s", server
.neterr
); 
 393     redisLog(REDIS_VERBOSE
,"Accepted connection to %s", server
.unixsocket
); 
 394     acceptCommonHandler(cfd
); 
 398 static void freeClientArgv(redisClient 
*c
) { 
 400     for (j 
= 0; j 
< c
->argc
; j
++) 
 401         decrRefCount(c
->argv
[j
]); 
 405 void freeClient(redisClient 
*c
) { 
 408     /* Note that if the client we are freeing is blocked into a blocking 
 409      * call, we have to set querybuf to NULL *before* to call 
 410      * unblockClientWaitingData() to avoid processInputBuffer() will get 
 411      * called. Also it is important to remove the file events after 
 412      * this, because this call adds the READABLE event. */ 
 413     sdsfree(c
->querybuf
); 
 415     if (c
->flags 
& REDIS_BLOCKED
) 
 416         unblockClientWaitingData(c
); 
 418     /* UNWATCH all the keys */ 
 420     listRelease(c
->watched_keys
); 
 421     /* Unsubscribe from all the pubsub channels */ 
 422     pubsubUnsubscribeAllChannels(c
,0); 
 423     pubsubUnsubscribeAllPatterns(c
,0); 
 424     dictRelease(c
->pubsub_channels
); 
 425     listRelease(c
->pubsub_patterns
); 
 426     /* Obvious cleanup */ 
 427     aeDeleteFileEvent(server
.el
,c
->fd
,AE_READABLE
); 
 428     aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
 429     listRelease(c
->reply
); 
 432     /* Remove from the list of clients */ 
 433     ln 
= listSearchKey(server
.clients
,c
); 
 434     redisAssert(ln 
!= NULL
); 
 435     listDelNode(server
.clients
,ln
); 
 436     /* Remove from the list of clients waiting for swapped keys, or ready 
 437      * to be restarted, but not yet woken up again. */ 
 438     if (c
->flags 
& REDIS_IO_WAIT
) { 
 439         redisAssert(server
.vm_enabled
); 
 440         if (listLength(c
->io_keys
) == 0) { 
 441             ln 
= listSearchKey(server
.io_ready_clients
,c
); 
 443             /* When this client is waiting to be woken up (REDIS_IO_WAIT), 
 444              * it should be present in the list io_ready_clients */ 
 445             redisAssert(ln 
!= NULL
); 
 446             listDelNode(server
.io_ready_clients
,ln
); 
 448             while (listLength(c
->io_keys
)) { 
 449                 ln 
= listFirst(c
->io_keys
); 
 450                 dontWaitForSwappedKey(c
,ln
->value
); 
 453         server
.vm_blocked_clients
--; 
 455     listRelease(c
->io_keys
); 
 456     /* Master/slave cleanup. 
 457      * Case 1: we lost the connection with a slave. */ 
 458     if (c
->flags 
& REDIS_SLAVE
) { 
 459         if (c
->replstate 
== REDIS_REPL_SEND_BULK 
&& c
->repldbfd 
!= -1) 
 461         list 
*l 
= (c
->flags 
& REDIS_MONITOR
) ? server
.monitors 
: server
.slaves
; 
 462         ln 
= listSearchKey(l
,c
); 
 463         redisAssert(ln 
!= NULL
); 
 467     /* Case 2: we lost the connection with the master. */ 
 468     if (c
->flags 
& REDIS_MASTER
) { 
 469         server
.master 
= NULL
; 
 471         server
.replstate 
= REDIS_REPL_CONNECT
; 
 472         /* Since we lost the connection with the master, we should also 
 473          * close the connection with all our slaves if we have any, so 
 474          * when we'll resync with the master the other slaves will sync again 
 475          * with us as well. Note that also when the slave is not connected 
 476          * to the master it will keep refusing connections by other slaves. */ 
 477         while (listLength(server
.slaves
)) { 
 478             ln 
= listFirst(server
.slaves
); 
 479             freeClient((redisClient
*)ln
->value
); 
 484     freeClientMultiState(c
); 
 488 void sendReplyToClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
 489     redisClient 
*c 
= privdata
; 
 490     int nwritten 
= 0, totwritten 
= 0, objlen
; 
 495     /* Use writev() if we have enough buffers to send */ 
 496     if (!server
.glueoutputbuf 
&& 
 497         listLength(c
->reply
) > REDIS_WRITEV_THRESHOLD 
&& 
 498         !(c
->flags 
& REDIS_MASTER
)) 
 500         sendReplyToClientWritev(el
, fd
, privdata
, mask
); 
 504     while(c
->bufpos 
> 0 || listLength(c
->reply
)) { 
 506             if (c
->flags 
& REDIS_MASTER
) { 
 507                 /* Don't reply to a master */ 
 508                 nwritten 
= c
->bufpos 
- c
->sentlen
; 
 510                 nwritten 
= write(fd
,c
->buf
+c
->sentlen
,c
->bufpos
-c
->sentlen
); 
 511                 if (nwritten 
<= 0) break; 
 513             c
->sentlen 
+= nwritten
; 
 514             totwritten 
+= nwritten
; 
 516             /* If the buffer was sent, set bufpos to zero to continue with 
 517              * the remainder of the reply. */ 
 518             if (c
->sentlen 
== c
->bufpos
) { 
 523             o 
= listNodeValue(listFirst(c
->reply
)); 
 524             objlen 
= sdslen(o
->ptr
); 
 527                 listDelNode(c
->reply
,listFirst(c
->reply
)); 
 531             if (c
->flags 
& REDIS_MASTER
) { 
 532                 /* Don't reply to a master */ 
 533                 nwritten 
= objlen 
- c
->sentlen
; 
 535                 nwritten 
= write(fd
, ((char*)o
->ptr
)+c
->sentlen
,objlen
-c
->sentlen
); 
 536                 if (nwritten 
<= 0) break; 
 538             c
->sentlen 
+= nwritten
; 
 539             totwritten 
+= nwritten
; 
 541             /* If we fully sent the object on head go to the next one */ 
 542             if (c
->sentlen 
== objlen
) { 
 543                 listDelNode(c
->reply
,listFirst(c
->reply
)); 
 547         /* Note that we avoid to send more thank REDIS_MAX_WRITE_PER_EVENT 
 548          * bytes, in a single threaded server it's a good idea to serve 
 549          * other clients as well, even if a very large request comes from 
 550          * super fast link that is always able to accept data (in real world 
 551          * scenario think about 'KEYS *' against the loopback interfae) */ 
 552         if (totwritten 
> REDIS_MAX_WRITE_PER_EVENT
) break; 
 554     if (nwritten 
== -1) { 
 555         if (errno 
== EAGAIN
) { 
 558             redisLog(REDIS_VERBOSE
, 
 559                 "Error writing to client: %s", strerror(errno
)); 
 564     if (totwritten 
> 0) c
->lastinteraction 
= time(NULL
); 
 565     if (listLength(c
->reply
) == 0) { 
 567         aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
 569         /* Close connection after entire reply has been sent. */ 
 570         if (c
->flags 
& REDIS_CLOSE_AFTER_REPLY
) freeClient(c
); 
 574 void sendReplyToClientWritev(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) 
 576     redisClient 
*c 
= privdata
; 
 577     int nwritten 
= 0, totwritten 
= 0, objlen
, willwrite
; 
 579     struct iovec iov
[REDIS_WRITEV_IOVEC_COUNT
]; 
 585     while (listLength(c
->reply
)) { 
 590         /* fill-in the iov[] array */ 
 591         for(node 
= listFirst(c
->reply
); node
; node 
= listNextNode(node
)) { 
 592             o 
= listNodeValue(node
); 
 593             objlen 
= sdslen(o
->ptr
); 
 595             if (totwritten 
+ objlen 
- offset 
> REDIS_MAX_WRITE_PER_EVENT
) 
 598             if(ion 
== REDIS_WRITEV_IOVEC_COUNT
) 
 599                 break; /* no more iovecs */ 
 601             iov
[ion
].iov_base 
= ((char*)o
->ptr
) + offset
; 
 602             iov
[ion
].iov_len 
= objlen 
- offset
; 
 603             willwrite 
+= objlen 
- offset
; 
 604             offset 
= 0; /* just for the first item */ 
 611         /* write all collected blocks at once */ 
 612         if((nwritten 
= writev(fd
, iov
, ion
)) < 0) { 
 613             if (errno 
!= EAGAIN
) { 
 614                 redisLog(REDIS_VERBOSE
, 
 615                          "Error writing to client: %s", strerror(errno
)); 
 622         totwritten 
+= nwritten
; 
 625         /* remove written robjs from c->reply */ 
 626         while (nwritten 
&& listLength(c
->reply
)) { 
 627             o 
= listNodeValue(listFirst(c
->reply
)); 
 628             objlen 
= sdslen(o
->ptr
); 
 630             if(nwritten 
>= objlen 
- offset
) { 
 631                 listDelNode(c
->reply
, listFirst(c
->reply
)); 
 632                 nwritten 
-= objlen 
- offset
; 
 636                 c
->sentlen 
+= nwritten
; 
 644         c
->lastinteraction 
= time(NULL
); 
 646     if (listLength(c
->reply
) == 0) { 
 648         aeDeleteFileEvent(server
.el
,c
->fd
,AE_WRITABLE
); 
 652 /* resetClient prepare the client to process the next command */ 
 653 void resetClient(redisClient 
*c
) { 
 660 void closeTimedoutClients(void) { 
 663     time_t now 
= time(NULL
); 
 666     listRewind(server
.clients
,&li
); 
 667     while ((ln 
= listNext(&li
)) != NULL
) { 
 668         c 
= listNodeValue(ln
); 
 669         if (server
.maxidletime 
&& 
 670             !(c
->flags 
& REDIS_SLAVE
) &&    /* no timeout for slaves */ 
 671             !(c
->flags 
& REDIS_MASTER
) &&   /* no timeout for masters */ 
 672             !(c
->flags 
& REDIS_BLOCKED
) &&  /* no timeout for BLPOP */ 
 673             dictSize(c
->pubsub_channels
) == 0 && /* no timeout for pubsub */ 
 674             listLength(c
->pubsub_patterns
) == 0 && 
 675             (now 
- c
->lastinteraction 
> server
.maxidletime
)) 
 677             redisLog(REDIS_VERBOSE
,"Closing idle client"); 
 679         } else if (c
->flags 
& REDIS_BLOCKED
) { 
 680             if (c
->blockingto 
!= 0 && c
->blockingto 
< now
) { 
 681                 addReply(c
,shared
.nullmultibulk
); 
 682                 unblockClientWaitingData(c
); 
 688 int processInlineBuffer(redisClient 
*c
) { 
 689     char *newline 
= strstr(c
->querybuf
,"\r\n"); 
 694     /* Nothing to do without a \r\n */ 
 698     /* Split the input buffer up to the \r\n */ 
 699     querylen 
= newline
-(c
->querybuf
); 
 700     argv 
= sdssplitlen(c
->querybuf
,querylen
," ",1,&argc
); 
 702     /* Leave data after the first line of the query in the buffer */ 
 703     c
->querybuf 
= sdsrange(c
->querybuf
,querylen
+2,-1); 
 705     /* Setup argv array on client structure */ 
 706     if (c
->argv
) zfree(c
->argv
); 
 707     c
->argv 
= zmalloc(sizeof(robj
*)*argc
); 
 709     /* Create redis objects for all arguments. */ 
 710     for (c
->argc 
= 0, j 
= 0; j 
< argc
; j
++) { 
 711         if (sdslen(argv
[j
])) { 
 712             c
->argv
[c
->argc
] = createObject(REDIS_STRING
,argv
[j
]); 
 722 /* Helper function. Trims query buffer to make the function that processes 
 723  * multi bulk requests idempotent. */ 
 724 static void setProtocolError(redisClient 
*c
, int pos
) { 
 725     c
->flags 
|= REDIS_CLOSE_AFTER_REPLY
; 
 726     c
->querybuf 
= sdsrange(c
->querybuf
,pos
,-1); 
 729 int processMultibulkBuffer(redisClient 
*c
) { 
 730     char *newline 
= NULL
; 
 735     if (c
->multibulklen 
== 0) { 
 736         /* The client should have been reset */ 
 737         redisAssert(c
->argc 
== 0); 
 739         /* Multi bulk length cannot be read without a \r\n */ 
 740         newline 
= strstr(c
->querybuf
,"\r\n"); 
 744         /* We know for sure there is a whole line since newline != NULL, 
 745          * so go ahead and find out the multi bulk length. */ 
 746         redisAssert(c
->querybuf
[0] == '*'); 
 747         c
->multibulklen 
= strtol(c
->querybuf
+1,&eptr
,10); 
 748         pos 
= (newline
-c
->querybuf
)+2; 
 749         if (c
->multibulklen 
<= 0) { 
 750             c
->querybuf 
= sdsrange(c
->querybuf
,pos
,-1); 
 752         } else if (c
->multibulklen 
> 1024*1024) { 
 753             addReplyError(c
,"Protocol error: invalid multibulk length"); 
 754             setProtocolError(c
,pos
); 
 758         /* Setup argv array on client structure */ 
 759         if (c
->argv
) zfree(c
->argv
); 
 760         c
->argv 
= zmalloc(sizeof(robj
*)*c
->multibulklen
); 
 762         /* Search new newline */ 
 763         newline 
= strstr(c
->querybuf
+pos
,"\r\n"); 
 766     redisAssert(c
->multibulklen 
> 0); 
 767     while(c
->multibulklen
) { 
 768         /* Read bulk length if unknown */ 
 769         if (c
->bulklen 
== -1) { 
 770             newline 
= strstr(c
->querybuf
+pos
,"\r\n"); 
 771             if (newline 
!= NULL
) { 
 772                 if (c
->querybuf
[pos
] != '$') { 
 773                     addReplyErrorFormat(c
, 
 774                         "Protocol error: expected '$', got '%c'", 
 776                     setProtocolError(c
,pos
); 
 780                 bulklen 
= strtol(c
->querybuf
+pos
+1,&eptr
,10); 
 781                 tolerr 
= (eptr
[0] != '\r'); 
 782                 if (tolerr 
|| bulklen 
== LONG_MIN 
|| bulklen 
== LONG_MAX 
|| 
 783                     bulklen 
< 0 || bulklen 
> 1024*1024*1024) 
 785                     addReplyError(c
,"Protocol error: invalid bulk length"); 
 786                     setProtocolError(c
,pos
); 
 789                 pos 
+= eptr
-(c
->querybuf
+pos
)+2; 
 790                 c
->bulklen 
= bulklen
; 
 792                 /* No newline in current buffer, so wait for more data */ 
 797         /* Read bulk argument */ 
 798         if (sdslen(c
->querybuf
)-pos 
< (unsigned)(c
->bulklen
+2)) { 
 799             /* Not enough data (+2 == trailing \r\n) */ 
 802             c
->argv
[c
->argc
++] = createStringObject(c
->querybuf
+pos
,c
->bulklen
); 
 810     c
->querybuf 
= sdsrange(c
->querybuf
,pos
,-1); 
 812     /* We're done when c->multibulk == 0 */ 
 813     if (c
->multibulklen 
== 0) { 
 819 void processInputBuffer(redisClient 
*c
) { 
 820     /* Keep processing while there is something in the input buffer */ 
 821     while(sdslen(c
->querybuf
)) { 
 822         /* Immediately abort if the client is in the middle of something. */ 
 823         if (c
->flags 
& REDIS_BLOCKED 
|| c
->flags 
& REDIS_IO_WAIT
) return; 
 825         /* REDIS_CLOSE_AFTER_REPLY closes the connection once the reply is 
 826          * written to the client. Make sure to not let the reply grow after 
 827          * this flag has been set (i.e. don't process more commands). */ 
 828         if (c
->flags 
& REDIS_CLOSE_AFTER_REPLY
) return; 
 830         /* Determine request type when unknown. */ 
 832             if (c
->querybuf
[0] == '*') { 
 833                 c
->reqtype 
= REDIS_REQ_MULTIBULK
; 
 835                 c
->reqtype 
= REDIS_REQ_INLINE
; 
 839         if (c
->reqtype 
== REDIS_REQ_INLINE
) { 
 840             if (processInlineBuffer(c
) != REDIS_OK
) break; 
 841         } else if (c
->reqtype 
== REDIS_REQ_MULTIBULK
) { 
 842             if (processMultibulkBuffer(c
) != REDIS_OK
) break; 
 844             redisPanic("Unknown request type"); 
 847         /* Multibulk processing could see a <= 0 length. */ 
 851             /* Only reset the client when the command was executed. */ 
 852             if (processCommand(c
) == REDIS_OK
) 
 858 void readQueryFromClient(aeEventLoop 
*el
, int fd
, void *privdata
, int mask
) { 
 859     redisClient 
*c 
= (redisClient
*) privdata
; 
 860     char buf
[REDIS_IOBUF_LEN
]; 
 865     nread 
= read(fd
, buf
, REDIS_IOBUF_LEN
); 
 867         if (errno 
== EAGAIN
) { 
 870             redisLog(REDIS_VERBOSE
, "Reading from client: %s",strerror(errno
)); 
 874     } else if (nread 
== 0) { 
 875         redisLog(REDIS_VERBOSE
, "Client closed connection"); 
 880         c
->querybuf 
= sdscatlen(c
->querybuf
,buf
,nread
); 
 881         c
->lastinteraction 
= time(NULL
); 
 885     processInputBuffer(c
);