diff --git a/src/networking.c b/src/networking.c index 59f056436f1a9c33b8846526c0529273e563811f..458f4f3988019608b297d0f67e18c7698aa9d399 100644 --- a/src/networking.c +++ b/src/networking.c @@ -1126,14 +1126,42 @@ void getClientsMaxBuffers(unsigned long *longest_output_list, *biggest_input_buffer = bib; } +/* A Redis "Peer ID" is a colon separated ip:port pair. + * For IPv4 it's in the form x.y.z.k:pork, example: "127.0.0.1:1234". + * For IPv6 addresses we use [] around the IP part, like in "[::1]:1234". + * For Unix socekts we use path:0, like in "/tmp/redis:0". + * + * A Peer ID always fits inside a buffer of REDIS_PEER_ID_LEN bytes, including + * the null term. + * + * The function is always successful, but if the IP or port can't be extracted + * for some reason, "?" and "0" are used (this is the semantics of + * anetPeerToString() from anet.c). In practical terms this should never + * happen. */ +void getClientPeerId(redisClient *client, char *peerid, size_t peerid_len) { + char ip[REDIS_IP_STR_LEN]; + int port; + + if (client->flags & REDIS_UNIX_SOCKET) { + /* Unix socket client. */ + snprintf(peerid,peerid_len,"%s:0",server.unixsocket); + return; + } else { + /* TCP client. */ + anetPeerToString(client->fd,ip,sizeof(ip),&port); + if (strchr(ip,':')) + snprintf(peerid,peerid_len,"[%s]:%d",ip,port); + else + snprintf(peerid,peerid_len,"%s:%d",ip,port); + } +} + /* Turn a Redis client into an sds string representing its state. */ sds getClientInfoString(redisClient *client) { - char ip[REDIS_IP_STR_LEN], flags[16], events[3], *p; - int port = 0; /* initialized to zero for the unix socket case. */ + char peerid[REDIS_PEER_ID_LEN], flags[16], events[3], *p; int emask; - if (!(client->flags & REDIS_UNIX_SOCKET)) - anetPeerToString(client->fd,ip,sizeof(ip),&port); + getClientPeerId(client,peerid,sizeof(peerid)); p = flags; if (client->flags & REDIS_SLAVE) { if (client->flags & REDIS_MONITOR) @@ -1158,9 +1186,8 @@ sds getClientInfoString(redisClient *client) { if (emask & AE_WRITABLE) *p++ = 'w'; *p = '\0'; return sdscatprintf(sdsempty(), - "addr=%s:%d fd=%d name=%s age=%ld idle=%ld flags=%s db=%d sub=%d psub=%d multi=%d qbuf=%lu qbuf-free=%lu obl=%lu oll=%lu omem=%lu events=%s cmd=%s", - (client->flags & REDIS_UNIX_SOCKET) ? server.unixsocket : ip, - port, + "addr=%s fd=%d name=%s age=%ld idle=%ld flags=%s db=%d sub=%d psub=%d multi=%d qbuf=%lu qbuf-free=%lu obl=%lu oll=%lu omem=%lu events=%s cmd=%s", + peerid, client->fd, client->name ? (char*)client->name->ptr : "", (long)(server.unixtime - client->ctime), diff --git a/src/redis.h b/src/redis.h index 808bb9211bfb0b8b06027b61092a9e7a69f49998..901969d0d18f22a85ab817e1285b71701e394f58 100644 --- a/src/redis.h +++ b/src/redis.h @@ -121,6 +121,7 @@ #define REDIS_DEFAULT_MIN_SLAVES_TO_WRITE 0 #define REDIS_DEFAULT_MIN_SLAVES_MAX_LAG 10 #define REDIS_IP_STR_LEN INET6_ADDRSTRLEN +#define REDIS_PEER_ID_LEN (REDIS_IP_STR_LEN+32) /* Must be enough for ip:port */ #define REDIS_BINDADDR_MAX 16 /* Protocol and I/O related defines */ @@ -1072,6 +1073,7 @@ void copyClientOutputBuffer(redisClient *dst, redisClient *src); void *dupClientReplyValue(void *o); void getClientsMaxBuffers(unsigned long *longest_output_list, unsigned long *biggest_input_buffer); +void getClientPeerId(redisClient *client, char *peerid, size_t peerid_len); sds getClientInfoString(redisClient *client); sds getAllClientsInfoString(void); void rewriteClientCommandVector(redisClient *c, int argc, ...);