Skip to content

Commit

Permalink
Support to listen on the IPV6 address (#554)
Browse files Browse the repository at this point in the history
  • Loading branch information
git-hulk authored May 14, 2022
1 parent 518549f commit a86f4d0
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 24 deletions.
2 changes: 1 addition & 1 deletion kvrocks.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1
# bind 127.0.0.1 ::1
bind 0.0.0.0

# Unix socket.
Expand Down
14 changes: 10 additions & 4 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,21 +306,27 @@ Status SockReadLine(int fd, std::string *data) {
}

int GetPeerAddr(int fd, std::string *addr, uint32_t *port) {
addr->clear();

sockaddr_storage sa{};
socklen_t sa_len = sizeof(sa);
if (getpeername(fd, reinterpret_cast<sockaddr *>(&sa), &sa_len) < 0) {
return -1;
}
if (sa.ss_family == AF_INET) {
if (sa.ss_family == AF_INET6) {
char buf[INET6_ADDRSTRLEN];
auto sa6 = reinterpret_cast<sockaddr_in6 *>(&sa);
inet_ntop(AF_INET6, reinterpret_cast<void *>(&sa6->sin6_addr), buf, INET_ADDRSTRLEN);
addr->append(buf);
*port = ntohs(sa6->sin6_port);
} else {
auto sa4 = reinterpret_cast<sockaddr_in *>(&sa);
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, reinterpret_cast<void *>(&sa4->sin_addr), buf, INET_ADDRSTRLEN);
addr->clear();
addr->append(buf);
*port = ntohs(sa4->sin_port);
return 0;
}
return -2; // only support AF_INET currently
return 0;
}

Status DecimalStringToNum(const std::string &str, int64_t *n, int64_t min, int64_t max) {
Expand Down
65 changes: 46 additions & 19 deletions src/worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ Worker::Worker(Server *svr, Config *config, bool repl) : svr_(svr) {
timeval tm = {10, 0};
evtimer_add(timer_, &tm);

Status s;
int port = config->port;
auto binds = config->binds;
for (const auto &bind : binds) {
Status s = listenTCP(bind, port, config->backlog);
s = listenTCP(bind, port, config->backlog);
if (!s.IsOK()) {
LOG(ERROR) << "[worker] Failed to listen on: "<< bind << ":" << port
<< ", encounter error: " << s.Msg();
Expand Down Expand Up @@ -154,27 +155,53 @@ void Worker::newUnixSocketConnection(evconnlistener *listener, evutil_socket_t f
}

Status Worker::listenTCP(const std::string &host, int port, int backlog) {
sockaddr_in sin{};
sin.sin_family = AF_INET;
evutil_inet_pton(AF_INET, host.data(), &(sin.sin_addr));
sin.sin_port = htons(port);
int fd = socket(AF_INET, SOCK_STREAM, 0);
int sock_opt = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt)) < 0) {
return Status(Status::NotOK, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
}
// to support multi-thread binding on macOS
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &sock_opt, sizeof(sock_opt)) < 0) {
return Status(Status::NotOK, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
char _port[6];
int af, rv, fd, sock_opt = 1;

if (strchr(host.data(), ':')) {
af = AF_INET6;
} else {
af = AF_INET;
}
snprintf(_port, sizeof(_port), "%d", port);
struct addrinfo hints, *srv_info, *p;
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

if ((rv = getaddrinfo(host.data(), _port, &hints, &srv_info)) != 0) {
return Status(Status::NotOK, gai_strerror(rv));
}
if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
return Status(Status::NotOK, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));

for (p = srv_info; p != nullptr; p = p->ai_next) {
if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
continue;
if (af == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &sock_opt, sizeof(sock_opt)) == -1) {
goto error;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt, sizeof(sock_opt)) < 0) {
goto error;
}
// to support multi-thread binding on macOS
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &sock_opt, sizeof(sock_opt)) < 0) {
goto error;
}
if (bind(fd, p->ai_addr, p->ai_addrlen)) {
goto error;
}
evutil_make_socket_nonblocking(fd);
auto lev = evconnlistener_new(base_, newTCPConnection, this,
LEV_OPT_CLOSE_ON_FREE, backlog, fd);
listen_events_.emplace_back(lev);
}
evutil_make_socket_nonblocking(fd);
auto lev = evconnlistener_new(base_, newTCPConnection, this,
LEV_OPT_CLOSE_ON_FREE, backlog, fd);
listen_events_.emplace_back(lev);

freeaddrinfo(srv_info);
return Status::OK();

error:
freeaddrinfo(srv_info);
return Status(Status::NotOK, evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
}

Status Worker::ListenUnixSocket(const std::string &path, int perm, int backlog) {
Expand Down

0 comments on commit a86f4d0

Please sign in to comment.