(07-30-2026, 09:50 AM)DidierMenant Wrote: I simply want to convert the format
AThread.Binding.PeerIP = '0:0:0:0:0:0:0:1'
into an IPv4 address (xxx.xxx.xxx.xxx).
I assume there is an existing function that I'm just not finding ?
No, Indy does not have a function to convert an IPv6 address into an IPv4 address.
Why do you want this? What is the actual use-case you are trying to solve where you can't use the
PeerIP exactly as it is given to you?
'0:0:0:0:0:0:0:1' is an IPv6 address (specifically, the IPv6 loopback address). You can't just reformat it as an IPv4 address without losing data (IPv4 uses 32 bits, IPv6 uses 128 bits).
Attempting to do such a conversion would work ONLY for an
IPv4-mapped IPv6 address, which is an IPv6 address whose last 32 bits are an IPv4 address. But,
'0:0:0:0:0:0:0:1' is not an IPv4-mapped address, as it does not begin with the required
'0:0:0:0:0:ffff:' prefix.
The only way the
PeerIP could ever report an IPv4-mapped IPv6 address is if your server is using a
dual-stack IPv6 socket, but Indy does not use dual-stack sockets at this time (there is an
open ticket for that).
That being said, if you really needed to, it is pretty trivial to manually extract the IPv4 portion of an IPv4-mapped IPv6 address, eg:
Code:
var IP := IndyUpperCase(AThread.Binding.PeerIP);
var IPv4: string;
if AThread.Binding.IPVersion = Id_IPv6 then
begin
if TextStartsWith(IP, '0:0:0:0:0:FFFF:') then
IPv4 := Copy(IP, 16, MaxInt)
else if TextStartsWith(IP, '::FFFF:') then
IPv4 := Copy(IP, 8, MaxInt);
end else
IPv4 := IP;
Or, using socket API functions (off the top of my head, might need some tweaking):
Code:
var IP := AThread.Binding.PeerIP;
var IPv4: string;
var hints: addrinfo;
ZeroMemory(@hints, sizeof(hints));
hints.ai_flags := AI_NUMERICHOST;
hints.ai_family := AF_UNSPEC;
hints.ai_socktype := SOCK_STREAM;
hints.ai_protocol := IPPROTO_TCP;
var res: paddrinfo;
if getaddrinfo(PChar(IP), nil, @hints, @res) = 0 then
begin
if INETADDR_ISV4MAPPED(res.ai_addr) then
begin
var bytes := IN6_GET_ADDR_V4MAPPED(@(psockaddr_in6(res.ai_addr).sin6_addr));
var addr: sockaddr_in;
ZeroMemory(@addr, sizeof(addr));
addr.sin_family := AF_INET;
Move(bytes^, addr.s_addr, sizeof(in_addr));
var host: array[0..15] of AnsiChar;
getnameinfo(psockaddr(@addr), sizeof(addr), host, sizeof(host), nil, 0, NI_NUMERICHOST);
IPv4 := string(host);
end
else if (res.sa_family = AF_INET4) then
IPv4 := IP;
freeaddrinfo(res);
end;