Skip to content

Commit

Permalink
IPv6
Browse files Browse the repository at this point in the history
  • Loading branch information
beef9999 committed Oct 19, 2023
1 parent 90b6abe commit 1882cb7
Show file tree
Hide file tree
Showing 18 changed files with 550 additions and 166 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -DNDEBUG -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-O3 -g") # Only for CI test
set(CMAKE_CXX_FLAGS_MINSIZEREL "-O2 -g") # Only for CI test
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
Expand Down
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
1 change: 1 addition & 0 deletions include/photon/net/utils-stdstring.h
59 changes: 59 additions & 0 deletions net/base_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
Internal header provides abstract socket base class
***/

#include <netinet/in.h>
#include <vector>

#include <photon/net/socket.h>
Expand All @@ -37,6 +38,64 @@ Internal header provides abstract socket base class
namespace photon {
namespace net {

// sockaddr_storage is the container for any socket address type
struct sockaddr_storage {
sockaddr_storage() = default;
explicit sockaddr_storage(const EndPoint& ep) {
if (ep.is_ipv4()) {
auto* in4 = (sockaddr_in*) &store;
in4->sin_family = AF_INET;
in4->sin_port = htons(ep.port);
in4->sin_addr.s_addr = ep.addr.to_nl();
} else {
auto* in6 = (sockaddr_in6*) &store;
in6->sin6_family = AF_INET6;
in6->sin6_port = htons(ep.port);
in6->sin6_addr = ep.addr.addr;
}
}
explicit sockaddr_storage(const sockaddr_in& addr) {
*((sockaddr_in*) &store) = addr;
}
explicit sockaddr_storage(const sockaddr_in6& addr) {
*((sockaddr_in6*) &store) = addr;
}
explicit sockaddr_storage(const sockaddr& addr) {
*((sockaddr*) &store) = addr;
}
EndPoint to_endpoint() const {
EndPoint ep;
if (store.ss_family == AF_INET6) {
auto s6 = (sockaddr_in6*) &store;
ep.addr = IPAddr(s6->sin6_addr);
ep.port = ntohs(s6->sin6_port);
} else if (store.ss_family == AF_INET) {
auto s4 = (sockaddr_in*) &store;
ep.addr = IPAddr(s4->sin_addr);
ep.port = ntohs(s4->sin_port);
}
return ep;
}
sockaddr* get_sockaddr() const {
return (sockaddr*) &store;
}
socklen_t get_socklen() const {
switch (store.ss_family) {
case AF_INET:
return sizeof(sockaddr_in);
case AF_INET6:
return sizeof(sockaddr_in6);
default:
return 0;
}
}
socklen_t get_max_socklen() const {
return sizeof(store);
}
// store must be zero initialized
::sockaddr_storage store = {};
};

struct SocketOpt {
int level;
int opt_name;
Expand Down
11 changes: 6 additions & 5 deletions net/basic_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ limitations under the License.
#include <photon/common/alog.h>
#include <photon/common/iovector.h>
#include <photon/common/utility.h>
#include "base_socket.h"

#ifndef MSG_ZEROCOPY
#define MSG_ZEROCOPY 0x4000000
Expand Down Expand Up @@ -262,11 +263,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_max_socklen();
int ret = getter(fd, storage.get_sockaddr(), &len);
if (ret < 0 || len > storage.get_max_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
Loading

0 comments on commit 1882cb7

Please sign in to comment.