summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhenwei pi <pizhenwei@bytedance.com>2022-07-27 10:08:32 +0800
committerzhenwei pi <pizhenwei@bytedance.com>2022-08-22 15:01:40 +0800
commitbff7ecc7864716c14fbb399f19acaee364975b29 (patch)
tree7f342f044ee6e39769b55e1a1754abb4ffc39dac
parentb9d77288243aeab306b99ff72a71d8490a91e0a8 (diff)
downloadredis-bff7ecc7864716c14fbb399f19acaee364975b29.tar.gz
Introduce connAddr
Originally, connPeerToString is designed to get the address info from socket only(for both TCP & TLS), and the API 'connPeerToString' is oriented to operate a FD like: int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port) { return anetFdToString(conn ? conn->fd : -1, ip, ip_len, port, FD_TO_PEER_NAME); } Introduce connAddr and implement .addr method for socket and TLS, thus the API 'connAddr' and 'connFormatAddr' become oriented to a connection like: static inline int connAddr(connection *conn, char *ip, size_t ip_len, int *port, int remote) { if (conn && conn->type->addr) { return conn->type->addr(conn, ip, ip_len, port, remote); } return -1; } Also remove 'FD_TO_PEER_NAME' & 'FD_TO_SOCK_NAME', use a boolean type 'remote' to get local/remote address of a connection. With these changes, it's possible to support the other connection types which does not use socket(Ex, RDMA). Thanks to Oran for suggestions! Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
-rw-r--r--src/anet.c21
-rw-r--r--src/anet.h7
-rw-r--r--src/cluster.c4
-rw-r--r--src/connection.h45
-rw-r--r--src/module.c2
-rw-r--r--src/networking.c14
-rw-r--r--src/redis-cli.c3
-rw-r--r--src/replication.c11
-rw-r--r--src/sentinel.c2
-rw-r--r--src/server.c2
-rw-r--r--src/socket.c25
-rw-r--r--src/tls.c5
12 files changed, 79 insertions, 62 deletions
diff --git a/src/anet.c b/src/anet.c
index d4411382c..00c30b83d 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -579,11 +579,11 @@ int anetUnixAccept(char *err, int s) {
return fd;
}
-int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type) {
+int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int remote) {
struct sockaddr_storage sa;
socklen_t salen = sizeof(sa);
- if (fd_to_str_type == FD_TO_PEER_NAME) {
+ if (remote) {
if (getpeername(fd, (struct sockaddr *)&sa, &salen) == -1) goto error;
} else {
if (getsockname(fd, (struct sockaddr *)&sa, &salen) == -1) goto error;
@@ -627,23 +627,6 @@ error:
return -1;
}
-/* Format an IP,port pair into something easy to parse. If IP is IPv6
- * (matches for ":"), the ip is surrounded by []. IP and port are just
- * separated by colons. This the standard to display addresses within Redis. */
-int anetFormatAddr(char *buf, size_t buf_len, char *ip, int port) {
- return snprintf(buf,buf_len, strchr(ip,':') ?
- "[%s]:%d" : "%s:%d", ip, port);
-}
-
-/* Like anetFormatAddr() but extract ip and port from the socket's peer/sockname. */
-int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type) {
- char ip[INET6_ADDRSTRLEN];
- int port;
-
- anetFdToString(fd,ip,sizeof(ip),&port,fd_to_str_type);
- return anetFormatAddr(buf, buf_len, ip, port);
-}
-
/* Create a pipe buffer with given flags for read end and write end.
* Note that it supports the file flags defined by pipe2() and fcntl(F_SETFL),
* and one of the use cases is O_CLOEXEC|O_NONBLOCK. */
diff --git a/src/anet.h b/src/anet.h
index b1a3847de..b571e52c1 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -49,10 +49,6 @@
#undef ip_len
#endif
-/* FD to address string conversion types */
-#define FD_TO_PEER_NAME 0
-#define FD_TO_SOCK_NAME 1
-
int anetTcpNonBlockConnect(char *err, const char *addr, int port);
int anetTcpNonBlockBestEffortBindConnect(char *err, const char *addr, int port, const char *source_addr);
int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len, int flags);
@@ -68,10 +64,9 @@ int anetEnableTcpNoDelay(char *err, int fd);
int anetDisableTcpNoDelay(char *err, int fd);
int anetSendTimeout(char *err, int fd, long long ms);
int anetRecvTimeout(char *err, int fd, long long ms);
-int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type);
+int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int remote);
int anetKeepAlive(char *err, int fd, int interval);
int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
-int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type);
int anetPipe(int fds[2], int read_flags, int write_flags);
int anetSetSockMarkId(char *err, int fd, uint32_t id);
int anetGetError(int fd);
diff --git a/src/cluster.c b/src/cluster.c
index c739a3892..a7d6f6205 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -1769,7 +1769,7 @@ int nodeIp2String(char *buf, clusterLink *link, char *announced_ip) {
buf[NET_IP_STR_LEN-1] = '\0'; /* We are not sure the input is sane. */
return C_OK;
} else {
- if (connPeerToString(link->conn, buf, NET_IP_STR_LEN, NULL) == C_ERR) {
+ if (connAddrPeerName(link->conn, buf, NET_IP_STR_LEN, NULL) == C_ERR) {
serverLog(LL_NOTICE, "Error converting peer IP to string: %s",
link->conn ? connGetLastError(link->conn) : "no link");
return C_ERR;
@@ -2273,7 +2273,7 @@ int clusterProcessPacket(clusterLink *link) {
{
char ip[NET_IP_STR_LEN];
- if (connSockName(link->conn,ip,sizeof(ip),NULL) != -1 &&
+ if (connAddrSockName(link->conn,ip,sizeof(ip),NULL) != -1 &&
strcmp(ip,myself->ip))
{
memcpy(myself->ip,ip,NET_IP_STR_LEN);
diff --git a/src/connection.h b/src/connection.h
index 853903208..a7c4c0cf4 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -32,9 +32,12 @@
#define __REDIS_CONNECTION_H
#include <errno.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/uio.h>
#define CONN_INFO_LEN 32
+#define CONN_ADDR_STR_LEN 128 /* Similar to INET6_ADDRSTRLEN, hoping to handle other protocols. */
struct aeEventLoop;
typedef struct connection connection;
@@ -62,6 +65,7 @@ typedef struct ConnectionType {
/* 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);
/* create/close connection */
void (*close)(struct connection *conn);
@@ -233,6 +237,44 @@ static inline int connLastErrorRetryable(connection *conn) {
return conn->last_errno == EINTR;
}
+/* Get address information of a connection.
+ * @remote works as boolean type to get local/remote address */
+static inline int connAddr(connection *conn, char *ip, size_t ip_len, int *port, int remote) {
+ if (conn && conn->type->addr) {
+ return conn->type->addr(conn, ip, ip_len, port, remote);
+ }
+
+ return -1;
+}
+
+/* Format an IP,port pair into something easy to parse. If IP is IPv6
+ * (matches for ":"), the ip is surrounded by []. IP and port are just
+ * separated by colons. This the standard to display addresses within Redis. */
+static inline int formatAddr(char *buf, size_t buf_len, char *ip, int port) {
+ return snprintf(buf,buf_len, strchr(ip,':') ?
+ "[%s]:%d" : "%s:%d", ip, port);
+}
+
+static inline int connFormatAddr(connection *conn, char *buf, size_t buf_len, int remote)
+{
+ char ip[CONN_ADDR_STR_LEN];
+ int port;
+
+ if (connAddr(conn, ip, sizeof(ip), &port, remote) < 0) {
+ return -1;
+ }
+
+ return formatAddr(buf, buf_len, ip, port);
+}
+
+static inline int connAddrPeerName(connection *conn, char *ip, size_t ip_len, int *port) {
+ return connAddr(conn, ip, ip_len, port, 1);
+}
+
+static inline int connAddrSockName(connection *conn, char *ip, size_t ip_len, int *port) {
+ return connAddr(conn, ip, ip_len, port, 0);
+}
+
connection *connCreateSocket();
connection *connCreateAcceptedSocket(int fd);
@@ -281,9 +323,6 @@ int connDisableTcpNoDelay(connection *conn);
int connKeepAlive(connection *conn, int interval);
int connSendTimeout(connection *conn, long long ms);
int connRecvTimeout(connection *conn, long long ms);
-int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port);
-int connFormatFdAddr(connection *conn, char *buf, size_t buf_len, int fd_to_str_type);
-int connSockName(connection *conn, char *ip, size_t ip_len, int *port);
/* Helpers for tls special considerations */
sds connTLSGetPeerCert(connection *conn);
diff --git a/src/module.c b/src/module.c
index d915b56a1..3e09cdd10 100644
--- a/src/module.c
+++ b/src/module.c
@@ -3331,7 +3331,7 @@ int modulePopulateClientInfoStructure(void *ci, client *client, int structver) {
ci1->flags |= REDISMODULE_CLIENTINFO_FLAG_SSL;
int port;
- connPeerToString(client->conn,ci1->addr,sizeof(ci1->addr),&port);
+ connAddrPeerName(client->conn,ci1->addr,sizeof(ci1->addr),&port);
ci1->port = port;
ci1->db = client->db->id;
ci1->id = client->id;
diff --git a/src/networking.c b/src/networking.c
index 6bf39d11a..04ba54768 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1196,7 +1196,7 @@ int islocalClient(client *c) {
/* tcp */
char cip[NET_IP_STR_LEN+1] = { 0 };
- connPeerToString(c->conn, cip, sizeof(cip)-1, NULL);
+ connAddrPeerName(c->conn, cip, sizeof(cip)-1, NULL);
return !strcmp(cip,"127.0.0.1") || !strcmp(cip,"::1");
}
@@ -2700,13 +2700,13 @@ done:
* you want to relax error checking or need to display something anyway (see
* anetFdToString implementation for more info). */
void genClientAddrString(client *client, char *addr,
- size_t addr_len, int fd_to_str_type) {
+ size_t addr_len, int remote) {
if (client->flags & CLIENT_UNIX_SOCKET) {
/* Unix socket client. */
snprintf(addr,addr_len,"%s:0",server.unixsocket);
} else {
/* TCP client. */
- connFormatFdAddr(client->conn,addr,addr_len,fd_to_str_type);
+ connFormatAddr(client->conn,addr,addr_len,remote);
}
}
@@ -2715,10 +2715,10 @@ void genClientAddrString(client *client, char *addr,
* The Peer ID never changes during the life of the client, however it
* is expensive to compute. */
char *getClientPeerId(client *c) {
- char peerid[NET_ADDR_STR_LEN];
+ char peerid[NET_ADDR_STR_LEN] = {0};
if (c->peerid == NULL) {
- genClientAddrString(c,peerid,sizeof(peerid),FD_TO_PEER_NAME);
+ genClientAddrString(c,peerid,sizeof(peerid),1);
c->peerid = sdsnew(peerid);
}
return c->peerid;
@@ -2729,10 +2729,10 @@ char *getClientPeerId(client *c) {
* The Socket Name never changes during the life of the client, however it
* is expensive to compute. */
char *getClientSockname(client *c) {
- char sockname[NET_ADDR_STR_LEN];
+ char sockname[NET_ADDR_STR_LEN] = {0};
if (c->sockname == NULL) {
- genClientAddrString(c,sockname,sizeof(sockname),FD_TO_SOCK_NAME);
+ genClientAddrString(c,sockname,sizeof(sockname),0);
c->sockname = sdsnew(sockname);
}
return c->sockname;
diff --git a/src/redis-cli.c b/src/redis-cli.c
index bc85c21d4..131e79a78 100644
--- a/src/redis-cli.c
+++ b/src/redis-cli.c
@@ -61,6 +61,7 @@
#include "help.h" /* Used for backwards-compatibility with pre-7.0 servers that don't support COMMAND DOCS. */
#include "anet.h"
#include "ae.h"
+#include "connection.h"
#include "cli_common.h"
#include "mt19937-64.h"
@@ -322,7 +323,7 @@ static void cliRefreshPrompt(void) {
prompt = sdscatfmt(prompt,"redis %s",config.hostsocket);
} else {
char addr[256];
- anetFormatAddr(addr, sizeof(addr), config.conn_info.hostip, config.conn_info.hostport);
+ formatAddr(addr, sizeof(addr), config.conn_info.hostip, config.conn_info.hostport);
prompt = sdscatlen(prompt,addr,strlen(addr));
}
diff --git a/src/replication.c b/src/replication.c
index 58ed10833..3ae130252 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -33,6 +33,7 @@
#include "cluster.h"
#include "bio.h"
#include "functions.h"
+#include "connection.h"
#include <memory.h>
#include <sys/time.h>
@@ -66,11 +67,11 @@ char *replicationGetSlaveName(client *c) {
ip[0] = '\0';
buf[0] = '\0';
if (c->slave_addr ||
- connPeerToString(c->conn,ip,sizeof(ip),NULL) != -1)
+ connAddrPeerName(c->conn,ip,sizeof(ip),NULL) != -1)
{
char *addr = c->slave_addr ? c->slave_addr : ip;
if (c->slave_listening_port)
- anetFormatAddr(buf,sizeof(buf),addr,c->slave_listening_port);
+ formatAddr(buf,sizeof(buf),addr,c->slave_listening_port);
else
snprintf(buf,sizeof(buf),"%s:<unknown-replica-port>",addr);
} else {
@@ -3156,7 +3157,7 @@ void roleCommand(client *c) {
char ip[NET_IP_STR_LEN], *slaveaddr = slave->slave_addr;
if (!slaveaddr) {
- if (connPeerToString(slave->conn,ip,sizeof(ip),NULL) == -1)
+ if (connAddrPeerName(slave->conn,ip,sizeof(ip),NULL) == -1)
continue;
slaveaddr = ip;
}
@@ -3817,7 +3818,7 @@ static client *findReplica(char *host, int port) {
char ip[NET_IP_STR_LEN], *replicaip = replica->slave_addr;
if (!replicaip) {
- if (connPeerToString(replica->conn, ip, sizeof(ip), NULL) == -1)
+ if (connAddrPeerName(replica->conn, ip, sizeof(ip), NULL) == -1)
continue;
replicaip = ip;
}
@@ -4048,7 +4049,7 @@ void updateFailoverStatus(void) {
char ip[NET_IP_STR_LEN], *replicaaddr = replica->slave_addr;
if (!replicaaddr) {
- if (connPeerToString(replica->conn,ip,sizeof(ip),NULL) == -1)
+ if (connAddrPeerName(replica->conn,ip,sizeof(ip),NULL) == -1)
continue;
replicaaddr = ip;
}
diff --git a/src/sentinel.c b/src/sentinel.c
index f819af11a..7f2ef7e16 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -3027,7 +3027,7 @@ int sentinelSendHello(sentinelRedisInstance *ri) {
if (sentinel.announce_ip) {
announce_ip = sentinel.announce_ip;
} else {
- if (anetFdToString(ri->link->cc->c.fd,ip,sizeof(ip),NULL,FD_TO_SOCK_NAME) == -1)
+ if (anetFdToString(ri->link->cc->c.fd,ip,sizeof(ip),NULL,0) == -1)
return C_ERR;
announce_ip = ip;
}
diff --git a/src/server.c b/src/server.c
index b96d95b75..f8dbb0972 100644
--- a/src/server.c
+++ b/src/server.c
@@ -5934,7 +5934,7 @@ sds genRedisInfoString(dict *section_dict, int all_sections, int everything) {
long lag = 0;
if (!slaveip) {
- if (connPeerToString(slave->conn,ip,sizeof(ip),&port) == -1)
+ if (connAddrPeerName(slave->conn,ip,sizeof(ip),&port) == -1)
continue;
slaveip = ip;
}
diff --git a/src/socket.c b/src/socket.c
index 989192c3a..2ef29e1d4 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -300,6 +300,14 @@ static void connSocketEventHandler(struct aeEventLoop *el, int fd, void *clientD
}
}
+static int connSocketAddr(connection *conn, char *ip, size_t ip_len, int *port, int remote) {
+ if (anetFdToString(conn->fd, ip, ip_len, port, remote) == 0)
+ return C_OK;
+
+ conn->last_errno = errno;
+ return C_ERR;
+}
+
static int connSocketBlockingConnect(connection *conn, const char *addr, int port, long long timeout) {
int fd = anetTcpNonBlockConnect(NULL,addr,port);
if (fd == -1) {
@@ -346,6 +354,7 @@ ConnectionType CT_Socket = {
/* ae & accept & listen & error & address handler */
.ae_handler = connSocketEventHandler,
+ .addr = connSocketAddr,
/* create/close connection */
.close = connSocketClose,
@@ -367,22 +376,6 @@ ConnectionType CT_Socket = {
.sync_readline = connSocketSyncReadLine,
};
-int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port) {
- if (anetFdToString(conn ? conn->fd : -1, ip, ip_len, port, FD_TO_PEER_NAME) == -1) {
- if (conn) conn->last_errno = errno;
- return C_ERR;
- }
- return C_OK;
-}
-
-int connSockName(connection *conn, char *ip, size_t ip_len, int *port) {
- return anetFdToString(conn->fd, ip, ip_len, port, FD_TO_SOCK_NAME);
-}
-
-int connFormatFdAddr(connection *conn, char *buf, size_t buf_len, int fd_to_str_type) {
- return anetFormatFdAddr(conn ? conn->fd : -1, buf, buf_len, fd_to_str_type);
-}
-
int connBlock(connection *conn) {
if (conn->fd == -1) return C_ERR;
return anetBlock(NULL, conn->fd);
diff --git a/src/tls.c b/src/tls.c
index 019f5a9d8..442824dcd 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -718,6 +718,10 @@ static void tlsEventHandler(struct aeEventLoop *el, int fd, void *clientData, in
tlsHandleEvent(conn, mask);
}
+static int connTLSAddr(connection *conn, char *ip, size_t ip_len, int *port, int remote) {
+ return anetFdToString(conn->fd, ip, ip_len, port, remote);
+}
+
static void connTLSClose(connection *conn_) {
tls_connection *conn = (tls_connection *) conn_;
@@ -1064,6 +1068,7 @@ ConnectionType CT_TLS = {
/* ae & accept & listen & error & address handler */
.ae_handler = tlsEventHandler,
+ .addr = connTLSAddr,
/* create/close connection */
.close = connTLSClose,