使用TIdHTTP和TIdSSLIOHandlerSocketOpenSSL进行内存泄漏

时间:2018-06-11 02:02:38

标签: delphi-xe5 indy10

我有以下课程

type
  TMyDownload = class
  private
    FHttp: TIdHttp;
    function VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
  public
    constructor Create(const ARootCertFile: string);
    destructor Destroy; override;
    function Get(const URL: string; Stream: TStream): Integer;
  end;

constructor TMyDownload.Create(const ARootCertFile: string);
begin
  inherited Create;

  FHttp := TIdHTTP.Create;
  FHttp.Compressor := TIdCompressorZLib.Create(FHttp);
  FHttp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(FHttp);
  FHttp.HandleRedirects := True;
  FHttp.ProtocolVersion := pv1_1;
  FHttp.ConnectTimeout := 10000;
  FHttp.ReadTimeout := 10000;
  FHttp.AllowCookies := True;

  with TIdSSLIOHandlerSocketOpenSSL(FHttp.IOHandler) do
  begin
    OnVerifyPeer := VerifyPeer;
    SSLOptions.Mode := sslmClient;
    SSLOptions.Method := sslvTLSv1_2;
    SSLOptions.RootCertFile := ARootCertFile;
    SSLOptions.SSLVersions := [sslvTLSv1_2];
    SSLOptions.VerifyMode := [sslvrfPeer, sslvrfFailIfNoPeerCert, sslvrfClientOnce];
    SSLOptions.VerifyDepth := 5;
  end;
end;

destructor TMyDownload.Destroy;
begin
  FreeAndNil(FHttp);
  inherited;
end;

function TMyDownload.Get(const URL: string; Stream: TStream): Integer;
begin
  try
    FHttp.Get(URL, Stream, [304]);
    Exit(FHttp.ResponseCode);
  except
    LogException(ClassName, False, True);
    Result := 500;
  end;
end;

function TMyDownload.VerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
var
  CurrentTime: TDateTime;
begin
  if (ADepth = 0) then
  begin
    if AOk and (AError = 0) then
    begin
      CurrentTime := Now;
      Result := (Pos('/CN=' + UpperCase(FHttp.URL.Host) + '/', '/' + UpperCase(Certificate.Subject.OneLine) + '/') <> 0)
                and (CurrentTime >= Certificate.notBefore)
                and (CurrentTime <= Certificate.notAfter);
    end
    else
      Result := False;
  end
  else
    Result := AOk and (AError = 0);
end;

以下列方式重复使用(每分钟):

// cacert.pem obtained from https://curl.haxx.se/docs/caextract.html
MyDownload := TMyDownload.Create('cacert.pem');
try
  Stream := TMemoryStream.Create;
  try
    MyDownload.Get('https://www.google.com/', Stream);
  finally
    Stream.Free;
  end;
finally
  MyDownload.Free;
end;

上述代码构成了整个程序。如果它运行3到5天,程序内存不足(在Win32上消耗2 + GB)。如果我禁用

SSLOptions.RootCertFile := ARootCertFile;

该计划运行良好,但不得不接受不安全的链证书。

是否有我缺少的东西,任何人都指向正确的方向

0 个答案:

没有答案