Hallo,
zunächst möchte ich mich bedanken für die hier geleistete Arbeit
Aber auch gleich mit einem kleinen Problem um die Ecke kommen. Die Reaktion denn die OpenSSL
DLL's nicht vorhanden sind - ist nicht so schön bei mir kommt es dann immer zu einer Schutzverletzung - im destructor der Klasse
TIdOpenSSLContextClient
Soweit ich durchdebuggt habe - ist die Aufrufkette folgende:
Delphi-Quellcode:
TIdTCPClientCustom.Connect( ) --> IOHandler :=
nil; (bedingt durch
Exception) --> TIdTCPConnection.SetIOHandler --> IdDisposeAndNil(LIOHandler);
--> TIdOpenSSLIOHandlerClient.Destroy --> TIdOpenSSLContextClient.Destroy
Delphi-Quellcode:
TIdTCPClientCustom.Connect( )
try
IOHandler.Open; -->
Exception weil
DLL'
s nicht verfügbar
except
if IOHandler <> nil then begin
IOHandler.Close;
if ManagedIOHandler then begin
// Mein IOHandler ist ManagedIOHandler = true! (bedingt durch anderen Code zuvor)
IOHandler := nil; // RLebeau - SetIOHandler() will free the IOHandler
end;
end;
raise;
end;
Das Set IOhandler = nil führt dann zu:
Delphi-Quellcode:
procedure TIdTCPConnection.SetIOHandler(AValue: TIdIOHandler);
if ManagedIOHandler then begin
if Assigned(LIOHandler) then begin
FIOHandler := nil;
-- Zugriffsfehler im Destructor des IOHandlers
IdDisposeAndNil(LIOHandler);
end;
ManagedIOHandler := False;
end;
Delphi-Quellcode:
destructor TIdOpenSSLIOHandlerClient.Destroy;
FContext.Free(); --> Zugriffsfehler
Delphi-Quellcode:
destructor TIdOpenSSLContextClient.Destroy;
OpenSSLContext ist hier noch
nil
und die Methoden / Funktionszeiger
-> SSL_CTX_sess_set_remove_cb
-> SSL_CTX_sess_set_new_cb ebenso... da
DLL ja nicht gefunden wurde
Meine Lösung sieht jetzt so aus ich ändere die Routine:
Delphi-Quellcode:
procedure TIdOpenSSLIOHandlerClient.EnsureContext;
begin
// schlägt das Laden der DLL fehl ist FContext noch <nil> und der Aufruf des TIdOpenSSLContextClient.Destroy entfällt.
EnsureOpenSSLLoaded();
if not Assigned(FContext)
then
FContext := TIdOpenSSLContextClient.Create();
// EnsureOpenSSLLoaded(); --> führt ggf. zu Exception, wo FContext welches nicht komplett initialsiert ist abgeräumt wird
try
BeforeInitContext(FContext);
TIdOpenSSLContextClient(FContext).Init(FOptions);
AfterInitContext(FContext);
except
on E: EExternalException
do
begin
try
FreeAndNil(FContext);
except
on E: EExternalException
do ;
// Nothing
end;
raise EIdOpenSSLLoadError.Create('
Failed to load OpenSSL');
end;
end;
end;
ist das so der richtige Weg?
Nachtrag:
in der Funktion TOpenSSLLoader.Load steckt leider auch ein Bug, auch wenn diese Funktion beim ersten Versuch sauber false liefert wenn die
DLL's nicht geladen werden konnten, liefert einer 2. Aufruf true - auch wenn die
DLL's immer noch nicht da sind... daher habe ich folgende geändert:
if not Result then
begin
// bei weiterem Aufruf nochmal versuchen die
DLL's zu laden...
FLoadCount.Decrement();
Exit;
end;
André