Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix-http-resolve-for-ipv6 #225

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.linux.arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Linux ARM

on:
push:
branches: [ "main" ]
branches: [ "main", "release/*" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "release/*" ]

jobs:
centos8-gcc921-epoll-release:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.linux.x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Linux x86

on:
push:
branches: [ "main" ]
branches: [ "main", "release/*" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "release/*" ]

jobs:
centos8-gcc921-epoll-release:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.macos.arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: macOS ARM

on:
push:
branches: [ "main" ]
branches: [ "main", "release/*" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "release/*" ]

jobs:
macOS-clang-debug:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: macOS

on:
push:
branches: [ "main" ]
branches: [ "main", "release/*" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "release/*" ]

jobs:
macOS-12-Monterey-debug:
Expand Down
65 changes: 46 additions & 19 deletions doc/docs/api/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Network lib provides non-blocking socket implementations for clients and servers
ISocketClient* new_tcp_socket_client();
ISocketServer* new_tcp_socket_server();

ISocketClient* new_tcp_socket_client_ipv6();
ISocketServer* new_tcp_socket_server_ipv6();

ISocketClient* new_uds_client();
ISocketServer* new_uds_server(bool autoremove = false);

Expand All @@ -42,6 +45,11 @@ ISocketClient* new_fstack_dpdk_socket_client();
ISocketServer* new_fstack_dpdk_socket_server();
```

:::note
An IPv6 socket server listening on `::0` can handle both v4 and v6 socket client.
:::


#### Class Method

```cpp
Expand Down Expand Up @@ -95,36 +103,55 @@ namespace net {
}
```

#### IPv4 Address
#### Address and Endpoint
```cpp
namespace photon {
namespace net {
union IPAddr {
// Save IP address as a 32 bits integer, or 4 bytes.
uint32_t addr = 0;
struct { uint8_t a, b, c, d; };

// Create from the Internet host address, in network byte order, or from string
struct IPAddr {
in6_addr addr;
// For compatibility, the default constructor is still 0.0.0.0 (IPv4)
IPAddr();
// V6 constructor (Internet Address)
explicit IPAddr(in6_addr internet_addr);
// V6 constructor (Network byte order)
IPAddr(uint32_t nl1, uint32_t nl2, uint32_t nl3, uint32_t nl4);
// V4 constructor (Internet Address)
explicit IPAddr(in_addr internet_addr);
// V4 constructor (Network byte order)
explicit IPAddr(uint32_t nl);
explicit IPAddr(const char* s)

// String constructor
explicit IPAddr(const char* s);
// Check if it's actually an IPv4 address mapped in IPV6
bool is_ipv4();
// We regard the default IPv4 0.0.0.0 as undefined
bool undefined();
// Should ONLY be used for IPv4 address
uint32_t to_nl() const;
void from_nl(uint32_t nl);
bool is_loopback() const;
bool is_broadcast() const;
bool is_link_local() const;
bool operator==(const IPAddr& rhs) const;
bool operator!=(const IPAddr& rhs) const;
static IPAddr V6None();
static IPAddr V6Any();
static IPAddr V6Loopback();
static IPAddr V4Broadcast();
static IPAddr V4Any();
static IPAddr V4Loopback();
};

// EndPoint represents IP address and port
// A default endpoint is undefined (0.0.0.0:0)
struct EndPoint {
IPAddr addr;
uint16_t port;

// convert from the typical struct sockaddr_in
sockaddr_in to_sockaddr_in() const;
void from_sockaddr_in(const struct sockaddr_in& addr_in);
uint16_t port = 0;
EndPoint() = default;
EndPoint(IPAddr ip, uint16_t port);
bool is_ipv4() const;
bool operator==(const EndPoint& rhs) const;
bool operator!=(const EndPoint& rhs) const;
bool undefined() const;
};

// operators to help logging IP addresses with alog
LogBuffer& operator << (LogBuffer& log, const IPAddr addr);
LogBuffer& operator << (LogBuffer& log, const EndPoint ep);
}
}
```
Expand Down
10 changes: 8 additions & 2 deletions doc/docs/introduction/how-to-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ cmake --build build -j

```bash
cd PhotonLibOS
# Use `brew info openssl` to find openssl path
cmake -B build -D OPENSSL_ROOT_DIR=/path/to/openssl/
cmake -B build
cmake --build build -j
```

Expand Down Expand Up @@ -178,3 +177,10 @@ ctest
| PHOTON_ENABLE_FSTACK_DPDK | OFF | Enable F-Stack and DPDK. Requires both. |
| PHOTON_ENABLE_EXTFS | OFF | Enable extfs. Requires `libe2fs` |

#### Example

If there is any shared lib you don't want Photon to link to on local host, build its static from source.

```bash
cmake -B build -D PHOTON_BUILD_DEPENDENCIES=ON -D PHOTON_GFLAGS_SOURCE=https://github.com/gflags/gflags/archive/refs/tags/v2.2.2.tar.gz
```
5 changes: 3 additions & 2 deletions net/http/test/client_function_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ TEST(http_client, get) {
auto op2 = client->new_operation(Verb::GET, target);
DEFER(delete op2);
op2->req.headers.content_length(0);
client->call(op2);
int ret = client->call(op2);
GTEST_ASSERT_EQ(0, ret);

char resp_body_buf[1024];
EXPECT_EQ(sizeof(socket_buf), op2->resp.resource_size());
auto ret = op2->resp.read(resp_body_buf, sizeof(socket_buf));
ret = op2->resp.read(resp_body_buf, sizeof(socket_buf));
EXPECT_EQ(sizeof(socket_buf), ret);
resp_body_buf[sizeof(socket_buf) - 1] = '\0';
LOG_DEBUG(resp_body_buf);
Expand Down
26 changes: 19 additions & 7 deletions net/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,23 +256,34 @@ bool Base64Decode(std::string_view in, std::string &out) {

class DefaultResolver : public Resolver {
public:
DefaultResolver(uint64_t cache_ttl, uint64_t resolve_timeout)
: dnscache_(cache_ttl), resolve_timeout_(resolve_timeout) {}
DefaultResolver(uint64_t cache_ttl, uint64_t resolve_timeout, bool ipv6)
: dnscache_(cache_ttl), resolve_timeout_(resolve_timeout), ipv6_(ipv6) {}
~DefaultResolver() { dnscache_.clear(); }

IPAddr resolve(const char *host) override {
auto ctr = [&]() -> IPAddr * {
auto *ip = new IPAddr();
std::vector<IPAddr> addrs;
photon::semaphore sem;
std::thread([&]() {
*ip = gethostbyname(host);
int ret = gethostbyname(host, addrs);
if (ret < 0) {
addrs.clear();
}
sem.signal(1);
}).detach();
auto ret = sem.wait(1, resolve_timeout_);
if (ret < 0 && errno == ETIMEDOUT) {
LOG_WARN("Domain resolution for ` timeout!", host);
return new IPAddr; // undefined addr
} else if (addrs.empty()) {
LOG_WARN("Domain resolution for ` failed", host);
return new IPAddr; // undefined addr
}
return ip;
for (auto& each : addrs) {
if ((each.is_ipv4() ^ !ipv6_) == 0)
return new IPAddr(each);
}
return new IPAddr; // undefined addr
};
return *(dnscache_.borrow(host, ctr));
}
Expand All @@ -287,10 +298,11 @@ class DefaultResolver : public Resolver {
private:
ObjectCache<std::string, IPAddr *> dnscache_;
uint64_t resolve_timeout_;
bool ipv6_;
};

Resolver* new_default_resolver(uint64_t cache_ttl, uint64_t resolve_timeout) {
return new DefaultResolver(cache_ttl, resolve_timeout);
Resolver* new_default_resolver(uint64_t cache_ttl, uint64_t resolve_timeout, bool ipv6) {
return new DefaultResolver(cache_ttl, resolve_timeout, ipv6);
}

} // namespace net
Expand Down
5 changes: 3 additions & 2 deletions net/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ bool zerocopy_available();
*/
class Resolver : public Object {
public:
// When failed, IPAddr(0) should be returned.
// When failed, return an Undefined IPAddr
// Normally dns servers return multiple ips in random order, choosing the first one should suffice.
virtual IPAddr resolve(const char* host) = 0;
virtual void resolve(const char* host, Delegate<void, IPAddr> func) = 0;
Expand All @@ -165,9 +165,10 @@ class Resolver : public Object {
*
* @param cache_ttl cache's lifetime in microseconds.
* @param resolve_timeout timeout in microseconds for domain resolution.
* @param ipv6 specify v4 or v6 domain name
* @return Resolver*
*/
Resolver* new_default_resolver(uint64_t cache_ttl = 3600UL * 1000000, uint64_t resolve_timeout = -1);
Resolver* new_default_resolver(uint64_t cache_ttl = 3600UL * 1000000, uint64_t resolve_timeout = -1, bool ipv6 = false);

} // namespace net
}
Loading