Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: The problem with Datasnap + iOS + IPv6...


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 2 - Last Post: Jul 24, 2017 1:03 PM Last Post By: Remy Lebeau (Te...
Luis Concepcion

Posts: 16
Registered: 3/16/00
The problem with Datasnap + iOS + IPv6...  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 20, 2017 2:59 AM
Hi

We have an iOS and Android app that uses Datasnap to connect to end-user's datasnap Windows database servers from their mobiles/tablets. Everything is working fine, except now Apple rejects the new version of our app because it is not IPv6 compatible.

Our Firemonkey mobile app (Delphi Seattle) lets end-users to set up their own server configuration (IP and Port). Thet must have a Windows PC server application running in their own server, so, there isn't any hostname. The just know their server IP address. Server application is installed in a simple Windows PC. Not a web server, domain, etc. so in most cases, there's not server hostname, but IP address.

Ok. After following Apple's instructions to create a IPv6 private wifi, the problema exists. I get "Server Unreachable" error when trying to connect to my Server IP address.
I have read that using brackets [ xxx ] with the hostname will work, but I can't get it. Maybe it only works with hostnames, not ip addresses.

Here is a simplified portion of code where I try the connection to the server:

Client side (mobile app):
- TSQLConnection (Datasnap Driver. Communication protocol: tcp/ip)
- TDSProviderConnection


        SQLConnection1.Params.Values['HostName'] := MY_SERVER_IP;
        try
            DSProviderConnection1.Connected:=true;
        except
            showmessage('error');
        end;
 


I have tried XX.XX.XX.XX and [XX.XX.XX.XX] values for MY_SERVER_IP with no success.
I don't know if I have to change something in the server's Windows application or just on client-side (mobile/firemonkey)

Any solution, please?

Luis C.
Luis Concepcion

Posts: 16
Registered: 3/16/00
Re: The problem with Datasnap + iOS + IPv6... [SOLVED]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 20, 2017 9:37 AM   in response to: Luis Concepcion in response to: Luis Concepcion
I got it

I found a chinese forum with some tricks I haven't found before.

It is possible to configure the Datasnap Communication IP version with the following parameter:

    TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).CommunicationIPVersion


By default, or if empty, it is IPv4. So, on the TSQLConnection.OnBeforeConnect event, just added the following line:

// You need to know if you are on IPv4 or IPv6 first. I explain it later.
 
if ipversion='IPv4' then   
    TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).CommunicationIPVersion:='IP_IPv4'
else
    TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).CommunicationIPVersion:='IP_IPv6'


And that's all!! Of course, you need to know if you are on a IPv4 network or in a IPv6 one. I do this with a TidTcpClient component. That component has a 'IPVersion' parameter you can set up.

So, first, try to connect using IPVersion:=Id_IPv4. If successful, you are on a IPv4 network. If not, then you probably are on a IPv6 network (or server is down). So...

    IdTCPClient1.IPVersion:=Id_IPv4;  // <--  try IPv4 first
    IdTCPClient1.Host:=MY_IP;
    try
        IdTCPClient1.Connect;
        result:=true;
        ipversion := 'IPv4';      // <-- will tell us what ip version to use
    except
    end;
 
    if IdTCPClient1.Connected=false then
    begin
        try
            IdTCPClient1.IPVersion:=Id_IPv6;  // <--  now try IPv6
            IdTCPClient1.Connect;
            result:=true;
            ipversion:='IPv6';    // <-- will tell us what ip version to use
        except
        end;
    end;


And that's all. Now the app works fine on both IPv4 and IPv6 from my iPad!
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: The problem with Datasnap + iOS + IPv6... [SOLVED]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jul 24, 2017 1:03 PM   in response to: Luis Concepcion in response to: Luis Concepcion
Luis Concepcion wrote:

It is possible to configure the Datasnap Communication IP version
with the following parameter:

Since Apple is really pushing for IPv6, I would suggest attempting to
connect using IPv6 first and then fallback to IPv4, rather than the
other way around:

begin
  ipversion := '';
 
  IdTCPClient1.Host := MY_IP;
 
  IdTCPClient1.IPVersion := Id_IPv6;  // <--  try IPv6 first 
  try
    IdTCPClient1.Connect;
    IdTCPClient1.Disconnect;
    ipversion := 'IP_IPv6';
  except
  end;
 
  if ipversion = '' then
  begin
    try
      IdTCPClient1.IPVersion := Id_IPv4;  // <--  now try IPv4
      IdTCPClient1.Connect;
      IdTCPClient1.Disconnect;
      ipversion := 'IP_IPv4';
    except
    end;
  end;
 
 
TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).Communi
cationIPVersion := ipversion;
end;

You might also consider pre-parsing the target IP before resorting to
opening a TCP connection:

uses
  ..., IdIPAddress;
 
...
 
var
  ipversion: string;
  addr: TIdIPAddress;
begin
  ipversion := '';
 
  addr := TIdIPAddress.MakeAddressObject(My_IP);
  if addr <> nil then
  begin
    case addr.AddrType of
      Id_IPv4: ipversion := 'IP_IPv4';
      Id_IPv6: ipversion := 'IP_IPv6';
    end;
    addr.Free;
  end;
 
  if ipversion = '' then
  begin
    IdTCPClient1.Host := MY_IP;
 
    IdTCPClient1.IPVersion := Id_IPv6;  // <--  try IPv6 first 
    try
      IdTCPClient1.Connect;
      IdTCPClient1.Disconnect;
      ipversion := 'IP_IPv6';
    except
    end;
 
    if ipversion = '' then
    begin
      try
        IdTCPClient1.IPVersion := Id_IPv4;  // <--  now try IPv4
        IdTCPClient1.Connect;
        IdTCPClient1.Disconnect;
        ipversion := 'IP_IPv4';
      except
      end;
    end;
  end;
 
 
TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).Communi
cationIPVersion := ipversion;
end;

You might also consider using the TIdStack.GetLocalAddressList() method
to discover if you are connected to an IPv6 network or not, instead of
making an outgoing TCP connection at all:

uses
  ..., IdIPAddress, IdStack;
 
...
 
var
  ipversion: string;
  addr: TIdIPAddress;
  addrs: TIdStackLocalAddressList;
  i: Integer;
begin
  ipversion := '';
 
  addr := TIdIPAddress.MakeAddressObject(My_IP);
  if addr <> nil then
  begin
    case addr.AddrType of
      Id_IPv4: ipversion := 'IP_IPv4';
      Id_IPv6: ipversion := 'IP_IPv6';
    end;
    addr.Free;
  end;
 
  if ipversion = '' then
  begin
    addrs := TIdStackLocalAddressList.Create;
    try
      GStack.GetLocalAddressList(addrs);
 
      for i := 0 to addrs.Count-1 do
      begin
        if addrs[i].IPVersion = Id_IPv6 then
        begin
          ipversion := 'IP_IPv6';
          Break;
        end;
      end;
 
      if ipversion = '' then
      begin
        for i := 0 to addrs.Count-1 do
        begin
          if addrs[i].IPVersion = Id_IPv4 then
          begin
            ipversion := 'IP_IPv4';
            Break;
          end;
        end;
      end;
    finally
      addrs.Free;
    end;
  end;
 
 
TDBXDatasnapProperties(SQLConnection1.ConnectionData.Properties).Communi
cationIPVersion := ipversion;
end;


--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02