diff --git a/redis.conf b/redis.conf index 057149ed0..a78d958c3 100644 --- a/redis.conf +++ b/redis.conf @@ -1500,16 +1500,21 @@ lua-time-limit 5000 # # In order to make Redis Cluster working in such environments, a static # configuration where each node knows its public address is needed. The -# following two options are used for this scope, and are: +# following four options are used for this scope, and are: # # * cluster-announce-ip # * cluster-announce-port +# * cluster-announce-tls-port # * cluster-announce-bus-port # -# Each instructs the node about its address, client port, and cluster message -# bus port. The information is then published in the header of the bus packets -# so that other nodes will be able to correctly map the address of the node -# publishing the information. +# Each instructs the node about its address, client ports (for connections +# without and with TLS) and cluster message bus port. The information is then +# published in the header of the bus packets so that other nodes will be able to +# correctly map the address of the node publishing the information. +# +# If cluster-tls is set to yes and cluster-announce-tls-port is omitted or set +# to zero, then cluster-announce-port refers to the TLS port. Note also that +# cluster-announce-tls-port has no effect if cluster-tls is set to no. # # If the above options are not used, the normal Redis Cluster auto-detection # will be used instead. @@ -1522,7 +1527,8 @@ lua-time-limit 5000 # Example: # # cluster-announce-ip 10.1.1.5 -# cluster-announce-port 6379 +# cluster-announce-tls-port 6379 +# cluster-announce-port 0 # cluster-announce-bus-port 6380 ################################## SLOW LOG ################################### diff --git a/src/cluster.c b/src/cluster.c index 76278c866..1ed9753f0 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -55,7 +55,7 @@ void clusterSendFail(char *nodename); void clusterSendFailoverAuthIfNeeded(clusterNode *node, clusterMsg *request); void clusterUpdateState(void); int clusterNodeGetSlotBit(clusterNode *n, int slot); -sds clusterGenNodesDescription(int filter); +sds clusterGenNodesDescription(int filter, int use_pport); clusterNode *clusterLookupNode(const char *name); int clusterNodeAddSlave(clusterNode *master, clusterNode *slave); int clusterAddSlot(clusterNode *n, int slot); @@ -190,6 +190,9 @@ int clusterLoadConfig(char *filename) { * base port. */ n->cport = busp ? atoi(busp) : n->port + CLUSTER_PORT_INCR; + /* The plaintext port for client in a TLS cluster (n->pport) is not + * stored in nodes.conf. It is received later over the bus protocol. */ + /* Parse flags */ p = s = argv[2]; while(p) { @@ -336,7 +339,7 @@ int clusterSaveConfig(int do_fsync) { /* Get the nodes description and concatenate our "vars" directive to * save currentEpoch and lastVoteEpoch. */ - ci = clusterGenNodesDescription(CLUSTER_NODE_HANDSHAKE); + ci = clusterGenNodesDescription(CLUSTER_NODE_HANDSHAKE, 0); ci = sdscatprintf(ci,"vars currentEpoch %llu lastVoteEpoch %llu\n", (unsigned long long) server.cluster->currentEpoch, (unsigned long long) server.cluster->lastVoteEpoch); @@ -437,6 +440,26 @@ int clusterLockConfig(char *filename) { return C_OK; } +/* Derives our ports to be announced in the cluster bus. */ +void deriveAnnouncedPorts(int *announced_port, int *announced_pport, + int *announced_cport) { + int port = server.tls_cluster ? server.tls_port : server.port; + /* Default announced ports. */ + *announced_port = port; + *announced_pport = server.tls_cluster ? server.port : 0; + *announced_cport = port + CLUSTER_PORT_INCR; + /* Config overriding announced ports. */ + if (server.tls_cluster && server.cluster_announce_tls_port) { + *announced_port = server.cluster_announce_tls_port; + *announced_pport = server.cluster_announce_port; + } else if (server.cluster_announce_port) { + *announced_port = server.cluster_announce_port; + } + if (server.cluster_announce_bus_port) { + *announced_cport = server.cluster_announce_bus_port; + } +} + /* Some flags (currently just the NOFAILOVER flag) may need to be updated * in the "myself" node based on the current configuration of the node, * that may change at runtime via CONFIG SET. This function changes the @@ -524,14 +547,9 @@ void clusterInit(void) { memset(server.cluster->slots_keys_count,0, sizeof(server.cluster->slots_keys_count)); - /* Set myself->port / cport to my listening ports, we'll just need to + /* Set myself->port/cport/pport to my listening ports, we'll just need to * discover the IP address via MEET messages. */ - myself->port = port; - myself->cport = port+CLUSTER_PORT_INCR; - if (server.cluster_announce_port) - myself->port = server.cluster_announce_port; - if (server.cluster_announce_bus_port) - myself->cport = server.cluster_announce_bus_port; + deriveAnnouncedPorts(&myself->port, &myself->pport, &myself->cport); server.cluster->mf_end = 0; resetManualFailover(); @@ -782,6 +800,7 @@ clusterNode *createClusterNode(char *nodename, int flags) { memset(node->ip,0,sizeof(node->ip)); node->port = 0; node->cport = 0; + node->pport = 0; node->fail_reports = listCreate(); node->voted_time = 0; node->orphaned_time = 0; @@ -1488,6 +1507,7 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { if (node->link) freeClusterLink(node->link); memcpy(node->ip,g->ip,NET_IP_STR_LEN); node->port = ntohs(g->port); + node->pport = ntohs(g->pport); node->cport = ntohs(g->cport); node->flags &= ~CLUSTER_NODE_NOADDR; } @@ -1509,6 +1529,7 @@ void clusterProcessGossipSection(clusterMsg *hdr, clusterLink *link) { node = createClusterNode(g->nodename, flags); memcpy(node->ip,g->ip,NET_IP_STR_LEN); node->port = ntohs(g->port); + node->pport = ntohs(g->pport); node->cport = ntohs(g->cport); clusterAddNode(node); } @@ -1548,6 +1569,7 @@ int nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, { char ip[NET_IP_STR_LEN] = {0}; int port = ntohs(hdr->port); + int pport = ntohs(hdr->pport); int cport = ntohs(hdr->cport); /* We don't proceed if the link is the same as the sender link, as this @@ -1559,12 +1581,13 @@ int nodeUpdateAddressIfNeeded(clusterNode *node, clusterLink *link, if (link == node->link) return 0; nodeIp2String(ip,link,hdr->myip); - if (node->port == port && node->cport == cport && + if (node->port == port && node->cport == cport && node->pport == pport && strcmp(ip,node->ip) == 0) return 0; /* IP / port is different, update it. */ memcpy(node->ip,ip,sizeof(ip)); node->port = port; + node->pport = pport; node->cport = cport; if (node->link) freeClusterLink(node->link); node->flags &= ~CLUSTER_NODE_NOADDR; @@ -1862,6 +1885,7 @@ int clusterProcessPacket(clusterLink *link) { node = createClusterNode(NULL,CLUSTER_NODE_HANDSHAKE); nodeIp2String(node->ip,link,hdr->myip); node->port = ntohs(hdr->port); + node->pport = ntohs(hdr->pport); node->cport = ntohs(hdr->cport); clusterAddNode(node); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG); @@ -1924,6 +1948,7 @@ int clusterProcessPacket(clusterLink *link) { link->node->flags |= CLUSTER_NODE_NOADDR; link->node->ip[0] = '\0'; link->node->port = 0; + link->node->pport = 0; link->node->cport = 0; freeClusterLink(link); clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG); @@ -2423,19 +2448,16 @@ void clusterBuildMessageHdr(clusterMsg *hdr, int type) { hdr->myip[NET_IP_STR_LEN-1] = '\0'; } - /* Handle cluster-announce-port as well. */ - int port = server.tls_cluster ? server.tls_port : server.port; - int announced_port = server.cluster_announce_port ? - server.cluster_announce_port : port; - int announced_cport = server.cluster_announce_bus_port ? - server.cluster_announce_bus_port : - (port + CLUSTER_PORT_INCR); + /* Handle cluster-announce-[tls-|bus-]port. */ + int announced_port, announced_pport, announced_cport; + deriveAnnouncedPorts(&announced_port, &announced_pport, &announced_cport); memcpy(hdr->myslots,master->slots,sizeof(hdr->myslots)); memset(hdr->slaveof,0,CLUSTER_NAMELEN); if (myself->slaveof != NULL) memcpy(hdr->slaveof,myself->slaveof->name, CLUSTER_NAMELEN); hdr->port = htons(announced_port); + hdr->pport = htons(announced_pport); hdr->cport = htons(announced_cport); hdr->flags = htons(myself->flags); hdr->state = server.cluster->state; @@ -2492,6 +2514,7 @@ void clusterSetGossipEntry(clusterMsg *hdr, int i, clusterNode *n) { gossip->port = htons(n->port); gossip->cport = htons(n->cport); gossip->flags = htons(n->flags); + gossip->pport = htons(n->pport); gossip->notused1 = 0; } @@ -4130,15 +4153,16 @@ sds representClusterNodeFlags(sds ci, uint16_t flags) { * See clusterGenNodesDescription() top comment for more information. * * The function returns the string representation as an SDS string. */ -sds clusterGenNodeDescription(clusterNode *node) { +sds clusterGenNodeDescription(clusterNode *node, int use_pport) { int j, start; sds ci; + int port = use_pport && node->pport ? node->pport : node->port; /* Node coordinates */ ci = sdscatlen(sdsempty(),node->name,CLUSTER_NAMELEN); ci = sdscatfmt(ci," %s:%i@%i ", node->ip, - node->port, + port, node->cport); /* Flags */ @@ -4249,10 +4273,13 @@ void clusterGenNodesSlotsInfo(int filter) { * include all the known nodes in the representation, including nodes in * the HANDSHAKE state. * + * Setting use_pport to 1 in a TLS cluster makes the result contain the + * plaintext client port rather then the TLS client port of each node. + * * The representation obtained using this function is used for the output * of the CLUSTER NODES function, and as format for the cluster * configuration file (nodes.conf) for a given node. */ -sds clusterGenNodesDescription(int filter) { +sds clusterGenNodesDescription(int filter, int use_pport) { sds ci = sdsempty(), ni; dictIterator *di; dictEntry *de; @@ -4265,7 +4292,7 @@ sds clusterGenNodesDescription(int filter) { clusterNode *node = dictGetVal(de); if (node->flags & filter) continue; - ni = clusterGenNodeDescription(node); + ni = clusterGenNodeDescription(node, use_pport); ci = sdscatsds(ci,ni); sdsfree(ni); ci = sdscatlen(ci,"\n",1); @@ -4319,7 +4346,10 @@ void addNodeReplyForClusterSlot(client *c, clusterNode *node, int start_slot, in addReplyLongLong(c, end_slot); addReplyArrayLen(c, 3); addReplyBulkCString(c, node->ip); - addReplyLongLong(c, node->port); + /* Report non-TLS ports to non-TLS client in TLS cluster if available. */ + int use_pport = (server.tls_cluster && + c->conn && connGetType(c->conn) != CONN_TYPE_TLS); + addReplyLongLong(c, use_pport && node->pport ? node->pport : node->port); addReplyBulkCBuffer(c, node->name, CLUSTER_NAMELEN); /* Remaining nodes in reply are replicas for slot range */ @@ -4329,7 +4359,10 @@ void addNodeReplyForClusterSlot(client *c, clusterNode *node, int start_slot, in if (nodeFailed(node->slaves[i])) continue; addReplyArrayLen(c, 3); addReplyBulkCString(c, node->slaves[i]->ip); - addReplyLongLong(c, node->slaves[i]->port); + /* Report slave's non-TLS port to non-TLS client in TLS cluster */ + addReplyLongLong(c, (use_pport && node->slaves[i]->pport ? + node->slaves[i]->pport : + node->slaves[i]->port)); addReplyBulkCBuffer(c, node->slaves[i]->name, CLUSTER_NAMELEN); nested_elements++; } @@ -4458,7 +4491,11 @@ NULL } } else if (!strcasecmp(c->argv[1]->ptr,"nodes") && c->argc == 2) { /* CLUSTER NODES */ - sds nodes = clusterGenNodesDescription(0); + /* Report plaintext ports, only if cluster is TLS but client is known to + * be non-TLS). */ + int use_pport = (server.tls_cluster && + c->conn && connGetType(c->conn) != CONN_TYPE_TLS); + sds nodes = clusterGenNodesDescription(0, use_pport); addReplyVerbatim(c,nodes,sdslen(nodes),"txt"); sdsfree(nodes); } else if (!strcasecmp(c->argv[1]->ptr,"myid") && c->argc == 2) { @@ -4834,9 +4871,12 @@ NULL return; } + /* Use plaintext port if cluster is TLS but client is non-TLS. */ + int use_pport = (server.tls_cluster && + c->conn && connGetType(c->conn) != CONN_TYPE_TLS); addReplyArrayLen(c,n->numslaves); for (j = 0; j < n->numslaves; j++) { - sds ni = clusterGenNodeDescription(n->slaves[j]); + sds ni = clusterGenNodeDescription(n->slaves[j], use_pport); addReplyBulkCString(c,ni); sdsfree(ni); } @@ -5892,10 +5932,15 @@ void clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_co } else if (error_code == CLUSTER_REDIR_MOVED || error_code == CLUSTER_REDIR_ASK) { + /* Redirect to IP:port. Include plaintext port if cluster is TLS but + * client is non-TLS. */ + int use_pport = (server.tls_cluster && + c->conn && connGetType(c->conn) != CONN_TYPE_TLS); + int port = use_pport && n->pport ? n->pport : n->port; addReplyErrorSds(c,sdscatprintf(sdsempty(), "-%s %d %s:%d", (error_code == CLUSTER_REDIR_ASK) ? "ASK" : "MOVED", - hashslot,n->ip,n->port)); + hashslot, n->ip, port)); } else { serverPanic("getNodeByQuery() unknown error."); } diff --git a/src/cluster.h b/src/cluster.h index ed1ad5c3a..f476a50a0 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -135,7 +135,9 @@ typedef struct clusterNode { mstime_t orphaned_time; /* Starting time of orphaned master condition */ long long repl_offset; /* Last known repl offset for this node. */ char ip[NET_IP_STR_LEN]; /* Latest known IP address of this node */ - int port; /* Latest known clients port of this node */ + int port; /* Latest known clients port (TLS or plain). */ + int pport; /* Latest known clients plaintext port. Only used + if the main clients port is for TLS. */ int cport; /* Latest known cluster port of this node. */ clusterLink *link; /* TCP/IP link with this node */ list *fail_reports; /* List of nodes signaling this as failing */ @@ -194,7 +196,8 @@ typedef struct { uint16_t port; /* base port last time it was seen */ uint16_t cport; /* cluster port last time it was seen */ uint16_t flags; /* node->flags copy */ - uint32_t notused1; + uint16_t pport; /* plaintext-port, when base port is TLS */ + uint16_t notused1; } clusterMsgDataGossip; typedef struct { @@ -267,7 +270,8 @@ typedef struct { unsigned char myslots[CLUSTER_SLOTS/8]; char slaveof[CLUSTER_NAMELEN]; char myip[NET_IP_STR_LEN]; /* Sender IP, if not all zeroed. */ - char notused1[34]; /* 34 bytes reserved for future usage. */ + char notused1[32]; /* 32 bytes reserved for future usage. */ + uint16_t pport; /* Sender TCP plaintext port, if base port is TLS */ uint16_t cport; /* Sender TCP cluster bus port */ uint16_t flags; /* Sender node flags */ unsigned char state; /* Cluster state from the POV of the sender */ diff --git a/src/config.c b/src/config.c index 459616eb4..64058791c 100644 --- a/src/config.c +++ b/src/config.c @@ -2495,6 +2495,7 @@ standardConfig configs[] = { createIntConfig("tcp-backlog", NULL, IMMUTABLE_CONFIG, 0, INT_MAX, server.tcp_backlog, 511, INTEGER_CONFIG, NULL, NULL), /* TCP listen backlog. */ createIntConfig("cluster-announce-bus-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.cluster_announce_bus_port, 0, INTEGER_CONFIG, NULL, NULL), /* Default: Use +10000 offset. */ createIntConfig("cluster-announce-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.cluster_announce_port, 0, INTEGER_CONFIG, NULL, NULL), /* Use server.port */ + createIntConfig("cluster-announce-tls-port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.cluster_announce_tls_port, 0, INTEGER_CONFIG, NULL, NULL), /* Use server.tls_port */ createIntConfig("repl-timeout", NULL, MODIFIABLE_CONFIG, 1, INT_MAX, server.repl_timeout, 60, INTEGER_CONFIG, NULL, NULL), createIntConfig("repl-ping-replica-period", "repl-ping-slave-period", MODIFIABLE_CONFIG, 1, INT_MAX, server.repl_ping_slave_period, 10, INTEGER_CONFIG, NULL, NULL), createIntConfig("list-compress-depth", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.list_compress_depth, 0, INTEGER_CONFIG, NULL, NULL), diff --git a/src/server.h b/src/server.h index 0b9cc3341..490c74f8d 100644 --- a/src/server.h +++ b/src/server.h @@ -1548,6 +1548,7 @@ struct redisServer { if the master is in failure state. */ char *cluster_announce_ip; /* IP address to announce on cluster bus. */ int cluster_announce_port; /* base port to announce on cluster bus. */ + int cluster_announce_tls_port; /* TLS port to announce on cluster bus. */ int cluster_announce_bus_port; /* bus port to announce on cluster bus. */ int cluster_module_flags; /* Set of flags that Redis modules are able to set in order to suppress certain diff --git a/tests/cluster/tests/04-resharding.tcl b/tests/cluster/tests/04-resharding.tcl index 1dcdb5a2c..4d31d314c 100644 --- a/tests/cluster/tests/04-resharding.tcl +++ b/tests/cluster/tests/04-resharding.tcl @@ -54,7 +54,17 @@ proc process_is_running {pid} { set numkeys 50000 set numops 200000 -set cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]] +set start_node_port [get_instance_attrib redis 0 port] +set cluster [redis_cluster 127.0.0.1:$start_node_port] +if {$::tls} { + # setup a non-TLS cluster client to the TLS cluster + set plaintext_port [get_instance_attrib redis 0 plaintext-port] + set cluster_plaintext [redis_cluster 127.0.0.1:$plaintext_port 0] + puts "Testing TLS cluster on start node 127.0.0.1:$start_node_port, plaintext port $plaintext_port" +} else { + set cluster_plaintext $cluster + puts "Testing using non-TLS cluster" +} catch {unset content} array set content {} set tribpid {} @@ -94,8 +104,11 @@ test "Cluster consistency during live resharding" { # This way we are able to stress Lua -> Redis command invocation # as well, that has tests to prevent Lua to write into wrong # hash slots. - if {$listid % 2} { + # We also use both TLS and plaintext connections. + if {$listid % 3 == 0} { $cluster rpush $key $ele + } elseif {$listid % 3 == 1} { + $cluster_plaintext rpush $key $ele } else { $cluster eval {redis.call("rpush",KEYS[1],ARGV[1])} 1 $key $ele } diff --git a/tests/cluster/tests/15-cluster-slots.tcl b/tests/cluster/tests/15-cluster-slots.tcl index 1b33c57bd..f154b7270 100644 --- a/tests/cluster/tests/15-cluster-slots.tcl +++ b/tests/cluster/tests/15-cluster-slots.tcl @@ -48,3 +48,16 @@ test "client can handle keys with hash tag" { $cluster set foo{tag} bar $cluster close } + +if {$::tls} { + test {CLUSTER SLOTS from non-TLS client in TLS cluster} { + set slots_tls [R 0 cluster slots] + set host [get_instance_attrib redis 0 host] + set plaintext_port [get_instance_attrib redis 0 plaintext-port] + set client_plain [redis $host $plaintext_port 0 0] + set slots_plain [$client_plain cluster slots] + $client_plain close + # Compare the ports in the first row + assert_no_match [lindex $slots_tls 0 3 1] [lindex $slots_plain 0 3 1] + } +} diff --git a/tests/instances.tcl b/tests/instances.tcl index 255d9740f..ad605c316 100644 --- a/tests/instances.tcl +++ b/tests/instances.tcl @@ -64,6 +64,8 @@ proc exec_instance {type dirname cfgfile} { proc spawn_instance {type base_port count {conf {}} {base_conf_file ""}} { for {set j 0} {$j < $count} {incr j} { set port [find_available_port $base_port $::redis_port_count] + # plaintext port (only used for TLS cluster) + set pport 0 # Create a directory for this instance. set dirname "${type}_${j}" lappend ::dirs $dirname @@ -83,7 +85,9 @@ proc spawn_instance {type base_port count {conf {}} {base_conf_file ""}} { puts $cfg "tls-port $port" puts $cfg "tls-replication yes" puts $cfg "tls-cluster yes" - puts $cfg "port 0" + # plaintext port, only used by plaintext clients in a TLS cluster + set pport [find_available_port $base_port $::redis_port_count] + puts $cfg "port $pport" puts $cfg [format "tls-cert-file %s/../../tls/server.crt" [pwd]] puts $cfg [format "tls-key-file %s/../../tls/server.key" [pwd]] puts $cfg [format "tls-client-cert-file %s/../../tls/client.crt" [pwd]] @@ -118,6 +122,8 @@ proc spawn_instance {type base_port count {conf {}} {base_conf_file ""}} { set cfg [open $cfgfile a+] if {$::tls} { puts $cfg "tls-port $port" + set pport [find_available_port $base_port $::redis_port_count] + puts $cfg "port $pport" } else { puts $cfg "port $port" } @@ -143,6 +149,7 @@ proc spawn_instance {type base_port count {conf {}} {base_conf_file ""}} { pid $pid \ host $::host \ port $port \ + plaintext-port $pport \ link $link \ ] } diff --git a/tests/support/cluster.tcl b/tests/support/cluster.tcl index 97a659a1d..df4b7f3d0 100644 --- a/tests/support/cluster.tcl +++ b/tests/support/cluster.tcl @@ -4,7 +4,7 @@ # # Example usage: # -# set c [redis_cluster 127.0.0.1 6379 127.0.0.1 6380] +# set c [redis_cluster {127.0.0.1:6379 127.0.0.1:6380}] # $c set foo # $c get foo # $c close @@ -17,6 +17,7 @@ set ::redis_cluster::id 0 array set ::redis_cluster::startup_nodes {} array set ::redis_cluster::nodes {} array set ::redis_cluster::slots {} +array set ::redis_cluster::tls {} # List of "plain" commands, which are commands where the sole key is always # the first argument. @@ -34,11 +35,14 @@ set ::redis_cluster::plain_commands { dump bitcount bitpos pfadd pfcount } -proc redis_cluster {nodes} { +# Create a cluster client. The nodes are given as a list of host:port. The TLS +# parameter (1 or 0) is optional and defaults to the global $::tls. +proc redis_cluster {nodes {tls -1}} { set id [incr ::redis_cluster::id] set ::redis_cluster::startup_nodes($id) $nodes set ::redis_cluster::nodes($id) {} set ::redis_cluster::slots($id) {} + set ::redis_cluster::tls($id) [expr $tls == -1 ? $::tls : $tls] set handle [interp alias {} ::redis_cluster::instance$id {} ::redis_cluster::__dispatch__ $id] $handle refresh_nodes_map return $handle @@ -60,9 +64,10 @@ proc ::redis_cluster::__method__refresh_nodes_map {id} { foreach start_node $::redis_cluster::startup_nodes($id) { set ip_port [lindex [split $start_node @] 0] lassign [split $ip_port :] start_host start_port + set tls $::redis_cluster::tls($id) if {[catch { set r {} - set r [redis $start_host $start_port 0 $::tls] + set r [redis $start_host $start_port 0 $tls] set nodes_descr [$r cluster nodes] $r close } e]} { @@ -107,7 +112,8 @@ proc ::redis_cluster::__method__refresh_nodes_map {id} { # Connect to the node set link {} - catch {set link [redis $host $port 0 $::tls]} + set tls $::redis_cluster::tls($id) + catch {set link [redis $host $port 0 $tls]} # Build this node description as an hash. set node [dict create \ @@ -161,6 +167,7 @@ proc ::redis_cluster::__method__close {id} { catch {unset ::redis_cluster::startup_nodes($id)} catch {unset ::redis_cluster::nodes($id)} catch {unset ::redis_cluster::slots($id)} + catch {unset ::redis_cluster::tls($id)} catch {interp alias {} ::redis_cluster::instance$id {}} } diff --git a/tests/support/redis.tcl b/tests/support/redis.tcl index 373058daf..4d321c975 100644 --- a/tests/support/redis.tcl +++ b/tests/support/redis.tcl @@ -35,6 +35,7 @@ array set ::redis::addr {} array set ::redis::blocking {} array set ::redis::deferred {} array set ::redis::reconnect {} +array set ::redis::tls {} array set ::redis::callback {} array set ::redis::state {} ;# State in non-blocking reply reading array set ::redis::statestack {} ;# Stack of states, for nested mbulks @@ -58,7 +59,7 @@ proc redis {{server 127.0.0.1} {port 6379} {defer 0} {tls 0} {tlsoptions {}}} { set ::redis::blocking($id) 1 set ::redis::deferred($id) $defer set ::redis::reconnect($id) 0 - set ::redis::tls $tls + set ::redis::tls($id) $tls ::redis::redis_reset_state $id interp alias {} ::redis::redisHandle$id {} ::redis::__dispatch__ $id } @@ -83,7 +84,7 @@ proc ::redis::__dispatch__raw__ {id method argv} { # Reconnect the link if needed. if {$fd eq {}} { lassign $::redis::addr($id) host port - if {$::redis::tls} { + if {$::redis::tls($id)} { set ::redis::fd($id) [::tls::socket $host $port] } else { set ::redis::fd($id) [socket $host $port] @@ -158,6 +159,7 @@ proc ::redis::__method__close {id fd} { catch {unset ::redis::blocking($id)} catch {unset ::redis::deferred($id)} catch {unset ::redis::reconnect($id)} + catch {unset ::redis::tls($id)} catch {unset ::redis::state($id)} catch {unset ::redis::statestack($id)} catch {unset ::redis::callback($id)}