Bug? TFPHTTPClient fails on Android when ConnectTimeout<>0 lazarus / 43-Android ---------------------------------------------------------------------- engkin · 2021-06-11 14:54 On Android both in terminal and GUI apps, TFPHTTPClient fails to connect when ConnectTimeout property has a value bigger than zero. The following project shows the problem: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program test_fphttpclient; {$define UseCThreads}{$mode objfpc}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes,SysUtils,fphttpclient,opensslsockets,openssl,netdb  { you can add units after this }; var  c:TFPHTTPClient;  r:RawByteString='';begin  WriteLn('GetDNSServers: '+GetDNSServers.ToString);  WriteLn('InitSSLInterface: '+InitSSLInterface.ToString(TUseBoolStrs.True));  WriteLn('IsSSLloaded: '+IsSSLloaded.ToString(TUseBoolStrs.True));   c:=TFPHTTPClient.Create(nil);  try    c.AllowRedirect:=True;    c.ConnectTimeout:=0;//<--- Passes    //c.ConnectTimeout:=3000;//<---- Fails    try      r:=c.Get('https://www.google.com');      WriteLn('Response Length: ',Length(r));    except      on e:exception do WriteLn(e.ClassName+': '+e.Message);    end;  finally    c.Free;  end;end.  Run it using: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i adb push "$Project()" "/data/local/tmp"adb shell chmod 755 /data/local/tmp/$ProjFile()adb shell /data/local/tmp/$ProjFile() OR adb push "$Project()" "/data/local/tmp" && adb shell chmod 755 /data/local/tmp/$ProjFile() && adb shell /data/local/tmp/$ProjFile() When ConnectTimeout>0, it fails with: QuoteGetDNSServers: 2 InitSSLInterface: True IsSSLloaded: True ESocketError: Connect to www.google.com:443 failed. Tracking the code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInetSocket.Connect;...  {$ifdef unix}  Err:=ESysEINTR;  While IsError and (Err in [ESysEINTR, ESysEAGAIN]) do  {$endif}    begin    IsError:=fpConnect(Handle, @addr, sizeof(addr))<>0;    if IsError then      Err:=Socketerror;    end;{$IFDEF HAVENONBLOCKING}  if (ConnectTimeOut>0) then    begin    if IsError and (Err=ErrWouldBlock) then      begin      TimeOutResult:=CheckSocketConnectTimeout(Handle, @FDS, @TimeV);      IsError:=(TimeOutResult<>ctrOK);      end;    SetSocketBlockingMode(Handle, bmBlocking, @FDS);    end;{$ENDIF}  If Not IsError then    begin    IsError:=Not FHandler.Connect;    if IsError then      CloseSocket(Handle);    end;  If IsError then    if TimeoutResult=ctrTimeout then      Raise ESocketError.Create(seConnectTimeOut, [Format('%s:%d',[FHost, FPort])])    else      Raise ESocketError.Create(seConnectFailed, [Format('%s:%d',[FHost, FPort])]);end; It fails in the call to fpConnect, but the Err is 0!!! I don't know what that means. Is it a bug in the way TInetSocket.Connect handles ConnectTimeout? As a nice outcome, Android is providing openssl libraries for both the GUI and the terminal apps. The above test using Laz2.0.10/FPC3.2.0 to cross compile to Android/ArmV7a ---------------------------------------------------------------------- engkin · 2021-06-13 02:46 Maybe it is not easy for others to test on their devices. I saw reports indicating a problem in Android 7, my test device. I can not be sure if the bug is in Android 7, or in TInetSocket.Connect. For now I changed TInetSocket.Connect to include my case: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TInetSocket.Connect;...  if (ConnectTimeOut>0) then    begin    if IsError and ((Err=ErrWouldBlock) {$ifdef Android}or (Err=0){$endif}) then//<--- is this correct for Android?... LAMW is not using TFPHTTPClient AFAICT. ---------------------------------------------------------------------- jmpessoa · 2021-06-13 17:05 QuoteLAMW is not using TFPHTTPClient AFAICT. But, you can use TFPHTTPClient and almost all  FCL (not LCL!) in LAMW,  just be careful with the paths and the linking process... This is a great path to be explored! ---------------------------------------------------------------------- engkin · 2021-06-13 17:18 Thank you, jmpessoa. Can you test this project in LAMW terminal on a real phone? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program test_fphttpclient;         {$define UseCThreads}    {$mode objfpc}{$H+}         uses      {$IFDEF UNIX}{$IFDEF UseCThreads}      cthreads,      {$ENDIF}{$ENDIF}      Classes,SysUtils,fphttpclient,opensslsockets,openssl,netdb      { you can add units after this };         var      c:TFPHTTPClient;      r:RawByteString='';    begin      WriteLn('GetDNSServers: '+GetDNSServers.ToString);      WriteLn('InitSSLInterface: '+InitSSLInterface.ToString(TUseBoolStrs.True));      WriteLn('IsSSLloaded: '+IsSSLloaded.ToString(TUseBoolStrs.True));        c:=TFPHTTPClient.Create(nil);      try        c.AllowRedirect:=True;        c.ConnectTimeout:=3000;        try        r:=c.Get('https://www.google.com');          WriteLn('Response Length: ',Length(r));        except          on e:exception do WriteLn(e.ClassName+': '+e.Message);        end;      finally        c.Free;      end;    end. ---------------------------------------------------------------------- jmpessoa · 2021-06-13 21:33 My limited test:  (I need update my lazarus/fpc....) Quote06-13 16:56:34.925 24502-24502/org.lamw.apptfphttpclientdemo1 I/ShowMessage: InitSSLInterface: True 06-13 16:56:34.955 24502-24502/org.lamw.apptfphttpclientdemo1 I/ShowMessage: IsSSLloaded: True 06-13 16:56:34.965 24502-24502/org.lamw.apptfphttpclientdemo1 D/LAMW: ESocketError: Host name resolution for "www.google.com" failed. ---------------------------------------------------------------------- engkin · 2021-06-14 11:09 Yes, you are having an older bug. Without updating you may be able to pass this bug by using Google DNS servers: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i begin  SetLength(DNSServers, 2);  DNSServers[0]:=StrToNetAddr('8.8.8.8');  DNSServers[1]:=StrToNetAddr('8.8.4.4');... ---------------------------------------------------------------------- jmpessoa · 2021-06-14 16:38 The same... [Without updating...] Quote06-14 12:31:37.576 6751-6751/org.lamw.apptfphttpclientdemo1 I/ShowMessage: InitSSLInterface: True 06-14 12:31:37.606 6751-6751/org.lamw.apptfphttpclientdemo1 I/ShowMessage: IsSSLloaded: True 06-14 12:31:47.626 6751-6751/org.lamw.apptfphttpclientdemo1 D/LAMW: ESocketError:Host name resolution for "www.google.com" failed. My code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {hint: Pascal files location: ...\AppTFPHTTPClientDemo1\jni }unit unit1; {$mode delphi} interface uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}   Classes, SysUtils, AndroidWidget, Laz_And_Controls,  fphttpclient,  httpdefs,  httpprotocol,  //opensslsockets,  openssl, Sockets,  netdb;  type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)    jButton1: jButton;    procedure jButton1Click(Sender: TObject);  private    {private declarations}  public    {public declarations}  end; var  AndroidModule1: TAndroidModule1; implementation  {$R *.lfm}   { TAndroidModule1 } //C:\laz4android2.0.0\fpc\3.0.4\source\packages\fcl- web\src\base  <--- (-Fu)procedure TAndroidModule1.jButton1Click(Sender: TObject);var  c:TFPHTTPClient;  r:RawByteString='';begin    SetLength(DNSServers, 2);   DNSServers[0]:=StrToNetAddr('8.8.8.8');   DNSServers[1]:=StrToNetAddr('8.8.4.4');    ShowMessage('InitSSLInterface: ' + InitSSLInterface.ToString(TUseBoolStrs.True));   ShowMessage('IsSSLloaded: ' +      IsSSLloaded.ToString(TUseBoolStrs.True));   c:=TFPHTTPClient.Create(nil);  try    c.AllowRedirect:=True;    //c.ConnectTimeout:=3000;    try      r:=c.Get('https://www.google.com');      ShowMessage('Response Length: '+IntToStr(Length(r))); // NOT CALLED !!!    except      on e:exception do LogDebug('LAMW',e.ClassName+':'+e.Message);    end;  finally    c.Free;  end; end; end. ---------------------------------------------------------------------- engkin · 2021-06-14 17:29 I took the relevant files and changed their names so they don't conflict with the original files in your installation, did some logging. You can change the procedure in ulog unit if you need to. Try it with and without -dPossibleFix in the Custom Options. As the last line when it fails without -dPossibleFix, I expect you to see: ESocketError: Connect to www.google.com:443 failed. With -dPossibleFix it should give you something along: Response Length: 49123