From 90b0d66cce97aaac3a6437ac77b5dad9064136d1 Mon Sep 17 00:00:00 2001 From: antirez Date: Thu, 4 Jul 2013 18:50:15 +0200 Subject: [PATCH] Ability to bind multiple addresses. --- src/config.c | 41 +++++++++++++++++++++++++++++++++++++---- src/redis.c | 6 +++--- src/redis.h | 4 +++- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/config.c b/src/config.c index 01bcafb7..78b458dc 100644 --- a/src/config.c +++ b/src/config.c @@ -125,8 +125,15 @@ void loadServerConfigFromString(char *config) { if (server.port < 0 || server.port > 65535) { err = "Invalid port"; goto loaderr; } - } else if (!strcasecmp(argv[0],"bind") && argc == 2) { - server.bindaddr = zstrdup(argv[1]); + } else if (!strcasecmp(argv[0],"bind") && argc >= 2) { + int j, addresses = argc-1; + + if (addresses > REDIS_BINDADDR_MAX) { + err = "Too many bind addresses specified"; goto loaderr; + } + for (j = 0; j < addresses; j++) + server.bindaddr[j] = zstrdup(argv[j+1]); + server.bindaddr_count = addresses; } else if (!strcasecmp(argv[0],"unixsocket") && argc == 2) { server.unixsocket = zstrdup(argv[1]); } else if (!strcasecmp(argv[0],"unixsocketperm") && argc == 2) { @@ -917,7 +924,6 @@ void configGetCommand(redisClient *c) { config_get_string_field("dbfilename",server.rdb_filename); config_get_string_field("requirepass",server.requirepass); config_get_string_field("masterauth",server.masterauth); - config_get_string_field("bind",server.bindaddr); config_get_string_field("unixsocket",server.unixsocket); config_get_string_field("logfile",server.logfile); config_get_string_field("pidfile",server.pidfile); @@ -1104,6 +1110,14 @@ void configGetCommand(redisClient *c) { decrRefCount(flagsobj); matches++; } + if (stringmatch(pattern,"bind",0)) { + sds aux = sdsjoin(server.bindaddr,server.bindaddr_count," "); + + addReplyBulkCString(c,"bind"); + addReplyBulkCString(c,aux); + sdsfree(aux); + matches++; + } setDeferredMultiBulkLength(c,replylen,matches*2); } @@ -1495,6 +1509,25 @@ void rewriteConfigClientoutputbufferlimitOption(struct rewriteConfigState *state } } +/* Rewrite the bind option. */ +void rewriteConfigBindOption(struct rewriteConfigState *state) { + int force = 1; + sds line, addresses; + char *option = "bind"; + + /* Nothing to rewrite if we don't have bind addresses. */ + if (server.bindaddr_count == 0) return; + + /* Rewrite as bind ... */ + addresses = sdsjoin(server.bindaddr,server.bindaddr_count," "); + line = sdsnew(option); + line = sdscatlen(line, " ", 1); + line = sdscatsds(line, addresses); + sdsfree(addresses); + + rewriteConfigRewriteLine(state,option,line,force); +} + /* Glue together the configuration lines in the current configuration * rewrite state into a single string, stripping multiple empty lines. */ sds rewriteConfigGetContentFromState(struct rewriteConfigState *state) { @@ -1630,7 +1663,7 @@ int rewriteConfig(char *path) { rewriteConfigYesNoOption(state,"daemonize",server.daemonize,0); rewriteConfigStringOption(state,"pidfile",server.pidfile,REDIS_DEFAULT_PID_FILE); rewriteConfigNumericalOption(state,"port",server.port,REDIS_SERVERPORT); - rewriteConfigStringOption(state,"bind",server.bindaddr,NULL); + rewriteConfigBindOption(state); rewriteConfigStringOption(state,"unixsocket",server.unixsocket,NULL); rewriteConfigOctalOption(state,"unixsocketperm",server.unixsocketperm,REDIS_DEFAULT_UNIX_SOCKET_PERM); rewriteConfigNumericalOption(state,"timeout",server.maxidletime,REDIS_MAXIDLETIME); diff --git a/src/redis.c b/src/redis.c index 81601273..a78ecfb5 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1221,7 +1221,7 @@ void initServerConfig() { server.runid[REDIS_RUN_ID_SIZE] = '\0'; server.arch_bits = (sizeof(long) == 8) ? 64 : 32; server.port = REDIS_SERVERPORT; - server.bindaddr = NULL; + server.bindaddr_count = 0; server.unixsocket = NULL; server.unixsocketperm = REDIS_DEFAULT_UNIX_SOCKET_PERM; server.ipfd = -1; @@ -1426,7 +1426,7 @@ void initServer() { server.db = zmalloc(sizeof(redisDb)*server.dbnum); if (server.port != 0) { - server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr); + server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr,server.bindaddr_count); if (server.ipfd == ANET_ERR) { redisLog(REDIS_WARNING, "Opening port %d: %s", server.port, server.neterr); @@ -2837,7 +2837,7 @@ void redisSetProcTitle(char *title) { #ifdef USE_SETPROCTITLE setproctitle("%s %s:%d", title, - server.bindaddr ? server.bindaddr : "*", + server.bindaddr_count ? server.bindaddr[0] : "*", server.port); #else REDIS_NOTUSED(title); diff --git a/src/redis.h b/src/redis.h index dade5e2a..1df4084e 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 16 +#define REDIS_BINDADDR_MAX 16 /* Protocol and I/O related defines */ #define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */ @@ -730,7 +731,8 @@ struct redisServer { int sentinel_mode; /* True if this instance is a Sentinel. */ /* Networking */ int port; /* TCP listening port */ - char *bindaddr; /* Bind address or NULL */ + char *bindaddr[REDIS_BINDADDR_MAX]; /* Addresses we should bind to */ + int bindaddr_count; /* Number of addresses in server.bindaddr[] */ char *unixsocket; /* UNIX socket path */ mode_t unixsocketperm; /* UNIX socket permission */ int ipfd; /* TCP socket file descriptor */