EIdReadTimeout in TROIndyHTTPChannel

Hi,

We have a strange issue with read timeouts.

We use a TROIndyHTTPChannel and sets the following timeout properties.
FRemObjectsTransportChannel.IndyClient.ConnectTimeout := 5000;
FRemObjectsTransportChannel.IndyClient.ReadTimeout := 60000;

When we then call a function in the interface we can get a EIdReadTimeout after 5-7s.

On the server side we can see that it is actually connected within 5s and is processing the function call.
The process can take more than 5 seconds but since the read timeout is set to 60s it should not be a problem.

Is there any other way to control connect/read timeout or do I just misunderstand how it is supposed to work.

Kind regards,

I actually found some really strange behavior that explains the EIdReadTimeout but I don’t understand what happens.

Here is the code:

FRemObjectsMessage: TROBinMessage;
FRemObjectsTransportChannel: TROIndyHTTPChannel;
FRemObjectsServer: IRRS;

FRemObjectsMessage := nil;
FRemObjectsTransportChannel := nil;
FRemObjectsServer := nil;
FRemObjectsMessage := TROBinMessage.Create;
FRemObjectsTransportChannel := TROIndyHTTPChannel.Create(nil);
FRemObjectsTransportChannel.TargetURL := FRemObjectsTargetURL;
FRemObjectsTransportChannel.Encryption.EncryptionMethod := tetBlowfish;
FRemObjectsTransportChannel.Encryption.EncryptionSendKey := CHServerEncryptionRecvKey;
FRemObjectsTransportChannel.Encryption.EncryptionRecvKey := CHServerEncryptionSendKey;
FRemObjectsTransportChannel.IndyClient.ConnectTimeout := 5000;
FRemObjectsTransportChannel.IndyClient.ReadTimeout := 60000;
FRemObjectsServer := CoRRS.Create(FRemObjectsMessage, FRemObjectsTransportChannel);
{The ReadTimeout is 60000ms}
FRemObjectsServer.Login(UserID, Password);
{!!! The ReadTimeout is 5000ms !!!}

When we call the Login the ReadTimeout changes.
Login is a function in our RemObjects interface so we don’t do anything ourselves in that function but the ReadTimeout changes for some reason.

Does anyone have an idea about what could be the cause?

Kind regards,

Hello,

I can’t reproduce your situation with latest DA release. I set values for ReadTimeout:=60000 and ConnectTimeout:=5000 as you point and call service method, that contain sleep(20000); inside it. Everything works as expected.
What DA/RO and Delphi version do you use?
You could send us simple testcase reproducing situation.

Best regards

Hi,

Thanks for the answer.

We are using RO 6.0.49.861 in Delphi XE.
I will get back to you with a testcase.

Kind regards,

Hi,

I created a simple client/server test case. See the attached file.

Whatever I set the ConnectTimeout to it is also set for the ReadTimeout.

procedure TClientForm.Button1Click(Sender: TObject);
begin
FRemObjectsServer := nil;
ROChannel.IndyClient.ConnectTimeout := 1000;
ROChannel.IndyClient.ReadTimeout := 60000;
FRemObjectsServer := CoNewService.Create(ROMessage, ROChannel);
try
FRemObjectsServer.GetServerTime;
except
end{except};
ShowMessage(‘ReadTimeout=’ + IntToStr(ROChannel.IndyClient.ReadTimeout));
end;

Kind regards,

To clarify my previous post, it’s when I call FRemObjectsServer.GetServerTime as ReadTimeout changes to the value of ConnectTimeout. The code for GetServerTime is the RemObjects auto-generated code for the interface.

Hello,

Unfortunately, not RO code causes this situation, but Indy.
During the request processing Indy calls InternalReadLn function from IdHTTP.pas :
function TIdCustomHTTP.InternalReadLn: String;
begin
IOHandler.ReadTimeout := ConnectTimeout; //// !!!
Result := IOHandler.ReadLn;
if IOHandler.ReadLnTimedout then begin
raise EIdReadTimeout.Create(RSReadTimeout);
end;
end;

That is why ReadTimeout gets equal to ConnectTimeout.

I was tested this situation in Delphi XE2 first and coulnd’t reproduce it. Because DelphiXE2 has such implementation in IdHTTP.pas:
function TIdCustomHTTP.InternalReadLn: String;
begin
Result := IOHandler.ReadLn;
if IOHandler.ReadLnTimedout then begin
raise EIdReadTimeout.Create(RSReadTimeout);
end;
end;

So you could increase ConnectTimeout to necessary ReadTimeout value

Best regards

Hi,

Thanks for your answer. Now we got the reason.

In our case we want to keep the ConnectTimeout low to not stall if we cannot connect to the server-side.

Is Indy version 10.5.7 used in all XE builds of RemObjects or could a later version then RO 6.0.49.861 for Delphi XE solve the issue?

Kind regards

Hello,

Is Indy version 10.5.7 used in all XE builds of RemObjects or could a later version >then RO 6.0.49.861 for Delphi XE solve the issue?

Even in the latest RO release in Delphi XE there is the same error.

You could try to edit IdHTTP.pas (that contained in …\Embarcadero\RAD Studio\8.0\source\Indy10\Protocols) manually - comment this line:

function TIdCustomHTTP.InternalReadLn: String;
begin
IOHandler.ReadTimeout := ConnectTimeout; //// !!!

end;

and save the file.

After that recompile IndyProtocols package, then recompile RemObjects_Indy_D15 package too.
This should help not to get your timeout error.

Best regards

Hi,
We solved it by putting IdHTTP.pas in the search path. Did the fix in that unit. That means we don’t have to recompile the packages. We can also upgrade RO without having to recompile RemObjects_Indy_D15 again.