Skip to content

Commit

Permalink
IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
beef9999 committed Oct 18, 2023
1 parent 90b6abe commit 0edbcb6
Show file tree
Hide file tree
Showing 14 changed files with 521 additions and 150 deletions.
18 changes: 17 additions & 1 deletion common/test/test_alog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ limitations under the License.
#include "../alog-functionptr.h"
#include "../alog-audit.h"
#include <gtest/gtest.h>
#include "photon/thread/thread.h"
#include <photon/thread/thread.h>
#include <photon/net/socket.h>
#include <chrono>
#include <vector>
#include <stdint.h>
Expand Down Expand Up @@ -556,6 +557,21 @@ TEST(ALog, LOG_LIMIT) {
EXPECT_LE(x, suppose + 3);
}

TEST(ALOG, IPAddr) {
log_output = &log_output_test;
DEFER(log_output = log_output_stdout);

photon::net::IPAddr ip("192.168.12.34");
EXPECT_STREQ(ip.to_string().c_str(), "192.168.12.34");
LOG_INFO(ip);
EXPECT_STREQ("192.168.12.34", log_output_test.log_start());

ip = photon::net::IPAddr("abcd:1111:222:33:4:5:6:7");
EXPECT_STREQ(ip.to_string().c_str(), "abcd:1111:222:33:4:5:6:7");
LOG_INFO(ip);
EXPECT_STREQ("abcd:1111:222:33:4:5:6:7", log_output_test.log_start());
}

int main(int argc, char **argv)
{
photon::vcpu_init();
Expand Down
10 changes: 5 additions & 5 deletions net/basic_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,11 @@ bool ISocketStream::skip_read(size_t count) {
}

int do_get_name(int fd, Getter getter, EndPoint& addr) {
struct sockaddr_in addr_in;
socklen_t len = sizeof(addr_in);
int ret = getter(fd, (struct sockaddr*) &addr_in, &len);
if (ret < 0 || len != sizeof(addr_in)) return -1;
addr.from_sockaddr_in(addr_in);
sockaddr_storage storage(addr);
socklen_t len = storage.get_socklen();
int ret = getter(fd, storage.get_sockaddr(), &len);
if (ret < 0 || len > storage.get_socklen()) return -1;
addr = storage.to_endpoint();
return 0;
}

Expand Down
22 changes: 11 additions & 11 deletions net/datagram_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,23 +139,23 @@ class UDP : public DatagramSocketBase {
virtual int connect(const Addr* addr, size_t addr_len) override {
auto ep = (EndPoint*)addr;
assert(ep && addr_len == sizeof(*ep));
auto in = ep->to_sockaddr_in();
return do_connect((sockaddr*)&in, sizeof(in));
sockaddr_storage s(*ep);
return do_connect(s.get_sockaddr(), s.get_socklen());
}
virtual int bind(const Addr* addr, size_t addr_len) override {
auto ep = (EndPoint*)addr;
assert(ep && addr_len == sizeof(*ep));
auto in = ep->to_sockaddr_in();
return do_bind((sockaddr*)&in, sizeof(in));
sockaddr_storage s(*ep);
return do_bind(s.get_sockaddr(), s.get_socklen());
}
virtual ssize_t send(const struct iovec* iov, int iovcnt, const Addr* addr,
size_t addr_len, int flags = 0) override {
auto ep = (EndPoint*)addr;
if (likely(!ep) || unlikely(addr_len != sizeof(*ep)))
return do_send(iov, iovcnt, nullptr, 0, flags);
assert(addr_len == sizeof(*ep));
auto in = ep->to_sockaddr_in();
return do_send(iov, iovcnt, (sockaddr*)&in, sizeof(in), flags);
sockaddr_storage s(*ep);
return do_send(iov, iovcnt, s.get_sockaddr(), s.get_socklen(), flags);
}
virtual ssize_t recv(const struct iovec* iov, int iovcnt, Addr* addr,
size_t* addr_len, int flags) override {
Expand All @@ -164,12 +164,12 @@ class UDP : public DatagramSocketBase {
return do_recv(iov, iovcnt, nullptr, 0, flags);
}

sockaddr_in in;
size_t alen = sizeof(in);
auto ret = do_recv(iov, iovcnt, (sockaddr*)&in, &alen, flags);
sockaddr_storage s(*ep);
size_t alen = s.get_socklen();
auto ret = do_recv(iov, iovcnt, s.get_sockaddr(), &alen, flags);
if (ret >= 0) {
ep->from(in);
*addr_len = sizeof(*ep);
*ep = s.to_endpoint();
*addr_len = alen;
}
return ret;
}
Expand Down
24 changes: 13 additions & 11 deletions net/http/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ class PooledDialer {
std::unique_ptr<Resolver> resolver;

//etsocket seems not support multi thread very well, use tcp_socket now. need to find out why
PooledDialer() :
explicit PooledDialer(bool ipv6) :
tls_ctx(new_tls_context(nullptr, nullptr, nullptr)),
tcpsock(new_tcp_socket_pool(new_tcp_socket_client(), -1, true)),
tlssock(new_tcp_socket_pool(new_tls_client(tls_ctx, new_tcp_socket_client(), true), -1, true)),
resolver(new_default_resolver(kDNSCacheLife)) {
auto tcp_cli = ipv6 ? new_tcp_socket_client_ipv6() : new_tcp_socket_client();
auto tls_cli = ipv6 ? new_tcp_socket_client_ipv6() : new_tcp_socket_client();
tcpsock.reset(new_tcp_socket_pool(tcp_cli, -1, true));
tlssock.reset(new_tcp_socket_pool(new_tls_client(tls_ctx, tls_cli, true), -1, true));
}

~PooledDialer() { delete tls_ctx; }
Expand Down Expand Up @@ -77,7 +79,7 @@ ISocketStream* PooledDialer::dial(std::string_view host, uint16_t port, bool sec
return sock;
}
LOG_DEBUG("connect ssl : ` ep : ` host : ` failed", secure, ep, host);
if (ipaddr.addr == 0) LOG_DEBUG("No connectable resolve result");
if (ipaddr.undefined()) LOG_DEBUG("No connectable resolve result");
// When failed, remove resolved result from dns cache so that following retries can try
// different ips.
resolver->discard_cache(strhost.c_str());
Expand All @@ -104,11 +106,11 @@ enum RoundtripStatus {

class ClientImpl : public Client {
public:
PooledDialer m_dialer;
std::unique_ptr<PooledDialer> m_dialer;
CommonHeaders<> m_common_headers;
ICookieJar *m_cookie_jar;
ClientImpl(ICookieJar *cookie_jar) :
m_cookie_jar(cookie_jar) {}
ClientImpl(ICookieJar *cookie_jar, bool ipv6) :
m_dialer(std::make_unique<PooledDialer>(ipv6)), m_cookie_jar(cookie_jar) {}

using SocketStream_ptr = std::unique_ptr<ISocketStream>;
int redirect(Operation* op) {
Expand Down Expand Up @@ -150,8 +152,8 @@ class ClientImpl : public Client {
LOG_ERROR_RETURN(ETIMEDOUT, ROUNDTRIP_FAILED, "connection timedout");
auto &req = op->req;
auto s = (m_proxy && !m_proxy_url.empty())
? m_dialer.dial(m_proxy_url, tmo.timeout())
: m_dialer.dial(req, tmo.timeout());
? m_dialer->dial(m_proxy_url, tmo.timeout())
: m_dialer->dial(req, tmo.timeout());
if (!s) LOG_ERROR_RETURN(0, ROUNDTRIP_NEED_RETRY, "connection failed");

SocketStream_ptr sock(s);
Expand Down Expand Up @@ -250,15 +252,15 @@ class ClientImpl : public Client {
}

ISocketStream* native_connect(std::string_view host, uint16_t port, bool secure, uint64_t timeout) override {
return m_dialer.dial(host, port, secure, timeout);
return m_dialer->dial(host, port, secure, timeout);
}

CommonHeaders<>* common_headers() override {
return &m_common_headers;
}
};

Client* new_http_client(ICookieJar *cookie_jar) { return new ClientImpl(cookie_jar); }
Client* new_http_client(ICookieJar *cookie_jar, bool ipv6) { return new ClientImpl(cookie_jar, ipv6); }

} // namespace http
} // namespace net
Expand Down
2 changes: 1 addition & 1 deletion net/http/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class Client : public Object {
};

//A Client without cookie_jar would ignore all response-header "Set-Cookies"
Client* new_http_client(ICookieJar *cookie_jar = nullptr);
Client* new_http_client(ICookieJar *cookie_jar = nullptr, bool ipv6 = false);

ICookieJar* new_simple_cookie_jar();

Expand Down
89 changes: 55 additions & 34 deletions net/kernel_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ limitations under the License.
#include <unordered_map>

#include <photon/common/alog.h>
#include <photon/common/alog-stdstring.h>
#include <photon/common/iovector.h>
#include <photon/io/fd-events.h>
#include <photon/thread/thread11.h>
Expand Down Expand Up @@ -60,20 +61,22 @@ limitations under the License.
#endif

LogBuffer& operator<<(LogBuffer& log, const in_addr& iaddr) {
return log << photon::net::IPAddr(ntohl(iaddr.s_addr));
return log << photon::net::IPAddr(iaddr);
}
LogBuffer& operator<<(LogBuffer& log, const in6_addr& iaddr) {
return log << photon::net::IPAddr(iaddr);
}

LogBuffer& operator<<(LogBuffer& log, const sockaddr_in& addr) {
return log << photon::net::EndPoint(addr);
photon::net::sockaddr_storage s(addr);
return log << s.to_endpoint();
}
LogBuffer& operator<<(LogBuffer& log, const sockaddr_in6& addr) {
photon::net::sockaddr_storage s(addr);
return log << s.to_endpoint();
}

LogBuffer& operator<<(LogBuffer& log, const sockaddr& addr) {
if (addr.sa_family == AF_INET) {
log << (const sockaddr_in&)addr;
} else {
log.printf("<sockaddr>");
}
return log;
photon::net::sockaddr_storage s(addr);
return log << s.to_endpoint();
}

namespace photon {
Expand All @@ -93,7 +96,7 @@ class KernelSocketStream : public SocketStreamBase {
} else {
fd = ::socket(socket_family, SOCK_STREAM, 0);
}
if (fd >= 0 && socket_family == AF_INET) {
if (fd >= 0 && (socket_family == AF_INET || socket_family == AF_INET6)) {
int val = 1;
::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t) sizeof(val));
}
Expand Down Expand Up @@ -214,18 +217,16 @@ class KernelSocketClient : public SocketClientBase {
ISocketStream* connect(const char* path, size_t count) override {
struct sockaddr_un addr_un;
if (fill_uds_path(addr_un, path, count) != 0) return nullptr;
return do_connect((const sockaddr*) &addr_un, nullptr, sizeof(addr_un));
return do_connect((const sockaddr*) &addr_un, sizeof(addr_un));
}

ISocketStream* connect(EndPoint remote, EndPoint local = EndPoint()) override {
sockaddr_in addr_remote = remote.to_sockaddr_in();
auto r = (sockaddr*) &addr_remote;
if (local.empty()) {
return do_connect(r, nullptr, sizeof(addr_remote));
sockaddr_storage r(remote);
if (local.undefined()) {
return do_connect(r.get_sockaddr(), r.get_socklen());
}
sockaddr_in addr_local = local.to_sockaddr_in();
auto l = (sockaddr*) &addr_local;
return do_connect(r, l, sizeof(addr_remote));
sockaddr_storage l(local);
return do_connect(r.get_sockaddr(), r.get_socklen(), l.get_sockaddr(), l.get_socklen());
}

protected:
Expand All @@ -240,7 +241,8 @@ class KernelSocketClient : public SocketClientBase {
return net::connect(fd, remote, addrlen, m_timeout);
}

ISocketStream* do_connect(const sockaddr* remote, const sockaddr* local, socklen_t addrlen) {
ISocketStream* do_connect(const sockaddr* remote, socklen_t len_remote,
const sockaddr* local = nullptr, socklen_t len_local = 0) {
auto stream = create_stream();
std::unique_ptr<KernelSocketStream> ptr(stream);
if (!ptr || ptr->fd < 0) {
Expand All @@ -251,11 +253,11 @@ class KernelSocketClient : public SocketClientBase {
}
ptr->timeout(m_timeout);
if (local != nullptr) {
if (::bind(ptr->fd, local, addrlen) != 0) {
if (::bind(ptr->fd, local, len_local) != 0) {
LOG_ERRNO_RETURN(0, nullptr, "fail to bind socket");
}
}
auto ret = fd_connect(ptr->fd, remote, addrlen);
auto ret = fd_connect(ptr->fd, remote, len_remote);
if (ret < 0) {
LOG_ERRNO_RETURN(0, nullptr, "Failed to connect socket");
}
Expand Down Expand Up @@ -300,7 +302,7 @@ class KernelSocketServer : public SocketServerBase {
if (m_listen_fd < 0) {
LOG_ERRNO_RETURN(0, -1, "fail to setup listen fd");
}
if (m_socket_family == AF_INET) {
if (m_socket_family == AF_INET || m_socket_family == AF_INET6) {
if (setsockopt<int>(IPPROTO_TCP, TCP_NODELAY, 1) != 0) {
LOG_ERRNO_RETURN(EINVAL, -1, "failed to setsockopt of TCP_NODELAY");
}
Expand Down Expand Up @@ -336,8 +338,11 @@ class KernelSocketServer : public SocketServerBase {
}

int bind(uint16_t port, IPAddr addr) override {
auto addr_in = EndPoint(addr, port).to_sockaddr_in();
return ::bind(m_listen_fd, (struct sockaddr*)&addr_in, sizeof(addr_in));
if (m_socket_family == AF_INET6 && addr.undefined()) {
addr = IPAddr::V6Any();
}
sockaddr_storage s(EndPoint(addr, port));
return ::bind(m_listen_fd, s.get_sockaddr(), s.get_socklen());
}

int bind(const char* path, size_t count) override {
Expand Down Expand Up @@ -419,11 +424,13 @@ class KernelSocketServer : public SocketServerBase {
int do_accept() { return fd_accept(m_listen_fd, nullptr, nullptr); }

int do_accept(EndPoint& remote_endpoint) {
struct sockaddr_in addr_in;
socklen_t len = sizeof(addr_in);
int cfd = fd_accept(m_listen_fd, (struct sockaddr*) &addr_in, &len);
if (cfd < 0 || len != sizeof(addr_in)) return -1;
remote_endpoint.from_sockaddr_in(addr_in);
sockaddr_storage s(remote_endpoint);
socklen_t len = s.get_socklen();

int cfd = fd_accept(m_listen_fd, s.get_sockaddr(), &len);
if (cfd < 0 || len > s.get_socklen())
return -1;
remote_endpoint = s.to_endpoint();
return cfd;
}

Expand Down Expand Up @@ -900,7 +907,8 @@ class ETKernelSocketStream : public KernelSocketStream, public NotifyContext {
if (fd >= 0) etpoller.register_notifier(fd, this);
}

ETKernelSocketStream() : KernelSocketStream(AF_INET, true) {
ETKernelSocketStream(int socket_family, bool nonblocking) :
KernelSocketStream(socket_family, nonblocking) {
if (fd >= 0) etpoller.register_notifier(fd, this);
}

Expand Down Expand Up @@ -947,7 +955,7 @@ class ETKernelSocketClient : public KernelSocketClient {

protected:
KernelSocketStream* create_stream() override {
return new ETKernelSocketStream();
return new ETKernelSocketStream(m_socket_family, m_nonblocking);
}
};

Expand Down Expand Up @@ -981,19 +989,32 @@ class ETKernelSocketServer : public KernelSocketServer, public NotifyContext {
/* ET Socket - End */

LogBuffer& operator<<(LogBuffer& log, const IPAddr addr) {
return log.printf(addr.d, '.', addr.c, '.', addr.b, '.', addr.a);
if (addr.is_ipv4())
return log.printf(addr.a, '.', addr.b, '.', addr.c, '.', addr.d);
else {
return log.printf(addr.to_string());
}
}

LogBuffer& operator<<(LogBuffer& log, const EndPoint ep) {
return log << ep.addr << ':' << ep.port;
if (ep.is_ipv4())
return log << ep.addr << ':' << ep.port;
else
return log << '[' << ep.addr << "]:" << ep.port;
}

extern "C" ISocketClient* new_tcp_socket_client() {
return new KernelSocketClient(AF_INET, true);
}
extern "C" ISocketClient* new_tcp_socket_client_ipv6() {
return new KernelSocketClient(AF_INET6, true);
}
extern "C" ISocketServer* new_tcp_socket_server() {
return NewObj<KernelSocketServer>(AF_INET, false, true)->init();
}
extern "C" ISocketServer* new_tcp_socket_server_ipv6() {
return NewObj<KernelSocketServer>(AF_INET6, false, true)->init();
}
extern "C" ISocketClient* new_uds_client() {
return new KernelSocketClient(AF_UNIX, true);
}
Expand Down
Loading

0 comments on commit 0edbcb6

Please sign in to comment.