summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhenwei pi <pizhenwei@bytedance.com>2022-08-22 15:09:59 +0800
committerzhenwei pi <pizhenwei@bytedance.com>2022-08-22 15:09:59 +0800
commit8234a5123d8727a0b72c7b1a2524edd113ffe016 (patch)
tree1418f61000d9be9a0c7d2d616be02b7cd346ae78
parentbff7ecc7864716c14fbb399f19acaee364975b29 (diff)
downloadredis-8234a5123d8727a0b72c7b1a2524edd113ffe016.tar.gz
Introduce connection layer framework
Use connTypeRegister() to register a connection type into redis, and query connection by connectionByType() via type. With this change, we can hide TLS specified methods into connection type: - void tlsInit(void); - void tlsCleanup(void); - int tlsConfigure(redisTLSContextConfig *ctx_config); - int isTlsConfigured(void); Merge isTlsConfigured & tlsConfigure, use an argument *reconfigure* to distinguish: tlsConfigure(&server.tls_ctx_config) -> onnTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 1) isTlsConfigured() && tlsConfigure(&server.tls_ctx_config) -> connTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 0) Finally, we can remove USE_OPENSSL from config.c. If redis is built without TLS, and still run redis with TLS, then redis reports: # Missing implement of connection type 1 # Failed to configure TLS. Check logs for more info. The log can be optimised, let's leave it in the future. Maybe we can use connection type as a string. Although uninitialized fields of a static struct are zero, we still set them as NULL explicitly in socket.c, let them clear to read & maintain: .init = NULL, .cleanup = NULL, .configure = NULL, Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
-rw-r--r--src/Makefile2
-rw-r--r--src/config.c10
-rw-r--r--src/connection.c102
-rw-r--r--src/connection.h30
-rw-r--r--src/sentinel.c2
-rw-r--r--src/server.c4
-rw-r--r--src/server.h6
-rw-r--r--src/socket.c9
-rw-r--r--src/tls.c40
9 files changed, 169 insertions, 36 deletions
diff --git a/src/Makefile b/src/Makefile
index ca08f5b2e..f5736514e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -316,7 +316,7 @@ endif
REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX)
-REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o
+REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o
REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o redisassert.o crcspeed.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o
REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX)
diff --git a/src/config.c b/src/config.c
index f98225cbe..7b8c4b75c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -30,6 +30,7 @@
#include "server.h"
#include "cluster.h"
+#include "connection.h"
#include <fcntl.h>
#include <sys/stat.h>
@@ -2571,13 +2572,12 @@ int updateClusterHostname(const char **err) {
return 1;
}
-#ifdef USE_OPENSSL
static int applyTlsCfg(const char **err) {
UNUSED(err);
/* If TLS is enabled, try to configure OpenSSL. */
if ((server.tls_port || server.tls_replication || server.tls_cluster)
- && tlsConfigure(&server.tls_ctx_config) == C_ERR) {
+ && connTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 1) == C_ERR) {
*err = "Unable to update TLS configuration. Check server logs.";
return 0;
}
@@ -2586,7 +2586,7 @@ static int applyTlsCfg(const char **err) {
static int applyTLSPort(const char **err) {
/* Configure TLS in case it wasn't enabled */
- if (!isTlsConfigured() && tlsConfigure(&server.tls_ctx_config) == C_ERR) {
+ if (connTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 0) == C_ERR) {
*err = "Unable to update TLS configuration. Check server logs.";
return 0;
}
@@ -2599,8 +2599,6 @@ static int applyTLSPort(const char **err) {
return 1;
}
-#endif /* USE_OPENSSL */
-
static int setConfigDirOption(standardConfig *config, sds *argv, int argc, const char **err) {
UNUSED(config);
if (argc != 1) {
@@ -3109,7 +3107,6 @@ standardConfig static_configs[] = {
createOffTConfig("auto-aof-rewrite-min-size", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.aof_rewrite_min_size, 64*1024*1024, MEMORY_CONFIG, NULL, NULL),
createOffTConfig("loading-process-events-interval-bytes", NULL, MODIFIABLE_CONFIG | HIDDEN_CONFIG, 1024, INT_MAX, server.loading_process_events_interval_bytes, 1024*1024*2, INTEGER_CONFIG, NULL, NULL),
-#ifdef USE_OPENSSL
createIntConfig("tls-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.tls_port, 0, INTEGER_CONFIG, NULL, applyTLSPort), /* TCP port. */
createIntConfig("tls-session-cache-size", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_size, 20*1024, INTEGER_CONFIG, NULL, applyTlsCfg),
createIntConfig("tls-session-cache-timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.tls_ctx_config.session_cache_timeout, 300, INTEGER_CONFIG, NULL, applyTlsCfg),
@@ -3130,7 +3127,6 @@ standardConfig static_configs[] = {
createStringConfig("tls-protocols", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.protocols, NULL, NULL, applyTlsCfg),
createStringConfig("tls-ciphers", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ciphers, NULL, NULL, applyTlsCfg),
createStringConfig("tls-ciphersuites", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ciphersuites, NULL, NULL, applyTlsCfg),
-#endif
/* Special configs */
createSpecialConfig("dir", NULL, MODIFIABLE_CONFIG | PROTECTED_CONFIG | DENY_LOADING_CONFIG, setConfigDirOption, getConfigDirOption, rewriteConfigDirOption, NULL),
diff --git a/src/connection.c b/src/connection.c
new file mode 100644
index 000000000..958c9b818
--- /dev/null
+++ b/src/connection.c
@@ -0,0 +1,102 @@
+/* ==========================================================================
+ * connection.c - connection layer framework
+ * --------------------------------------------------------------------------
+ * Copyright (C) 2022 zhenwei pi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ==========================================================================
+ */
+
+#include "server.h"
+#include "connection.h"
+
+static ConnectionType *connTypes[CONN_TYPE_MAX];
+
+int connTypeRegister(ConnectionType *ct) {
+ int type = ct->get_type(NULL);
+
+ /* unknown connection type as a fatal error */
+ if (type >= CONN_TYPE_MAX) {
+ serverPanic("Unsupported connection type %d", type);
+ }
+
+ if (connTypes[type] == ct) {
+ serverLog(LL_WARNING, "Connection type %d already registered", type);
+ return C_OK;
+ }
+
+ serverLog(LL_VERBOSE, "Connection type %d registered", type);
+ connTypes[type] = ct;
+
+ if (ct->init) {
+ ct->init();
+ }
+
+ return C_OK;
+}
+
+int connTypeInitialize() {
+ /* currently socket connection type is necessary */
+ serverAssert(RedisRegisterConnectionTypeSocket() == C_OK);
+
+ /* may fail if without BUILD_TLS=yes */
+ RedisRegisterConnectionTypeTLS();
+
+ return C_OK;
+}
+
+ConnectionType *connectionByType(int type) {
+ ConnectionType *ct;
+
+ serverAssert(type < CONN_TYPE_MAX);
+
+ ct = connTypes[type];
+ if (!ct) {
+ serverLog(LL_WARNING, "Missing implement of connection type %d", type);
+ }
+
+ return ct;
+}
+
+void connTypeCleanup(int type) {
+ ConnectionType *ct = connectionByType(type);
+
+ if (ct && ct->cleanup) {
+ ct->cleanup();
+ }
+}
+
+void connTypeCleanupAll() {
+ int type;
+
+ for (type = 0; type < CONN_TYPE_MAX; type++) {
+ connTypeCleanup(type);
+ }
+}
+
+int connTypeConfigure(int type, void *priv, int reconfigure) {
+ ConnectionType *ct = connectionByType(type);
+
+ if (ct && ct->configure) {
+ return ct->configure(priv, reconfigure);
+ }
+
+ return C_ERR;
+}
diff --git a/src/connection.h b/src/connection.h
index a7c4c0cf4..b3eb6cc20 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -54,8 +54,9 @@ typedef enum {
#define CONN_FLAG_CLOSE_SCHEDULED (1<<0) /* Closed scheduled by a handler */
#define CONN_FLAG_WRITE_BARRIER (1<<1) /* Write barrier requested */
-#define CONN_TYPE_SOCKET 1
-#define CONN_TYPE_TLS 2
+#define CONN_TYPE_SOCKET 0
+#define CONN_TYPE_TLS 1
+#define CONN_TYPE_MAX 2
typedef void (*ConnectionCallbackFunc)(struct connection *conn);
@@ -63,6 +64,11 @@ typedef struct ConnectionType {
/* connection type */
int (*get_type)(struct connection *conn);
+ /* connection type initialize & finalize & configure */
+ void (*init)(void); /* auto-call during register */
+ void (*cleanup)(void);
+ int (*configure)(void *priv, int reconfigure);
+
/* ae & accept & listen & error & address handler */
void (*ae_handler)(struct aeEventLoop *el, int fd, void *clientData, int mask);
int (*addr)(connection *conn, char *ip, size_t ip_len, int *port, int remote);
@@ -329,4 +335,24 @@ sds connTLSGetPeerCert(connection *conn);
int tlsHasPendingData();
int tlsProcessPendingData();
+/* Initialize the redis connection framework */
+int connTypeInitialize();
+
+/* Register a connection type into redis connection framework */
+int connTypeRegister(ConnectionType *ct);
+
+/* Configure a connection type. A typical case is to configure TLS.
+ * @priv is connection type specified,
+ * @reconfigure is boolean type to specify if overwrite the original config */
+int connTypeConfigure(int type, void *priv, int reconfigure);
+
+/* Cleanup a connection type. A typical case is to cleanup TLS. */
+void connTypeCleanup(int type);
+
+/* Walk all the connection type, and cleanup them all if possible */
+void connTypeCleanupAll();
+
+int RedisRegisterConnectionTypeSocket();
+int RedisRegisterConnectionTypeTLS();
+
#endif /* __REDIS_CONNECTION_H */
diff --git a/src/sentinel.c b/src/sentinel.c
index 7f2ef7e16..b1c180d41 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -848,7 +848,7 @@ void sentinelRunPendingScripts(void) {
sj->pid = 0;
} else if (pid == 0) {
/* Child */
- tlsCleanup();
+ connTypeCleanupAll();
execve(sj->argv[0],sj->argv,environ);
/* If we are here an error occurred. */
_exit(2); /* Don't retry execution. */
diff --git a/src/server.c b/src/server.c
index f8dbb0972..fe8d9bb81 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2447,7 +2447,7 @@ void initServer(void) {
}
if ((server.tls_port || server.tls_replication || server.tls_cluster)
- && tlsConfigure(&server.tls_ctx_config) == C_ERR) {
+ && connTypeConfigure(CONN_TYPE_TLS, &server.tls_ctx_config, 1) == C_ERR) {
serverLog(LL_WARNING, "Failed to configure TLS. Check logs for more info.");
exit(1);
}
@@ -6944,7 +6944,7 @@ int main(int argc, char **argv) {
ACLInit(); /* The ACL subsystem must be initialized ASAP because the
basic networking code and client creation depends on it. */
moduleInitModulesSystem();
- tlsInit();
+ connTypeInitialize();
/* Store the executable path and arguments in a safe place in order
* to be able to restart the server later. */
diff --git a/src/server.h b/src/server.h
index c0f68c73f..ffcc7aff2 100644
--- a/src/server.h
+++ b/src/server.h
@@ -3579,12 +3579,6 @@ void swapMainDbWithTempDb(redisDb *tempDb);
_serverLog(level, __VA_ARGS__);\
} while(0)
-/* TLS stuff */
-void tlsInit(void);
-void tlsCleanup(void);
-int tlsConfigure(redisTLSContextConfig *ctx_config);
-int isTlsConfigured(void);
-
#define redisDebug(fmt, ...) \
printf("DEBUG %s:%d > " fmt "\n", __FILE__, __LINE__, __VA_ARGS__)
#define redisDebugMark() \
diff --git a/src/socket.c b/src/socket.c
index 2ef29e1d4..d93882cce 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -352,6 +352,11 @@ ConnectionType CT_Socket = {
/* connection type */
.get_type = connSocketGetType,
+ /* connection type initialize & finalize & configure */
+ .init = NULL,
+ .cleanup = NULL,
+ .configure = NULL,
+
/* ae & accept & listen & error & address handler */
.ae_handler = connSocketEventHandler,
.addr = connSocketAddr,
@@ -409,3 +414,7 @@ int connRecvTimeout(connection *conn, long long ms) {
return anetRecvTimeout(NULL, conn->fd, ms);
}
+int RedisRegisterConnectionTypeSocket()
+{
+ return connTypeRegister(&CT_Socket);
+}
diff --git a/src/tls.c b/src/tls.c
index 442824dcd..4078fd307 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -141,7 +141,7 @@ static void initCryptoLocks(void) {
}
#endif /* USE_CRYPTO_LOCKS */
-void tlsInit(void) {
+static void tlsInit(void) {
/* Enable configuring OpenSSL using the standard openssl.cnf
* OPENSSL_config()/OPENSSL_init_crypto() should be the first
* call to the OpenSSL* library.
@@ -169,7 +169,7 @@ void tlsInit(void) {
pending_list = listCreate();
}
-void tlsCleanup(void) {
+static void tlsCleanup(void) {
if (redis_tls_ctx) {
SSL_CTX_free(redis_tls_ctx);
redis_tls_ctx = NULL;
@@ -281,12 +281,20 @@ error:
/* Attempt to configure/reconfigure TLS. This operation is atomic and will
* leave the SSL_CTX unchanged if fails.
+ * @priv: config of redisTLSContextConfig.
+ * @reconfigure: if true, ignore the previous configure; if false, only
+ * configure from @ctx_config if redis_tls_ctx is NULL.
*/
-int tlsConfigure(redisTLSContextConfig *ctx_config) {
+static int tlsConfigure(void *priv, int reconfigure) {
+ redisTLSContextConfig *ctx_config = (redisTLSContextConfig *)priv;
char errbuf[256];
SSL_CTX *ctx = NULL;
SSL_CTX *client_ctx = NULL;
+ if (!reconfigure && redis_tls_ctx) {
+ return C_OK;
+ }
+
if (!ctx_config->cert_file) {
serverLog(LL_WARNING, "No tls-cert-file configured!");
goto error;
@@ -406,12 +414,6 @@ error:
return C_ERR;
}
-/* Return 1 if TLS was already configured, 0 otherwise.
- */
-int isTlsConfigured(void) {
- return redis_tls_ctx != NULL;
-}
-
#ifdef TLS_DEBUGGING
#define TLSCONN_DEBUG(fmt, ...) \
serverLog(LL_DEBUG, "TLSCONN: " fmt, __VA_ARGS__)
@@ -1066,6 +1068,11 @@ ConnectionType CT_TLS = {
/* connection type */
.get_type = connTLSGetType,
+ /* connection type initialize & finalize & configure */
+ .init = tlsInit,
+ .cleanup = tlsCleanup,
+ .configure = tlsConfigure,
+
/* ae & accept & listen & error & address handler */
.ae_handler = tlsEventHandler,
.addr = connTLSAddr,
@@ -1090,17 +1097,16 @@ ConnectionType CT_TLS = {
.sync_readline = connTLSSyncReadLine,
};
-#else /* USE_OPENSSL */
-
-void tlsInit(void) {
+int RedisRegisterConnectionTypeTLS()
+{
+ return connTypeRegister(&CT_TLS);
}
-void tlsCleanup(void) {
-}
+#else /* USE_OPENSSL */
-int tlsConfigure(redisTLSContextConfig *ctx_config) {
- UNUSED(ctx_config);
- return C_OK;
+int RedisRegisterConnectionTypeTLS()
+{
+ return C_ERR;
}
connection *connCreateTLS(void) {