#1 2015-01-29 17:47:11

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

secSSL and IOS

Hi AB

as you know smile i write Crossplatform Client with FireMonkey.
No i switched the Server to secSSL.

For this i testet my 3 kinds of Clients:

  1. Windows
    Here i had to copy / install libeay32.dll, libssl32.dll and ssleay32.dll from OpenSSL (1.0.1) in my Path - Works fine.

  2. IOS
    Exception: in idHTTP.pas at TIdCustomHTTP.CheckAndConnect the IOHandler is nil

    i googled and found this: http://www.monien.net/delphi-xe5-ssl-ht … estclient/

    I added

    {$if defined(IOS)}
      IdSSLOpenSSLHeaders_Static,
    {$endif}

    to my code.
    Than i downloaded Libcrypto.a and libssl.a which i added to the Project.

    But the IOHandler is still nil....

    I checked the Program with the Debugger but can not find the place.
    I set the 5th parameter of TSQLRestClientHTTP.Create in GetClient to True (aHTTPS) and in TIndyHttpConnectionClass.Create the
    fConnection.IOHandler:= TIdSSLIOHandlerSocketOpenSSL.Create(nil) is set.

    so it is very serious for me. (May be a Ref Count Problem ?!)

  3. Android
    Same Exception at same place as IOS.

Last edited by itSDS (2015-01-29 19:35:15)


Rad Studio 12.1 Santorini

Offline

#2 2015-01-29 20:18:45

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: secSSL and IOS

Hi AB,

i think i have fixed the Problem. The Reason is in the RefCount - Management of Delphi (XE7) - could not say exactly but it works smile

type
  TIndyHttpConnectionClass = class(TAbstractHttpConnection)
  protected
    fConnection: TIdHTTP;   // itSDS
    fIOHandler : TIdSSLIOHandlerSocketOpenSSL;
  public
    constructor Create(const aParameters: TSQLRestConnectionParams); override;
    procedure URI(var Call: TSQLRestURIParams; const InDataType: string;
      KeepAlive: integer); override;
    destructor Destroy; override;
  end;

{ TIndyHttpConnectionClass }

constructor TIndyHttpConnectionClass.Create(
  const aParameters: TSQLRestConnectionParams);
begin
  inherited;
  fConnection := TIdHTTP.Create(nil);
  fConnection.HTTPOptions := fConnection.HTTPOptions+[hoKeepOrigProtocol];
  fConnection.ConnectTimeout := fParameters.ConnectionTimeOut;
  if fParameters.Https then begin
    fIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);   // itSDS
    fConnection.IOHandler:= fIOHandler; // itSDS
  end;
  if fParameters.ProxyName<>'' then
    fConnection.ProxyParams.ProxyServer := fParameters.ProxyName;
end;

destructor TIndyHttpConnectionClass.Destroy;
begin
  fConnection.Free;
  fIOHandler.Free;    // itSDS
  inherited;
end;

in your Version the destructor of TIdSSLIOHandlerSocketOpenSSL is called in the end of TIndyHttpConnectionClass.Create. The Reason may be the Implementation of fConnection.IOHandler (fConnection.SetIOHandler)
As Workaround i added 1 extra Member fIOHandler in your TIndyHttpConnectionClass - Class.

Now SSL works on Windows, IOS, Android with FireMonkey
pls add my Modification to mORMot.


Rad Studio 12.1 Santorini

Offline

#3 2015-01-30 10:38:20

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: secSSL and IOS

Hi AB i made a Ticket at Embarcadero

https://quality.embarcadero.com/browse/RSP-9994

may be they will find the Error.

I think the Problem is in TidTCPConnection and Delphi, there are lots of comments from the Developers concerning Problems.
At SetIOhander for example something about ARC.
At first i think my workround should fix the problem.

Last edited by itSDS (2015-01-30 10:39:15)


Rad Studio 12.1 Santorini

Offline

#4 2015-01-30 10:46:14

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,183
Website

Re: secSSL and IOS

itSDS wrote:

Now SSL works on Windows, IOS, Android with FireMonkey
pls add my Modification to mORMot.

This is just GREAT news!

Using a dedicated member at owner class is probably the best workaround we could find.
I suppose the error is in TIdHTTP.IOHandler property definition, which should store the IOHandler class as true reference, not as weak reference.
Another clear example of the breaking changes introduced by the NextGen ARC model, even in officially supported libraries.
Forcing to change the memory model was an awful decision from Embarcadero. At least, the ARC model should have been made optional, to leverage code compatibility.

I've committed your patch.
See http://synopse.info/fossil/info/0934096da2

Thanks a lot Stefan for your very valuable input!
smile

Online

#5 2015-01-30 13:02:31

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: secSSL and IOS

tyvm smile

here is a little correction for SynCrossPlatformSpecific

//  {$ifdef IOS}
//  {$ifdef CPUARM}
//  IdSSLOpenSSLHeaders_Static,
//  {$endif}
//  {$endif}

{$if defined(IOS) and defined(CPUARM)}
  IdSSLOpenSSLHeaders_Static,   // libcrypto.a und libssl.a sind im Ordner Framework\_main
{$else}
  IdSSLOpenSSLHeaders,
{$endif}

the IdSSLOpenSSLHeaders is needed for IdOpenSSLSetLibPath('/usr/lib/');  // for OSX and iOS x86


Rad Studio 12.1 Santorini

Offline

#6 2015-01-30 13:16:45

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,183
Website

Re: secSSL and IOS

Indeed.

Should be fixed by http://synopse.info/fossil/info/664d7e6d29

Online

#7 2015-02-05 00:24:41

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: secSSL and IOS

Hi Arnaud i got an answer on my Ticket

This is not an Indy bug. It is an ARC mis-management problem in the user code shown in this ticket.
The TIdTCPConnection.IOHandler and TIdTCPConnection.Socket properties are implemented as [weak] references, as they reference an external component whose lifetime is not dependent on TIdHTTP's lifetime. The user code shown is creating a temp IOHandler object with no Owner assigned to it, and its ARC reference count is not being incremented by TIdHTTP, so it falls to 0 when the user's code exits, thus freeing the IOHandler and nilling TIdHTTP's references to it.  An Owner needs to be assigned so the IOHandler's ARC reference count is incremented, keeping it alive.
Connection.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Connection);
Or:
Connection.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
Either way, the user's code is also assigning the TIdHTTP object to a local variable, not to a class member. Its ARC reference count is going to fall to 0 when the variable goes out of scope, freeing the TIdHTTP object.


Rad Studio 12.1 Santorini

Offline

#8 2015-02-05 07:26:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,183
Website

Re: secSSL and IOS

This was at least a lack of documentation from the Indy part, I guess.

But what matter is that your workaround was just correct.
The fIOHandler: TIdSSLIOHandlerSocketOpenSSL property will take care of the ARC reference count as expected.
Nice!

Online

#9 2015-02-05 13:37:46

itSDS
Member
From: Germany
Registered: 2014-04-24
Posts: 506

Re: secSSL and IOS

I tested it with the following:

fConnection.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(fConnection);

and removed my fIOHandler Stuff - it works. So i don't have to care about the extra Variable smile


Rad Studio 12.1 Santorini

Offline

Board footer

Powered by FluxBB