Forum > Android

Bug? TFPHTTPClient fails on Android when ConnectTimeout<>0

(1/2) > >>

engkin:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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:

--- Quote ---GetDNSServers: 2
InitSSLInterface: True
IsSSLloaded: True
ESocketError: Connect to www.google.com:443 failed.
--- End quote ---

Tracking the code:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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:

--- Quote ---LAMW is not using TFPHTTPClient AFAICT.

--- End quote ---

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:
Thank you, jmpessoa.

Can you test this project in LAMW terminal on a real phone?

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---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:

My limited test:  (I need update my lazarus/fpc....)


--- Quote ---06-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.

--- End quote ---

Navigation

[0] Message Index

[#] Next page

Go to full version