feat add byte_order
All checks were successful
ci/push/linux-aarch64-gcc/1 Pipeline was successful
ci/push/linux-aarch64-gcc/2 Pipeline was successful
ci/push/linux-x64-gcc/1 Pipeline was successful
ci/push/linux-x64-gcc/2 Pipeline was successful

This commit is contained in:
tqcq 2024-08-12 15:39:24 +08:00
parent 9bad174e0e
commit 72d4092a9e
4 changed files with 255 additions and 11 deletions

View File

@ -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
View 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

View 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

View File

@ -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();