mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge #3809
3809: Compress IPv6 string representations according to RFC5952 r=def- a=heinrich5991 https://tools.ietf.org/html/rfc5952#section-4 Also add some tests. <!-- What is the motivation for the changes of this pull request --> ## Checklist - [x] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [x] Written a unit test if it works standalone, system.c especially - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: heinrich5991 <heinrich5991@gmail.com>
This commit is contained in:
commit
4f974effa0
|
@ -1089,6 +1089,73 @@ int net_addr_comp_noport(const NETADDR *a, const NETADDR *b)
|
|||
return net_addr_comp(&ta, &tb);
|
||||
}
|
||||
|
||||
void net_addr_str_v6(const unsigned short ip[8], int port, char *buffer, int buffer_size)
|
||||
{
|
||||
int longest_seq_len = 0;
|
||||
int longest_seq_start = -1;
|
||||
int w = 0;
|
||||
int i;
|
||||
{
|
||||
int seq_len = 0;
|
||||
int seq_start = -1;
|
||||
// Determine longest sequence of zeros.
|
||||
for(i = 0; i < 8 + 1; i++)
|
||||
{
|
||||
if(seq_start != -1)
|
||||
{
|
||||
if(i == 8 || ip[i] != 0)
|
||||
{
|
||||
if(longest_seq_len < seq_len)
|
||||
{
|
||||
longest_seq_len = seq_len;
|
||||
longest_seq_start = seq_start;
|
||||
}
|
||||
seq_len = 0;
|
||||
seq_start = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq_len += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(i != 8 && ip[i] == 0)
|
||||
{
|
||||
seq_start = i;
|
||||
seq_len = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(longest_seq_len <= 1)
|
||||
{
|
||||
longest_seq_len = 0;
|
||||
longest_seq_start = -1;
|
||||
}
|
||||
w += str_format(buffer + w, buffer_size - w, "[");
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
if(longest_seq_start <= i && i < longest_seq_start + longest_seq_len)
|
||||
{
|
||||
if(i == longest_seq_start)
|
||||
{
|
||||
w += str_format(buffer + w, buffer_size - w, "::");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *colon = i == 0 || i == longest_seq_start + longest_seq_len ? "" : ":";
|
||||
w += str_format(buffer + w, buffer_size - w, "%s%x", colon, ip[i]);
|
||||
}
|
||||
}
|
||||
w += str_format(buffer + w, buffer_size - w, "]");
|
||||
if(port >= 0)
|
||||
{
|
||||
str_format(buffer + w, buffer_size - w, ":%d", port);
|
||||
}
|
||||
}
|
||||
|
||||
void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
|
||||
{
|
||||
if(addr->type == NETTYPE_IPV4 || addr->type == NETTYPE_WEBSOCKET_IPV4)
|
||||
|
@ -1100,15 +1167,18 @@ void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_por
|
|||
}
|
||||
else if(addr->type == NETTYPE_IPV6)
|
||||
{
|
||||
if(add_port != 0)
|
||||
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
|
||||
(addr->ip[0] << 8) | addr->ip[1], (addr->ip[2] << 8) | addr->ip[3], (addr->ip[4] << 8) | addr->ip[5], (addr->ip[6] << 8) | addr->ip[7],
|
||||
(addr->ip[8] << 8) | addr->ip[9], (addr->ip[10] << 8) | addr->ip[11], (addr->ip[12] << 8) | addr->ip[13], (addr->ip[14] << 8) | addr->ip[15],
|
||||
addr->port);
|
||||
else
|
||||
str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]",
|
||||
(addr->ip[0] << 8) | addr->ip[1], (addr->ip[2] << 8) | addr->ip[3], (addr->ip[4] << 8) | addr->ip[5], (addr->ip[6] << 8) | addr->ip[7],
|
||||
(addr->ip[8] << 8) | addr->ip[9], (addr->ip[10] << 8) | addr->ip[11], (addr->ip[12] << 8) | addr->ip[13], (addr->ip[14] << 8) | addr->ip[15]);
|
||||
int port = -1;
|
||||
unsigned short ip[8];
|
||||
int i;
|
||||
if(add_port)
|
||||
{
|
||||
port = addr->port;
|
||||
}
|
||||
for(i = 0; i < 8; i++)
|
||||
{
|
||||
ip[i] = (addr->ip[i * 2] << 8) | (addr->ip[i * 2 + 1]);
|
||||
}
|
||||
net_addr_str_v6(ip, port, string, max_length);
|
||||
}
|
||||
else
|
||||
str_format(string, max_length, "unknown type %d", addr->type);
|
||||
|
|
|
@ -23,8 +23,8 @@ TEST(NetAddr, FromStr)
|
|||
EXPECT_FALSE(net_addr_from_str(&Addr, "[::1]"));
|
||||
net_addr_str(&Addr, aBuf1, sizeof(aBuf1), true);
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf1, "[0:0:0:0:0:0:0:1]:0");
|
||||
EXPECT_STREQ(aBuf2, "[0:0:0:0:0:0:0:1]");
|
||||
EXPECT_STREQ(aBuf1, "[::1]:0");
|
||||
EXPECT_STREQ(aBuf2, "[::1]");
|
||||
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[0123:4567:89ab:cdef:1:2:3:4]:5678"));
|
||||
net_addr_str(&Addr, aBuf1, sizeof(aBuf1), true);
|
||||
|
@ -33,6 +33,47 @@ TEST(NetAddr, FromStr)
|
|||
EXPECT_STREQ(aBuf2, "[123:4567:89ab:cdef:1:2:3:4]");
|
||||
}
|
||||
|
||||
TEST(NetAddr, StrV6)
|
||||
{
|
||||
NETADDR Addr;
|
||||
char aBuf1[NETADDR_MAXSTRSIZE];
|
||||
char aBuf2[NETADDR_MAXSTRSIZE];
|
||||
|
||||
// Test vectors from RFC 5952 section 4:
|
||||
// https://tools.ietf.org/html/rfc5952#section-4
|
||||
// 4.1 Handling Leading Zeros in a 16-Bit Field
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:0db8::0001]:1"));
|
||||
net_addr_str(&Addr, aBuf1, sizeof(aBuf1), true);
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf1, "[2001:db8::1]:1");
|
||||
EXPECT_STREQ(aBuf2, "[2001:db8::1]");
|
||||
|
||||
// 4.2.1 Shorten as Much as Possible
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:db8:0:0:0:0:2:1]"));
|
||||
net_addr_str(&Addr, aBuf1, sizeof(aBuf1), true);
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf1, "[2001:db8::2:1]:0");
|
||||
EXPECT_STREQ(aBuf2, "[2001:db8::2:1]");
|
||||
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:db8::0:1]"));
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf2, "[2001:db8::1]");
|
||||
|
||||
// 4.2.2 Handling One 16-Bit 0 Field
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:db8::1:1:1:1:1]"));
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf2, "[2001:db8:0:1:1:1:1:1]");
|
||||
|
||||
// 4.2.3 Choice in Placement of "::"
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:0:0:1:0:0:0:1]"));
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf2, "[2001:0:0:1::1]");
|
||||
|
||||
EXPECT_FALSE(net_addr_from_str(&Addr, "[2001:db8:0:0:1:0:0:1]"));
|
||||
net_addr_str(&Addr, aBuf2, sizeof(aBuf2), false);
|
||||
EXPECT_STREQ(aBuf2, "[2001:db8::1:0:0:1]");
|
||||
}
|
||||
|
||||
TEST(NetAddr, FromStrInvalid)
|
||||
{
|
||||
NETADDR Addr;
|
||||
|
|
Loading…
Reference in a new issue