Skip to content

Commit

Permalink
parse_address_list()
Browse files Browse the repository at this point in the history
  • Loading branch information
lihuiba committed Oct 7, 2024
1 parent ec1e8de commit 0a5880d
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 18 deletions.
50 changes: 34 additions & 16 deletions net/kernel_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1040,25 +1040,43 @@ extern "C" ISocketServer* new_fstack_dpdk_socket_server() {

/* Implementations in socket.h */

EndPoint::EndPoint(const char* _ep) {
estring_view ep(_ep);
static int parse_port(estring_view& ep) {
auto pos = ep.find_last_of(':');
if (pos == 0 || pos == estring::npos)
return;
if (pos == estring::npos) return -1;
auto port_str = ep.substr(pos + 1);
if (!port_str.all_digits())
return;
auto _port = port_str.to_uint64();
if (_port > UINT16_MAX)
return;
port = (uint16_t)_port;
auto ipsv = (ep[0] == '[') ? ep.substr(1, pos - 2) : ep.substr(0, pos);
if (ipsv.length() >= INET6_ADDRSTRLEN - 1)
return;
if (!port_str.all_digits()) return -1;
auto port = port_str.to_uint64();
if (port > UINT16_MAX) return -1;
ep = (pos > 2 && ep[0] == '[') ? ep.substr(1, pos - 2)
: ep.substr(0, pos);
return (int)port;
}

static void parse_addr(std::string_view s, IPAddr* addr) {
if (s.length() >= INET6_ADDRSTRLEN - 1) return;
char ip_str[INET6_ADDRSTRLEN];
memcpy(ip_str, ipsv.data(), ipsv.length());
ip_str[ipsv.length()] = '\0';
addr = IPAddr(ip_str);
memcpy(ip_str, s.data(), s.length());
ip_str[s.length()] = '\0';
*addr = IPAddr(ip_str);
}

EndPoint::EndPoint(const char* s_) {
estring_view s(s_);
if (s.empty()) return;
int port_ = parse_port(s);
if (port_ < 0) return;
port = (uint16_t)port_;
parse_addr(s, &addr);
}

EndPoint EndPoint::parse(std::string_view s, uint16_t default_port) {
if (s.empty()) return {};
int port = parse_port((estring_view&)s);
if (port < 0) port = default_port;
IPAddr addr;
parse_addr(s, &addr);
if (addr.undefined()) return {};
return {addr, (uint16_t)port};
}

LogBuffer& operator<<(LogBuffer& log, const IPAddr& addr) {
Expand Down
4 changes: 3 additions & 1 deletion net/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ limitations under the License.
#include <photon/common/stream.h>
#include <photon/common/callback.h>
#include <photon/common/object.h>
#include <photon/common/string_view.h>

#ifdef __linux__
#define _in_addr_field s6_addr32
Expand Down Expand Up @@ -154,9 +155,10 @@ namespace net {
IPAddr addr;
uint16_t port = 0;
EndPoint() = default;
explicit EndPoint(const char* ep);
EndPoint(IPAddr ip, uint16_t port) : addr(ip), port(port) {}
explicit EndPoint(const char* ep);
EndPoint(const char* ip, uint16_t port) : addr(ip), port(port) {}
static EndPoint parse(std::string_view ep, uint16_t default_port);
bool is_ipv4() const {
return addr.is_ipv4();
};
Expand Down
3 changes: 3 additions & 0 deletions net/test/test-ipv6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
TEST(ipv6, endpoint) {
auto c = photon::net::EndPoint("127.0.0.1");
EXPECT_TRUE(c.undefined()); // must have ':port' included
c = photon::net::EndPoint::parse("127.0.0.1", 1234);
EXPECT_FALSE(c.undefined());
EXPECT_EQ(c.port, 1234);
c = photon::net::EndPoint("127.0.0.1:8888");
EXPECT_FALSE(c.undefined());
c = photon::net::EndPoint("[::1]:8888");
Expand Down
15 changes: 14 additions & 1 deletion net/test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ TEST(Socket, endpoint) {

photon::net::sockaddr_storage s(saddrin);
ep = s.to_endpoint();
EXPECT_TRUE(ep == EndPoint(IPAddr("12.34.56.78"), 4321));
IPAddr addr12345678("12.34.56.78");
EXPECT_TRUE(ep == EndPoint(addr12345678, 4321));

auto rsai = (sockaddr_in*) s.get_sockaddr();
EXPECT_EQ(saddrin.sin_addr.s_addr, rsai->sin_addr.s_addr);
Expand All @@ -200,6 +201,18 @@ TEST(Socket, endpoint) {
LOG_DEBUG(ep.addr);
EXPECT_NE(nullptr, strstr(log_output_test._log_buf, "12.34.56.78"));
log_output = log_output_stdout;

EndPoint epfsv1("12.34.56.78:4321"), epfsv2("12.34.56.78", 4321);
EXPECT_EQ(epfsv1.addr, addr12345678);
EXPECT_EQ(epfsv1.port, 4321);
EXPECT_EQ(epfsv1, epfsv2);

std::vector<EndPoint> addrs;
parse_address_list("1.1.1.1:1,2.2.2.2:2,3.3.3.3:3,4.4.4.4", &addrs, 4);
EXPECT_EQ(addrs[0], EndPoint("1.1.1.1:1"));
EXPECT_EQ(addrs[1], EndPoint("2.2.2.2:2"));
EXPECT_EQ(addrs[2], EndPoint("3.3.3.3:3"));
EXPECT_EQ(addrs[3], EndPoint("4.4.4.4:4"));
}

TEST(Socket, timeout) {
Expand Down
14 changes: 14 additions & 0 deletions net/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,5 +343,19 @@ Resolver* new_default_resolver(uint64_t cache_ttl, uint64_t resolve_timeout) {
return new DefaultResolver(cache_ttl, resolve_timeout);
}

int parse_address_list(std::string_view list, std::vector<EndPoint>* addresses, uint16_t default_port) {
addresses->clear();
if (list.empty()) return 0;
for (auto p = list.begin(); p < list.end();) {
auto q = p + 1;
while (q < list.end() && *q != ',') ++q;
std::string_view epsv(p, q - p);
addresses->push_back(EndPoint::parse(epsv, default_port));
p = q + 1;
}
return 0;
}


} // namespace net
}
4 changes: 4 additions & 0 deletions net/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,9 @@ class Resolver : public Object {
*/
Resolver* new_default_resolver(uint64_t cache_ttl = 3600UL * 1000000, uint64_t resolve_timeout = -1);

// parse a string list of endpoints into vector
// ip[:port],ip[:port],ip[:port],...
int parse_address_list(std::string_view list, std::vector<EndPoint>* addresses, uint16_t default_port = 0);

} // namespace net
}

0 comments on commit 0a5880d

Please sign in to comment.