Skrim 11 Posted May 14, 2023 I upload Xml files to a remote service using Indy. Most of the time it's working just fine, but sometimes there is an error returning error code -1. (Unknown error?) When I say "not working" the file connection/transfer is not accepted by the remote service. It's just on a few pc's it's not working, could it be those pc's are missing required files (dll)? Using OpenSSL/Indy, what files do I have to distrbute in my Win32 application? uses SysUtils, IdIOHandler, IdIOHandlerSocket, IdSSLOpenSSLHeaders, idHTTP, IdContext, IdLogBase, IdLogFile, IdSSLOpenSSL, IdHTTPHeaderInfo, IdMultipartFormData, IdURI; Share this post Link to post
Remy Lebeau 1436 Posted May 14, 2023 3 hours ago, Skrim said: Most of the time it's working just fine, but sometimes there is an error returning error code -1. (Unknown error?) What exactly is reporting that error? Can you provide the exact and complete error message? And what does your code look like? 3 hours ago, Skrim said: When I say "not working" the file connection/transfer is not accepted by the remote service. That is not very helpful. 3 hours ago, Skrim said: It's just on a few pc's it's not working, could it be those pc's are missing required files (dll)? Anything is possible, though you should be getting a different error if that were the case. More likely, those PCs are probably running firewalls that are blocking your connection. 3 hours ago, Skrim said: Using OpenSSL/Indy, what files do I have to distrbute in my Win32 application? The 2 OpenSSL DLLs, libeay32.dll and ssleay32.dll. And make sure they are for OpenSSL 1.0.2u or earlier, as TIdSSLIOHandlerSocketOpenSSL does not support newer versions. You can get those DLLs from https://github.com/IndySockets/OpenSSL-Binaries If you want to use newer DLLs, use this WIP SSLIOHandler instead. Share this post Link to post
Skrim 11 Posted May 14, 2023 Several clients connect to one remote server/service. Some clients receive error, most works just fine. Clients are on several dfferent locations. Could it be the clients firewall is blocking sending? Here is some of my code. procedure TFormSend.HttpFinish(ASender: TObject); begin LogMemo.Lines.Add(Format('Finished. Http status code : %d',[(ASender as TxxxxxUpload).ResponseCode])); if (ASender as TxxxxxUpload).ResponseCode=201 then showmessage('Invoice delivered') else showmessage('Error : Invoice could not be delivered'); end; procedure TMyClient.SendFile; var tmpstream: TStringStream; Params: TIdMultipartFormDataStream; FIdSSLIOHandler: TIdSSLIOHandlerSocketOpenSSL; FidHttp: TIdHTTP; FIdURI: TIdURI; FURL: string; begin HttpStart(Self); FResponseCode := 600; if DoCheckParams then begin Params := TIdMultipartFormDataStream.Create; FidHttp := TIdHTTP.Create(nil); FIdSSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); FIdURI := TIdURI.Create(FEndPoint); tmpstream := TStringStream.Create(Trim(FDocumentID)); try with FidHttp do begin ReadTimeout := 30000; // 0 ConnectTimeout := 30000; HTTPOptions := [hoKeepOrigProtocol]; // hoKeepOrigProtocol,hoForceEncodeParams HandleRedirects := true; RedirectMaximum := 5; ProtocolVersion := pv1_1; AllowCookies := true; OnWork := WorkEvent; OnWorkBegin := WorkBegin; OnWorkEnd := WorkEnd; OnStatus := StatusEvent; with Request do begin UserAgent := FUserAgent; BasicAuthentication := true; RawHeaders.FoldLines := false; Accept := 'application/xml'; Connection := 'keep-alive'; end; end; with (FIdSSLIOHandler as TIdSSLIOHandlerSocketOpenSSL) do begin with SSLOptions do begin Method := sslvTLSv1; SSLVersions := [sslvTLSv1]; Mode := sslmUnassigned; VerifyMode := []; VerifyDepth := 2; end; port := 443; host := FIdURI.host; end; FidHttp.IOHandler := FIdSSLIOHandler; Params.AddFile('file', FXMLfile, 'application/xml'); Params.AddFormField('SenderID', FSenderID); Params.AddFormField('RecipientID', FRecipientID); Params.AddFormField('ChannelID', FChannelID); Params.AddFormField('ProcessID', FProcessID); Params.AddFormField('DocumentID', '', '', tmpstream).ContentTransfer := '8bit'; FIdURI.Username := FUser; FIdURI.Password := FPassword; FURL := FIdURI.GetFullURI(); Params.Seek(0, soFromBeginning); try FidHttp.Post(FURL, Params, FResponse); FResponseCode := FidHttp.ResponseCode; FResponse.Seek(0, soFromBeginning); except on E1: EIdHTTPProtocolException do begin FResponseCode := FidHttp.ResponseCode; ErrorEvent(Self,'IdHTTPProtocol Protocol Exception:' + #$D#$A + StringReplace(E1.ErrorMessage, #10, #$D#$A, [rfReplaceAll])); ErrorEvent(Self,'IdHTTPProtocol RawHeaders=' + #$D#$A + FidHttp.Request.RawHeaders.Text); end; on E2: Exception do begin FResponseCode := FidHttp.ResponseCode; ErrorEvent(Self,'IdHTTPProtocol Unknown Exception: ' + E2.Message); end; end; finally Params.Free; FIdSSLIOHandler.Free; FidHttp.Free; FIdURI.Free; tmpstream.Free; end; end else ErrorEvent(Self,'Some required params are missed'); HttpFinish(Self); end; Share this post Link to post
Skrim 11 Posted May 14, 2023 (edited) 2 hours ago, Remy Lebeau said: What exactly is reporting that error? Can you provide the exact and complete error message? And what does your code look like? The error code is just -1. Nothing more, not very helpful From Windows? Edited May 14, 2023 by Skrim Share this post Link to post
Skrim 11 Posted May 14, 2023 Solved. On those pc's giving an error both libeay32.dll and ssleay32.dll were missing. Would be nice with a message "Cannot find file xxxx.dll", not just -1 🙂 Share this post Link to post
Remy Lebeau 1436 Posted May 15, 2023 (edited) On 5/14/2023 at 8:11 AM, Skrim said: Solved. On those pc's giving an error both libeay32.dll and ssleay32.dll were missing. Would be nice with a message "Cannot find file xxxx.dll", not just -1 🙂 When your code is calling TIdHTTP.Post(), if it catches any non-HTTP exception, it is reading the TIdHTTP.ResponseCode property, which won't have a valid number in that case and so returns -1. Indy does, in fact, raise an exception if the OpenSSL DLLs are missing or otherwise are unable to be loaded - EIdOSSLCouldNotLoadSSLLibrary. After that exception is raised, you can call Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit, and it will tell you whether the DLLs themselves could not be loaded, or whether any of the required exports are missing (ie, because the DLLs are the wrong version for what Indy is expecting). There are other exception classes you can catch for other OpenSSL-related errors, too. Most of them derive from either EIdOpenSSLAPISSLError or EIdOpenSSLAPICryptoError, both of which provide error codes. For example: try FidHttp.Post(FURL, Params, FResponse); FResponseCode := FidHttp.ResponseCode; FResponse.Seek(0, soFromBeginning); except on E: EIdHTTPProtocolException do begin FResponseCode := E.ErrorCode; ErrorEvent(Self, 'HTTP Protocol Exception:' + #$D#$A + AdjustLineBreaks(E.ErrorMessage, tlbsCRLF)); ErrorEvent(Self, 'HTTP Protocol RawHeaders=' + #$D#$A + FidHttp.Request.RawHeaders.Text); end; on E: EIdOSSLCouldNotLoadSSLLibrary do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS Library Exception: ' + E.Message); ErrorEvent(Self, 'SSL/TLS Didnt Load=' + #$D#$A + WhichFailedToLoad); end; on E: EIdOpenSSLAPISSLError do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS API Exception: [' + E.ClassName + '] ' + E.Message); ErrorEvent(Self, 'SSL/TLS API ErrorCode=' + IntToStr(E.ErrorCode)); ErrorEvent(Self, 'SSL/TLS API RetCode=' + IntToStr(E.RetCode)); end; on E: EIdOpenSSLAPICryptoError do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'SSL/TLS Crypto Exception: [' + E.ClassName + '] ' + E.Message); ErrorEvent(Self, 'SSL/TLS Crypto ErrorCode=' + IntToStr(E.ErrorCode)); end; on E: Exception do begin FResponseCode := -1; // or whatever you want ErrorEvent(Self, 'Unknown Exception: [' + E.ClassName + '] ' + E.Message); end; end; Edited May 15, 2023 by Remy Lebeau Share this post Link to post
Skrim 11 Posted May 15, 2023 Thanks Remy, appreciate your answer. I will try it out. Regards, Ole Share this post Link to post