diff options
author | zhenwei pi <pizhenwei@bytedance.com> | 2022-07-27 10:08:32 +0800 |
---|---|---|
committer | zhenwei pi <pizhenwei@bytedance.com> | 2022-08-22 15:01:40 +0800 |
commit | bff7ecc7864716c14fbb399f19acaee364975b29 (patch) | |
tree | 7f342f044ee6e39769b55e1a1754abb4ffc39dac | |
parent | b9d77288243aeab306b99ff72a71d8490a91e0a8 (diff) | |
download | redis-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.c | 21 | ||||
-rw-r--r-- | src/anet.h | 7 | ||||
-rw-r--r-- | src/cluster.c | 4 | ||||
-rw-r--r-- | src/connection.h | 45 | ||||
-rw-r--r-- | src/module.c | 2 | ||||
-rw-r--r-- | src/networking.c | 14 | ||||
-rw-r--r-- | src/redis-cli.c | 3 | ||||
-rw-r--r-- | src/replication.c | 11 | ||||
-rw-r--r-- | src/sentinel.c | 2 | ||||
-rw-r--r-- | src/server.c | 2 | ||||
-rw-r--r-- | src/socket.c | 25 | ||||
-rw-r--r-- | src/tls.c | 5 |
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); @@ -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, |