feat add byte_order
This commit is contained in:
parent
9bad174e0e
commit
72d4092a9e
@ -297,6 +297,7 @@ if(TILE_BUILD_TESTS)
|
|||||||
|
|
||||||
tile_add_test(io_util_rate_limiter_test "tile/io/util/rate_limiter_test.cc")
|
tile_add_test(io_util_rate_limiter_test "tile/io/util/rate_limiter_test.cc")
|
||||||
tile_add_test(base_exposed_var_test "tile/base/exposed_var_test.cc")
|
tile_add_test(base_exposed_var_test "tile/base/exposed_var_test.cc")
|
||||||
|
tile_add_test(base_byte_order_test "tile/base/byte_order_test.cc")
|
||||||
# tile_add_test(fiber_detail_scheduler_test "tile/fiber/detail/scheduler_test.cc")
|
# tile_add_test(fiber_detail_scheduler_test "tile/fiber/detail/scheduler_test.cc")
|
||||||
tile_add_test(base_internal_meta_test "tile/base/internal/meta_test.cc")
|
tile_add_test(base_internal_meta_test "tile/base/internal/meta_test.cc")
|
||||||
# tile_add_test(net_internal_http_engine_test
|
# tile_add_test(net_internal_http_engine_test
|
||||||
|
126
tile/base/byte_order.h
Normal file
126
tile/base/byte_order.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#ifndef TILE_BASE_BYTE_ORDER_H
|
||||||
|
#define TILE_BASE_BYTE_ORDER_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#define TILE_BYTE_ORDER __BYTE_ORDER__
|
||||||
|
#define TILE_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
|
||||||
|
#define TILE_BIG_ENDIAN __ORDER_BIG_ENDIAN__
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
#define htobe16(v) htons(v)
|
||||||
|
#define htobe32(v) htonl(v)
|
||||||
|
#define be16toh(v) ntohs(v)
|
||||||
|
#define be32toh(v) ntohl(v)
|
||||||
|
#define htole16(v) (v)
|
||||||
|
#define htole32(v) (v)
|
||||||
|
#define htole64(v) (v)
|
||||||
|
#define le16toh(v) (v)
|
||||||
|
#define le32toh(v) (v)
|
||||||
|
#define le64toh(v) (v)
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
#define htobe16(v) (v)
|
||||||
|
#define htobe32(v) (v)
|
||||||
|
#define be16toh(v) (v)
|
||||||
|
#define be32toh(v) (v)
|
||||||
|
#define htole16(v) __builtin_bswap16(v)
|
||||||
|
#define htole32(v) __builtin_bswap32(v)
|
||||||
|
#define htole64(v) __builtin_bswap64(v)
|
||||||
|
#define le16toh(v) __builtin_bswap16(v)
|
||||||
|
#define le32toh(v) __builtin_bswap32(v)
|
||||||
|
#define le64toh(v) __builtin_bswap64(v)
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tile {
|
||||||
|
|
||||||
|
inline uint16_t ByteSwap16(uint16_t val) { return __builtin_bswap16(val); }
|
||||||
|
inline uint32_t ByteSwap32(uint32_t val) { return __builtin_bswap32(val); }
|
||||||
|
inline uint64_t ByteSwap64(uint64_t val) { return __builtin_bswap64(val); }
|
||||||
|
|
||||||
|
inline bool IsHostLittleEndian() {
|
||||||
|
#if TILE_LITTLE_ENDIAN == TILE_BYTE_ORDER
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsHostBigEndian() {
|
||||||
|
#if TILE_BIG_ENDIAN == TILE_BYTE_ORDER
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t HostToNetwork16(uint16_t val_in_host) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_host;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap16(val_in_host);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t HostToNetwork32(uint32_t val_in_host) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_host;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap32(val_in_host);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t HostToNetwork64(uint64_t val_in_host) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_host;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap64(val_in_host);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t NetworkToHost16(uint16_t val_in_network) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_network;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap16(val_in_network);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t NetworkToHost32(uint32_t val_in_network) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_network;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap32(val_in_network);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t NetworkToHost64(uint64_t val_in_network) {
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
return val_in_network;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
return ByteSwap64(val_in_network);
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tile
|
||||||
|
|
||||||
|
#endif // TILE_BASE_BYTE_ORDER_H
|
116
tile/base/byte_order_test.cc
Normal file
116
tile/base/byte_order_test.cc
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include "tile/base/byte_order.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace tile {
|
||||||
|
|
||||||
|
static union EndianHelper {
|
||||||
|
uint16_t v16;
|
||||||
|
uint32_t v32;
|
||||||
|
uint32_t v64;
|
||||||
|
uint8_t bytes[8];
|
||||||
|
} endian_helper = {.bytes = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}};
|
||||||
|
|
||||||
|
TEST(ByteOrder, ByteSwap16) {
|
||||||
|
const uint16_t val = 0x1234;
|
||||||
|
const uint16_t expected = 0x3412;
|
||||||
|
ASSERT_EQ(expected, ByteSwap16(val));
|
||||||
|
}
|
||||||
|
TEST(ByteOrder, ByteSwap32) {
|
||||||
|
const uint32_t val = 0x12345678;
|
||||||
|
const uint32_t expected = 0x78563412;
|
||||||
|
ASSERT_EQ(expected, ByteSwap32(val));
|
||||||
|
}
|
||||||
|
TEST(ByteOrder, ByteSwap64) {
|
||||||
|
const uint64_t val = 0x1234567890abcdef;
|
||||||
|
const uint64_t expected = 0xefcdab9078563412;
|
||||||
|
ASSERT_EQ(expected, ByteSwap64(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, IsHostByteOrder) {
|
||||||
|
ASSERT_NE(IsHostBigEndian(), IsHostLittleEndian());
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
ASSERT_TRUE(IsHostBigEndian());
|
||||||
|
ASSERT_FALSE(IsHostLittleEndian());
|
||||||
|
#else
|
||||||
|
ASSERT_TRUE(IsHostLittleEndian());
|
||||||
|
ASSERT_FALSE(IsHostBigEndian());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, HostToNetwork16) {
|
||||||
|
const uint16_t val = 0x1234;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint16_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint16_t expected = 0x3412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, HostToNetwork16(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, HostToNetwork32) {
|
||||||
|
const uint32_t val = 0x12345678;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint32_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint32_t expected = 0x78563412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, HostToNetwork32(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, HostToNetwork64) {
|
||||||
|
const uint64_t val = 0x1234567890abcdef;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint64_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint64_t expected = 0xefcdab9078563412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, HostToNetwork64(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, NetworkToHost16) {
|
||||||
|
const uint16_t val = 0x1234;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint16_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint16_t expected = 0x3412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, NetworkToHost16(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, NetworkToHost32) {
|
||||||
|
const uint32_t val = 0x12345678;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint32_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint32_t expected = 0x78563412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, NetworkToHost32(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ByteOrder, NetworkToHost64) {
|
||||||
|
const uint64_t val = 0x1234567890abcdef;
|
||||||
|
#if TILE_BYTE_ORDER == TILE_BIG_ENDIAN
|
||||||
|
const uint64_t expected = val;
|
||||||
|
#elif TILE_BYTE_ORDER == TILE_LITTLE_ENDIAN
|
||||||
|
const uint64_t expected = 0xefcdab9078563412;
|
||||||
|
#else
|
||||||
|
#error "Unsupported byte order"
|
||||||
|
#endif
|
||||||
|
ASSERT_EQ(expected, NetworkToHost64(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tile
|
@ -1,5 +1,6 @@
|
|||||||
#include "tile/base/net/endpoint.h"
|
#include "tile/base/net/endpoint.h"
|
||||||
|
|
||||||
|
#include "tile/base/byte_order.h"
|
||||||
#include "tile/base/config.h"
|
#include "tile/base/config.h"
|
||||||
#include "tile/base/string.h"
|
#include "tile/base/string.h"
|
||||||
|
|
||||||
@ -27,16 +28,16 @@ std::string SockAddrToString(const sockaddr *addr, socklen_t length) {
|
|||||||
switch (af) {
|
switch (af) {
|
||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
auto p = reinterpret_cast<const sockaddr_in *>(addr);
|
auto p = reinterpret_cast<const sockaddr_in *>(addr);
|
||||||
uint32_t s_addr = ntohl(p->sin_addr.s_addr);
|
uint32_t s_addr = NetworkToHost32(p->sin_addr.s_addr);
|
||||||
return Format("{}.{}.{}.{}:{}", (s_addr >> 24) & 0xff,
|
return Format("{}.{}.{}.{}:{}", (s_addr >> 24) & 0xff,
|
||||||
(s_addr >> 16) & 0xff, (s_addr >> 8) & 0xff, s_addr & 0xff,
|
(s_addr >> 16) & 0xff, (s_addr >> 8) & 0xff, s_addr & 0xff,
|
||||||
ntohs(p->sin_port));
|
NetworkToHost16(p->sin_port));
|
||||||
}
|
}
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
auto p = reinterpret_cast<const sockaddr_in6 *>(addr);
|
auto p = reinterpret_cast<const sockaddr_in6 *>(addr);
|
||||||
char ip[INET6_ADDRSTRLEN];
|
char ip[INET6_ADDRSTRLEN];
|
||||||
TILE_CHECK(inet_ntop(af, &p->sin6_addr, ip, INET6_ADDRSTRLEN));
|
TILE_CHECK(inet_ntop(af, &p->sin6_addr, ip, INET6_ADDRSTRLEN));
|
||||||
return Format("[{}]:{}", ip, ntohs(p->sin6_port));
|
return Format("[{}]:{}", ip, NetworkToHost16(p->sin6_port));
|
||||||
}
|
}
|
||||||
case AF_UNIX: {
|
case AF_UNIX: {
|
||||||
auto p = reinterpret_cast<const sockaddr_un *>(addr);
|
auto p = reinterpret_cast<const sockaddr_un *>(addr);
|
||||||
@ -119,7 +120,7 @@ Endpoint EndpointFromIpv4(const std::string &ip, std::uint16_t port) {
|
|||||||
memset(p, 0, sizeof(sockaddr_in));
|
memset(p, 0, sizeof(sockaddr_in));
|
||||||
TILE_PCHECK(inet_pton(AF_INET, ip.c_str(), &p->sin_addr), "Cannot parse [{}]",
|
TILE_PCHECK(inet_pton(AF_INET, ip.c_str(), &p->sin_addr), "Cannot parse [{}]",
|
||||||
ip);
|
ip);
|
||||||
p->sin_port = htons(port);
|
p->sin_port = HostToNetwork16(port);
|
||||||
p->sin_family = AF_INET;
|
p->sin_family = AF_INET;
|
||||||
*er.RetrieveLength() = sizeof(sockaddr_in);
|
*er.RetrieveLength() = sizeof(sockaddr_in);
|
||||||
return er.Build();
|
return er.Build();
|
||||||
@ -132,7 +133,7 @@ Endpoint EndpointFromIpv6(const std::string &ip, std::uint16_t port) {
|
|||||||
memset(p, 0, sizeof(sockaddr_in6));
|
memset(p, 0, sizeof(sockaddr_in6));
|
||||||
TILE_PCHECK(inet_pton(AF_INET6, ip.c_str(), &p->sin6_addr),
|
TILE_PCHECK(inet_pton(AF_INET6, ip.c_str(), &p->sin6_addr),
|
||||||
"Cannot parse [{}]", ip);
|
"Cannot parse [{}]", ip);
|
||||||
p->sin6_port = htons(port);
|
p->sin6_port = HostToNetwork16(port);
|
||||||
p->sin6_family = AF_INET6;
|
p->sin6_family = AF_INET6;
|
||||||
*er.RetrieveLength() = sizeof(sockaddr_in6);
|
*er.RetrieveLength() = sizeof(sockaddr_in6);
|
||||||
return er.Build();
|
return er.Build();
|
||||||
@ -186,10 +187,10 @@ std::uint16_t EndpointGetPort(const Endpoint &endpoint) {
|
|||||||
"Unexpected: Address family #{} is not valid IP address family.",
|
"Unexpected: Address family #{} is not valid IP address family.",
|
||||||
endpoint.Family());
|
endpoint.Family());
|
||||||
if (endpoint.Family() == AF_INET) {
|
if (endpoint.Family() == AF_INET) {
|
||||||
return ntohs(
|
return NetworkToHost16(
|
||||||
reinterpret_cast<const sockaddr_in *>(endpoint.Get())->sin_port);
|
reinterpret_cast<const sockaddr_in *>(endpoint.Get())->sin_port);
|
||||||
} else if (endpoint.Family() == AF_INET6) {
|
} else if (endpoint.Family() == AF_INET6) {
|
||||||
return ntohs(
|
return NetworkToHost16(
|
||||||
reinterpret_cast<const sockaddr_in6 *>(endpoint.Get())->sin6_port);
|
reinterpret_cast<const sockaddr_in6 *>(endpoint.Get())->sin6_port);
|
||||||
}
|
}
|
||||||
TILE_NOT_IMPLEMENTED("Unsupported family [{}]", endpoint.Family());
|
TILE_NOT_IMPLEMENTED("Unsupported family [{}]", endpoint.Family());
|
||||||
@ -284,7 +285,7 @@ bool IsPrivateIpv4AddressRfc(const Endpoint &addr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ip = ntohl(addr.UnsafeGet<sockaddr_in>()->sin_addr.s_addr);
|
auto ip = NetworkToHost32(addr.UnsafeGet<sockaddr_in>()->sin_addr.s_addr);
|
||||||
for (auto &&item : kRanges) {
|
for (auto &&item : kRanges) {
|
||||||
if ((ip & item.first) == item.second) {
|
if ((ip & item.first) == item.second) {
|
||||||
return true;
|
return true;
|
||||||
@ -309,7 +310,7 @@ bool IsPrivateIpv4AddressCorp(const Endpoint &addr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ip = ntohl(addr.UnsafeGet<sockaddr_in>()->sin_addr.s_addr);
|
auto ip = NetworkToHost32(addr.UnsafeGet<sockaddr_in>()->sin_addr.s_addr);
|
||||||
for (auto &&item : kRanges) {
|
for (auto &&item : kRanges) {
|
||||||
auto &mask = item.first;
|
auto &mask = item.first;
|
||||||
auto &expected = item.second;
|
auto &expected = item.second;
|
||||||
@ -352,7 +353,7 @@ std::optional<Endpoint> TryParseTraits<Endpoint>::TryParse(Slice s,
|
|||||||
if (inet_pton(AF_INET, ip.c_str(), &p->sin_addr) != 1) {
|
if (inet_pton(AF_INET, ip.c_str(), &p->sin_addr) != 1) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
p->sin_port = htons(*port);
|
p->sin_port = HostToNetwork16(*port);
|
||||||
p->sin_family = AF_INET;
|
p->sin_family = AF_INET;
|
||||||
*er.RetrieveLength() = sizeof(sockaddr_in);
|
*er.RetrieveLength() = sizeof(sockaddr_in);
|
||||||
return er.Build();
|
return er.Build();
|
||||||
@ -379,7 +380,7 @@ std::optional<Endpoint> TryParseTraits<Endpoint>::TryParse(Slice s,
|
|||||||
if (inet_pton(AF_INET6, ip.c_str(), &p->sin6_addr) != 1) {
|
if (inet_pton(AF_INET6, ip.c_str(), &p->sin6_addr) != 1) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
p->sin6_port = htons(*port);
|
p->sin6_port = HostToNetwork16(*port);
|
||||||
p->sin6_family = AF_INET6;
|
p->sin6_family = AF_INET6;
|
||||||
*er.RetrieveLength() = sizeof(sockaddr_in6);
|
*er.RetrieveLength() = sizeof(sockaddr_in6);
|
||||||
return er.Build();
|
return er.Build();
|
||||||
|
Loading…
Reference in New Issue
Block a user