Network Connect Timeouts

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Network Connect Timeouts

Mark Fine
I'd like a configurable network connect timeout. Has anyone solved this reasonably?

System.Timeout.timeout times out connections, but works on the granularity of the life of the connection. Is there a reasonable way to configure a timeout around just establishing the connection? Maybe something like a conditional timeout that enables an action to disable the timeout once it expires?

As a workaround, I'm spinning trying to successfully connect first before trying to connect for real:

-- | Try the TCP connection and see if you can connect...
--
tryTCPClient :: Int -> ClientSettings -> IO ()
tryTCPClient microseconds settings = do
  ok <- newIORef False
  void $ timeout microseconds $ runTCPClient settings $ const $
    writeIORef ok True
  ok' <- readIORef ok
  unless ok' $
    tryTCPClient microseconds settings

-- | Wrap runTCPClient with a connect timeout.
--
-- Tries the TCP connection first, and the runs the regular runTCPClient.
-- Of course, this only enforces a TCP connect timeout on the first connect.
-- The second TCP connect has no timeout :(
--
runTCPClient' :: Int -> ClientSettings -> (AppData -> IO a) -> IO a
runTCPClient' microseconds settings action = do
  tryTCPClient microseconds settings
  runTCPClient settings action

I've also tried running the tryTCPClient in its own thread concurrently with runTCPClient and throwing an exception if it can't connect in microseconds. None of these offer an actual true connection establishment timeout.

Has anyone found a way to solve this? Thanks!

Mark



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Network Connect Timeouts

Joachim Durchholz
I do not have an answer to your actual question, just a side node on
your workaround:

Am 14.10.2017 um 04:14 schrieb Mark Fine:
> As a workaround, I'm spinning trying to successfully connect first
> before trying to connect for real:

This does not give you the effect you want out of it.

Nowadays, middleboxes and servers keep track of past connections, for
various reasons - mostly it's NAT in things like cable modems, and
intrusion detection systems (IDSes) in servers or close-to-server
middleboxes.

Cable modems and similar tend to operate under memory-constrained
conditions. If you open two connections, this may be the final straw
that breaks the cable modem, causing all kinds of weird behaviour (the
better ones will drop the longest-unused connections, but I have seen
some that will start exhibiting all kinds of bugs).
This failure mode is particularly important if you plan to open many
connections from a client at the user's home; otherwise it is less relevant.

IDSes will notice that you quickly opened and closed connections, and
potentially flag this as suspicious.


The usual solution is to open the connection, and retry a few times.
(Failed connection attempts tend to be not remembered by middleboxes.)
If retrying fails, either ask the user if the program should retry
connecting (not telling the user that there were retries already, they
don't care and wouldn't understand), or if it's a server, do the retries
with an exponential standoff and log the situation once it becomes
severe enough.
Neither solution is really doable at the network connection layer, so
maybe it's actually okay if there is no answer to your original question :-)

Regards,
Jo
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Network Connect Timeouts

Chris Wong-2
In reply to this post by Mark Fine
Hi Mark,

What networking library are you using?

There should be a lower level interface which allows for managing the lifetime of a connection by hand.

Chris

On Oct 14, 2017 15:17, "Mark Fine" <[hidden email]> wrote:
I'd like a configurable network connect timeout. Has anyone solved this reasonably?

System.Timeout.timeout times out connections, but works on the granularity of the life of the connection. Is there a reasonable way to configure a timeout around just establishing the connection? Maybe something like a conditional timeout that enables an action to disable the timeout once it expires?

As a workaround, I'm spinning trying to successfully connect first before trying to connect for real:

-- | Try the TCP connection and see if you can connect...
--
tryTCPClient :: Int -> ClientSettings -> IO ()
tryTCPClient microseconds settings = do
  ok <- newIORef False
  void $ timeout microseconds $ runTCPClient settings $ const $
    writeIORef ok True
  ok' <- readIORef ok
  unless ok' $
    tryTCPClient microseconds settings

-- | Wrap runTCPClient with a connect timeout.
--
-- Tries the TCP connection first, and the runs the regular runTCPClient.
-- Of course, this only enforces a TCP connect timeout on the first connect.
-- The second TCP connect has no timeout :(
--
runTCPClient' :: Int -> ClientSettings -> (AppData -> IO a) -> IO a
runTCPClient' microseconds settings action = do
  tryTCPClient microseconds settings
  runTCPClient settings action

I've also tried running the tryTCPClient in its own thread concurrently with runTCPClient and throwing an exception if it can't connect in microseconds. None of these offer an actual true connection establishment timeout.

Has anyone found a way to solve this? Thanks!

Mark



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Network Connect Timeouts

Chris Wong-2
Hi Mark,

From reading the source code for runTCPClient [1], it looks like a thin wrapper around getSocketFamilyTCP and close.

It should be sufficient to copy that definition into your project and wrap the getSocketFamilyTCP call in a timeout. You might need to import Data.Streaming.Network.Internal to get access to the AppData constructor.

Hope this helps!

[1] https://hackage.haskell.org/package/streaming-commons-0.1.18/docs/src/Data-Streaming-Network.html#runTCPClient

On Sun, Oct 15, 2017 at 9:08 AM, Mark Fine <[hidden email]> wrote:
Hi Chris,

In my application, I'm using Data.Conduit.Network from conduit-extra directly (Data.Streaming.Network from streaming-commons indirectly). The timeout I'm interested in managing is the connection establishment timeout - how long does the connect call wait to establish a connection. I haven't been able to figure out how to control this outside of applying a non-conditional timeout to the connect call (which is a timeout on the lifetime of a connection, not a timeout on the establishment of a connection). Thanks!

Mark

On Sat, Oct 14, 2017 at 3:09 AM, Chris Wong <[hidden email]> wrote:
Hi Mark,

What networking library are you using?

There should be a lower level interface which allows for managing the lifetime of a connection by hand.

Chris

On Oct 14, 2017 15:17, "Mark Fine" <[hidden email]> wrote:
I'd like a configurable network connect timeout. Has anyone solved this reasonably?

System.Timeout.timeout times out connections, but works on the granularity of the life of the connection. Is there a reasonable way to configure a timeout around just establishing the connection? Maybe something like a conditional timeout that enables an action to disable the timeout once it expires?

As a workaround, I'm spinning trying to successfully connect first before trying to connect for real:

-- | Try the TCP connection and see if you can connect...
--
tryTCPClient :: Int -> ClientSettings -> IO ()
tryTCPClient microseconds settings = do
  ok <- newIORef False
  void $ timeout microseconds $ runTCPClient settings $ const $
    writeIORef ok True
  ok' <- readIORef ok
  unless ok' $
    tryTCPClient microseconds settings

-- | Wrap runTCPClient with a connect timeout.
--
-- Tries the TCP connection first, and the runs the regular runTCPClient.
-- Of course, this only enforces a TCP connect timeout on the first connect.
-- The second TCP connect has no timeout :(
--
runTCPClient' :: Int -> ClientSettings -> (AppData -> IO a) -> IO a
runTCPClient' microseconds settings action = do
  tryTCPClient microseconds settings
  runTCPClient settings action

I've also tried running the tryTCPClient in its own thread concurrently with runTCPClient and throwing an exception if it can't connect in microseconds. None of these offer an actual true connection establishment timeout.

Has anyone found a way to solve this? Thanks!

Mark



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.




--
Chris Wong (https://lambda.xyz)

"I had not the vaguest idea what this meant and when I could not remember the words, my tutor threw the book at my head, which did not stimulate my intellect in any way." -- Bertrand Russell

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: Network Connect Timeouts

Mark Fine
Hi Chris,

Yeah, definitely looks like I can reconstitute runTCPClient with a wrapped getSocketFamilyTCP - messy, but should work. Thanks!

Mark

On Sat, Oct 14, 2017 at 5:17 PM, Chris Wong <[hidden email]> wrote:
Hi Mark,

From reading the source code for runTCPClient [1], it looks like a thin wrapper around getSocketFamilyTCP and close.

It should be sufficient to copy that definition into your project and wrap the getSocketFamilyTCP call in a timeout. You might need to import Data.Streaming.Network.Internal to get access to the AppData constructor.

Hope this helps!

[1] https://hackage.haskell.org/package/streaming-commons-0.1.18/docs/src/Data-Streaming-Network.html#runTCPClient

On Sun, Oct 15, 2017 at 9:08 AM, Mark Fine <[hidden email]> wrote:
Hi Chris,

In my application, I'm using Data.Conduit.Network from conduit-extra directly (Data.Streaming.Network from streaming-commons indirectly). The timeout I'm interested in managing is the connection establishment timeout - how long does the connect call wait to establish a connection. I haven't been able to figure out how to control this outside of applying a non-conditional timeout to the connect call (which is a timeout on the lifetime of a connection, not a timeout on the establishment of a connection). Thanks!

Mark

On Sat, Oct 14, 2017 at 3:09 AM, Chris Wong <[hidden email]> wrote:
Hi Mark,

What networking library are you using?

There should be a lower level interface which allows for managing the lifetime of a connection by hand.

Chris

On Oct 14, 2017 15:17, "Mark Fine" <[hidden email]> wrote:
I'd like a configurable network connect timeout. Has anyone solved this reasonably?

System.Timeout.timeout times out connections, but works on the granularity of the life of the connection. Is there a reasonable way to configure a timeout around just establishing the connection? Maybe something like a conditional timeout that enables an action to disable the timeout once it expires?

As a workaround, I'm spinning trying to successfully connect first before trying to connect for real:

-- | Try the TCP connection and see if you can connect...
--
tryTCPClient :: Int -> ClientSettings -> IO ()
tryTCPClient microseconds settings = do
  ok <- newIORef False
  void $ timeout microseconds $ runTCPClient settings $ const $
    writeIORef ok True
  ok' <- readIORef ok
  unless ok' $
    tryTCPClient microseconds settings

-- | Wrap runTCPClient with a connect timeout.
--
-- Tries the TCP connection first, and the runs the regular runTCPClient.
-- Of course, this only enforces a TCP connect timeout on the first connect.
-- The second TCP connect has no timeout :(
--
runTCPClient' :: Int -> ClientSettings -> (AppData -> IO a) -> IO a
runTCPClient' microseconds settings action = do
  tryTCPClient microseconds settings
  runTCPClient settings action

I've also tried running the tryTCPClient in its own thread concurrently with runTCPClient and throwing an exception if it can't connect in microseconds. None of these offer an actual true connection establishment timeout.

Has anyone found a way to solve this? Thanks!

Mark



_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.




--
Chris Wong (https://lambda.xyz)

"I had not the vaguest idea what this meant and when I could not remember the words, my tutor threw the book at my head, which did not stimulate my intellect in any way." -- Bertrand Russell


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.