X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/826b5beb9c04fef0d9942b8846989732b0d03ead..674df1eef514169b5bea0a4d4e841aabee0209c9:/src/networking.c diff --git a/src/networking.c b/src/networking.c index 4367e30b..c16e182f 100644 --- a/src/networking.c +++ b/src/networking.c @@ -36,7 +36,7 @@ redisClient *createClient(int fd) { c->reqtype = 0; c->argc = 0; c->argv = NULL; - c->cmd = NULL; + c->cmd = c->lastcmd = NULL; c->multibulklen = 0; c->bulklen = -1; c->sentlen = 0; @@ -419,6 +419,7 @@ static void acceptCommonHandler(int fd) { if (write(c->fd,err,strlen(err)) == -1) { /* Nothing to do, Just to avoid the warning... */ } + server.stat_rejected_conn++; freeClient(c); return; } @@ -767,19 +768,17 @@ int processMultibulkBuffer(redisClient *c) { } pos += newline-(c->querybuf+pos)+2; - #if 1 - if (ll > 4096) { + if (ll >= REDIS_MBULK_BIG_ARG) { /* If we are going to read a large object from network * try to make it likely that it will start at c->querybuf * boundary so that we can optimized object creation * avoiding a large copy of data. */ c->querybuf = sdsrange(c->querybuf,pos,-1); pos = 0; + /* Hint the sds library about the amount of bytes this string is + * going to contain. */ + c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2); } - #endif - /* Hint the sds library about the amount of bytes this string is - * going to contain. */ - if (ll > 4096) c->querybuf = sdsMakeRoomFor(c->querybuf,ll+2); c->bulklen = ll; } @@ -792,10 +791,9 @@ int processMultibulkBuffer(redisClient *c) { * instead of creating a new object by *copying* the sds we * just use the current sds string. */ if (pos == 0 && - /* sdslen(c->querybuf) > 4096 && */ + c->bulklen >= REDIS_MBULK_BIG_ARG && (signed) sdslen(c->querybuf) == c->bulklen+2) { - // printf("HERE (arg %d)\n",c->argc); c->argv[c->argc++] = createObject(REDIS_STRING,c->querybuf); sdsIncrLen(c->querybuf,-2); /* remove CRLF */ c->querybuf = sdsempty(); @@ -804,7 +802,6 @@ int processMultibulkBuffer(redisClient *c) { c->querybuf = sdsMakeRoomFor(c->querybuf,c->bulklen+2); pos = 0; } else { - // printf("NOT HERE (arg %d) (pos %d)\n",c->argc, pos); c->argv[c->argc++] = createStringObject(c->querybuf+pos,c->bulklen); pos += c->bulklen+2; @@ -877,15 +874,13 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { * at the risk of requring more read(2) calls. This way the function * processMultiBulkBuffer() can avoid copying buffers to create the * Redis Object representing the argument. */ - #if 1 if (c->reqtype == REDIS_REQ_MULTIBULK && c->multibulklen && c->bulklen != -1 - && c->bulklen > 4096) + && c->bulklen >= REDIS_MBULK_BIG_ARG) { int remaining = (unsigned)(c->bulklen+2)-sdslen(c->querybuf); if (remaining < readlen) readlen = remaining; } - #endif qblen = sdslen(c->querybuf); c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); @@ -909,6 +904,13 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { } else { return; } + if (sdslen(c->querybuf) > server.client_max_querybuf_len) { + sds ci = getClientInfoString(c); + redisLog(REDIS_WARNING,"Closing client that reached max query buffer length: %s", ci); + sdsfree(ci); + freeClient(c); + return; + } processInputBuffer(c); } @@ -930,46 +932,76 @@ void getClientsMaxBuffers(unsigned long *longest_output_list, *biggest_input_buffer = bib; } -void clientCommand(redisClient *c) { +/* Turn a Redis client into an sds string representing its state. */ +sds getClientInfoString(redisClient *client) { + char ip[32], flags[16], events[3], *p; + int port; + time_t now = time(NULL); + int emask; + + if (anetPeerToString(client->fd,ip,&port) == -1) { + ip[0] = '?'; + ip[1] = '\0'; + port = 0; + } + p = flags; + if (client->flags & REDIS_SLAVE) { + if (client->flags & REDIS_MONITOR) + *p++ = 'O'; + else + *p++ = 'S'; + } + if (client->flags & REDIS_MASTER) *p++ = 'M'; + if (client->flags & REDIS_MULTI) *p++ = 'x'; + if (client->flags & REDIS_BLOCKED) *p++ = 'b'; + if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; + if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; + if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; + if (p == flags) *p++ = 'N'; + *p++ = '\0'; + + emask = client->fd == -1 ? 0 : aeGetFileEvents(server.el,client->fd); + p = events; + if (emask & AE_READABLE) *p++ = 'r'; + if (emask & AE_WRITABLE) *p++ = 'w'; + *p = '\0'; + return sdscatprintf(sdsempty(), + "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d qbuf=%lu obl=%lu oll=%lu events=%s cmd=%s", + ip,port,client->fd, + (long)(now - client->lastinteraction), + flags, + client->db->id, + (int) dictSize(client->pubsub_channels), + (int) listLength(client->pubsub_patterns), + (unsigned long) sdslen(client->querybuf), + (unsigned long) client->bufpos, + (unsigned long) listLength(client->reply), + events, + client->lastcmd ? client->lastcmd->name : "NULL"); +} + +sds getAllClientsInfoString(void) { listNode *ln; listIter li; redisClient *client; + sds o = sdsempty(); - if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { - sds o = sdsempty(); - time_t now = time(NULL); + listRewind(server.clients,&li); + while ((ln = listNext(&li)) != NULL) { + client = listNodeValue(ln); + o = sdscatsds(o,getClientInfoString(client)); + o = sdscatlen(o,"\n",1); + } + return o; +} - listRewind(server.clients,&li); - while ((ln = listNext(&li)) != NULL) { - char ip[32], flags[16], *p; - int port; +void clientCommand(redisClient *c) { + listNode *ln; + listIter li; + redisClient *client; - client = listNodeValue(ln); - if (anetPeerToString(client->fd,ip,&port) == -1) continue; - p = flags; - if (client->flags & REDIS_SLAVE) { - if (client->flags & REDIS_MONITOR) - *p++ = 'O'; - else - *p++ = 'S'; - } - if (client->flags & REDIS_MASTER) *p++ = 'M'; - if (p == flags) *p++ = 'N'; - if (client->flags & REDIS_MULTI) *p++ = 'x'; - if (client->flags & REDIS_BLOCKED) *p++ = 'b'; - if (client->flags & REDIS_DIRTY_CAS) *p++ = 'd'; - if (client->flags & REDIS_CLOSE_AFTER_REPLY) *p++ = 'c'; - if (client->flags & REDIS_UNBLOCKED) *p++ = 'u'; - *p++ = '\0'; - o = sdscatprintf(o, - "addr=%s:%d fd=%d idle=%ld flags=%s db=%d sub=%d psub=%d\n", - ip,port,client->fd, - (long)(now - client->lastinteraction), - flags, - client->db->id, - (int) dictSize(client->pubsub_channels), - (int) listLength(client->pubsub_patterns)); - } + if (!strcasecmp(c->argv[1]->ptr,"list") && c->argc == 2) { + sds o = getAllClientsInfoString(); addReplyBulkCBuffer(c,o,sdslen(o)); sdsfree(o); } else if (!strcasecmp(c->argv[1]->ptr,"kill") && c->argc == 3) {