Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Simply convert PeerIp to IpV4
#1
Hello,
in indy 10

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 ?
Reply
#2
(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;

Reply
#3
It is indeed the localhost loop (itself) on an IndySoap server V10 that is disturbed me like this,
Even though the remote clients are using IPv4 !

I am working on a tracer-profiler for webservices Soap I/O to measure performance.

Tank
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)