Files
raddebugger/src/socket/socket.c
T
2026-10-02 20:57:47 -07:00

127 lines
3.8 KiB
C

// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Helpers
internal SOCK_Endpoint
sock_endpoint_from_string_port(String8 address, U16 port)
{
//- rjf: detect kind
SOCK_EndpointKind kind = SOCK_EndpointKind_IPv4;
{
if(str8_find_needle(address, 0, s(":"), 0) < address.size)
{
kind = SOCK_EndpointKind_IPv6;
}
}
//- rjf: fill based on format
SOCK_Endpoint ep = {0};
ep.port = port;
ep.kind = kind;
switch(kind)
{
default:
case SOCK_EndpointKind_IPv4:
{
U64 off = 0;
U64 part_start_off = 0;
for(;off < 4;)
{
U64 part_end_off = str8_find_needle(address, part_start_off+1, s("."), 0);
String8 part = str8_substr(address, r1u64(part_start_off, part_end_off));
U64 part_val = u64_from_str8(part, 10);
ep.address_u8[off] = (U8)part_val;
part_start_off = part_end_off+1;
off += 1;
if(part_end_off >= address.size)
{
break;
}
}
}break;
case SOCK_EndpointKind_IPv6:
{
U64 off = 0;
U64 part_start_off = 0;
U64 double_colon_off = 0;
for(;off < 8;)
{
U64 part_end_off = str8_find_needle(address, part_start_off+1, s(":"), 0);
String8 part = str8_substr(address, r1u64(part_start_off, part_end_off));
U64 part_val = u64_from_str8(part, 16);
ep.address_u16[off] = (U16)part_val;
part_start_off = part_end_off+1;
if(part_end_off+1 < address.size && address.str[part_end_off+1] == ':')
{
double_colon_off = off;
}
off += 1;
if(part_end_off >= address.size)
{
break;
}
}
if(off < 8 && double_colon_off < 8)
{
U64 shift_amt = 8 - off;
MemoryCopy(&ep.address_u16[0] + double_colon_off + shift_amt, &ep.address_u16[0] + double_colon_off, sizeof(U16) * (off - double_colon_off));
}
}break;
}
return ep;
}
internal SOCK_Endpoint
sock_endpoint_from_string(String8 address_and_port)
{
String8 addr = {0};
U64 port_off = 0;
if(address_and_port.size > 0 && address_and_port.str[0] == '[')
{
U64 addr_end_off = str8_find_needle(address_and_port, 1, s("]"), 0);
addr = str8_substr(address_and_port, r1u64(1, addr_end_off));
port_off = str8_find_needle(address_and_port, addr_end_off+1, s(":"), 0)+1;
}
else
{
U64 colon_off = str8_find_needle(address_and_port, 0, s(":"), 0);
port_off = colon_off + 1;
addr = str8_prefix(address_and_port, colon_off);
}
String8 port_string = str8_skip(address_and_port, port_off);
U16 port = u64_from_str8(port_string, 10);
SOCK_Endpoint ep = sock_endpoint_from_string_port(addr, port);
return ep;
}
internal String8
sock_string_from_endpoint(Arena *arena, SOCK_Endpoint endpoint)
{
String8 result = {0};
switch(endpoint.kind)
{
default:{}break;
case SOCK_EndpointKind_IPv4:
{
result = str8f(arena, "%i.%i.%i.%i:%i", (int)endpoint.address_u8[0], (int)endpoint.address_u8[1], (int)endpoint.address_u8[2], (int)endpoint.address_u8[3], (int)endpoint.port);
}break;
case SOCK_EndpointKind_IPv6:
{
result = str8f(arena, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%i",
(int)endpoint.address_u16[0],
(int)endpoint.address_u16[1],
(int)endpoint.address_u16[2],
(int)endpoint.address_u16[3],
(int)endpoint.address_u16[4],
(int)endpoint.address_u16[5],
(int)endpoint.address_u16[6],
(int)endpoint.address_u16[7],
(int)endpoint.port);
}break;
}
return result;
}