These are chat archives for IndySockets/Indy

31st
Mar 2017
Justin
@klsyzzz
Mar 31 2017 02:31
Hi @rlebeau is there any where I can get the help file or KB for the latest Indy release? the one on http://www.indyproject.org seems old
Remy Lebeau
@rlebeau
Mar 31 2017 02:44
the documentation hasn't been updated in a long time
Justin
@klsyzzz
Mar 31 2017 02:45
ok, so best ask here?
Remy Lebeau
@rlebeau
Mar 31 2017 02:45
if you have a specific issue, sure
Justin
@klsyzzz
Mar 31 2017 02:45
Just wondering in TIdSMTP there is a property named UseTLS, what's the one utUseRequireTLS?
what's the difference between this one and the other 2: implicit and explicit
Remy Lebeau
@rlebeau
Mar 31 2017 02:59
that is a little hard to explain. it is not really used much on the client-side (though it can be), more on the server-side. It is kind of like a mix of utUseImplicitTLS and utUseExplicitTLS. It is like Explicit in that SSL/TLS is activated dynamically only when supported by both parties, but it is like Implicit in that if the handshake fails then an exception is always raised and the connection is aborted, whereas with utUseExplicitTLS the exception can optionally be bypassed (with an event handler) so the connection can continue being used unsecure (thus making SSL/TLS optional even if attempted and failed). Also, utUseRequireTLS is used by some servers to make sure that certain commands can only be executed by clients over an already-secure SSL/TLS connection. If the connection is not secure, those commands fail.
Justin
@klsyzzz
Mar 31 2017 03:01
you explained it clear like mud, thanks

we currently using Explicit option, and here is the code:

1 idSMTP.Connect;
2 idSMTP.Authenticate;
3 idSMTP.send(idMessage);

however I found that even I remove line 2, it still works correctly. I checked the code for Authenticate, it calls StartTLS. Does TIdSMTP.Connect also call StartTLS as well somewhere?

Remy Lebeau
@rlebeau
Mar 31 2017 03:19
Send() calls Authenticate(), which in turn calls StartTLS()
Justin
@klsyzzz
Mar 31 2017 03:19
oh that's why. thank you.
jimakoz
@jimakoz
Mar 31 2017 09:00
Hi guys, my set up is Delphi 10.1 and Indy 10.6.2.5341 and basically I’ve got an issue with the TIdFTPServer when clients abruptly disconnect during a data transfer. So, the problem is really the fact that when an abruptly disconnect occurs the server doesn’t pick it up and never triggers the OnDisconenct() event. I’ve introduced a mechanism that periodically checks for timed out connections but I cannot find a way to completely kick out the connection. Any ideas?
jimakoz
@jimakoz
Mar 31 2017 09:07
That’s the code I’m using to clear idle connections, but unfortunately doesn’t work.
with ftpServer.Contexts.LockList do
begin
try
for i := Count - 1 downto 0 do
begin
Context := TidContext(List[i]);
if Context = nil then Continue;
Context.Connection.IOHandler.WriteBufferClear;
Context.Connection.IOHandler.InputBuffer.Clear;
Context.Connection.IOHandler.Close;
if Context.Connection.Connected then Context.Connection.Disconnect;
end;
finally
ftpServer.Contexts.UnlockList;
end;
end;
jimakoz
@jimakoz
Mar 31 2017 14:14
Hi, I think I have found some sort of a work around to this issue. Instead of getting the TIdContext context of a connection I get the TIdFTPServerContext instead. Then by calling the KillDataChannel method I can disconnect fully the connection. Yes, it produces a couple of exception but the OnException Event will trap all of those, so no problem!
Remy Lebeau
@rlebeau
Mar 31 2017 15:40
@jimakoz abnormal disconnects take time for the OS to detect, they are not immediate. Only graceful disconnects are. What you are doing is VERY dangerous code, because you are manipulating connections that may be actively busy doing things, like processing commands or transferring files. You are not doing anything to validate the current state of the connections. Each client runs in its own thread, you can't just wipe the buffers, or rip out the data channel, from behind the thread's back. If you really want to kill idle connections, just set a timeout on each connection in the OnConnect event, and let the client thread raise an exception if the timeout elapses while waiting for new data from the client. You can do the same thing for the data channel conection during each transfer. Let the server handle any raised exception and it will close the connection(s) for you. You can use an IOHandler's own ReadTimeout property, or you can enable TCP layer keep-alives using the IOHandler's Binding.SetKeepAliveValues() method.
jimakoz
@jimakoz
Mar 31 2017 18:24
@rlebeau many thanks for your reply. I have tried indeed setting both ReadTimeout and SetKeepAliveValues in the OnConnect event as part of a solution, but nothing is happening when the client disconnects abruptly. For example when a client uploads a file and the network cable gets unplugged the server will never trigger the disconnect event. It will release the connections only when the server gets deactivated, with errors simi!ar to the ones i get with the above solution. How can i set timeouts on the data channel connection?
Remy Lebeau
@rlebeau
Mar 31 2017 18:45
@jimakoz Let me say it again - "abnormal disconnects take time for the OS to detect" You are NOT going to get an immediate reaction from the OS, it needs time to timeout internally, and that can take a LONG time, but it will happen EVENTUALLY. Until that happens, socket operations will not report failures. TCP is designed to recover connections after short network outages, so the OS has to wait awhile before it kills a lost connection for good. If you don't want to wait that long, you have to use your own timeout in your own code. TCP keepalives help with that, as do reading timeouts. You might also consider using Binding.SetSockOpt(SO_SNDTIMEO) and Binding.SetSockOpt(SO_RCVTIMEO) on platforms that support those options (like Windows).
@jimakoz as for setting a data channel timeout, there does not appear to be a specific event that is appropriate for that, but TIdFTPServer.OnDataPortAfterBind might work, at least in Active mode transfers (probably not for Passive mode transfers since an inbound connection is not accepted yet).
jimakoz
@jimakoz
Mar 31 2017 19:21
@rlebeau , i see what you are saying, but unfortunately the connection will NEVER timeout (even if i set the keepalive and readtimeout values) , we're talking about days here. I've seen cases that the connection was still "active" even after a month! Anyhow, i might give it another go with the SetSockOpt option but i doubt is going to make any difference. I think the issue is on the data channel side, that never gets released...thanks for your support anyway.
Remy Lebeau
@rlebeau
Mar 31 2017 19:28
@jimakoz The OS will certainly never wait THAT long, so the socket code is either deadlocked, or probably stuck in an endless loop somewhere. Rather than rip the connection out, you should debug the server to find out where the code flow is going to when the cable is pulled out and then patch the code to address that.
jimakoz
@jimakoz
Mar 31 2017 19:36
Thanks @rlebeau , I'll try that and if i find something i'll let you know