Skip to content

Commit 6f8bf9d

Browse files
Merge pull request #50 from avieth/avieth/separate_bind_address
Separate bind address
2 parents f2f761b + db3a3b8 commit 6f8bf9d

File tree

2 files changed

+43
-31
lines changed

2 files changed

+43
-31
lines changed

src/Network/Transport/TCP.hs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,12 @@ import qualified Data.ByteString as BS (length)
275275
-- ValidRemoteEndPointState).
276276

277277
data TCPTransport = TCPTransport
278-
{ transportHost :: !N.HostName
279-
, transportPort :: !N.ServiceName
280-
, transportState :: !(MVar TransportState)
281-
, transportParams :: !TCPParameters
278+
{ transportHost :: !N.HostName
279+
, transportPort :: !N.ServiceName
280+
, transportBindHost :: !N.HostName
281+
, transportBindPort :: !N.ServiceName
282+
, transportState :: !(MVar TransportState)
283+
, transportParams :: !TCPParameters
282284
}
283285

284286
data TransportState =
@@ -497,20 +499,25 @@ data TransportInternals = TransportInternals
497499
--------------------------------------------------------------------------------
498500

499501
-- | Create a TCP transport
500-
createTransport :: N.HostName
501-
-> N.ServiceName
502+
createTransport :: N.HostName -- ^ Bind host name.
503+
-> N.ServiceName -- ^ Bind port.
504+
-> (N.ServiceName -> (N.HostName, N.ServiceName))
505+
-- ^ External address host name and port, computed from the
506+
-- actual bind port.
502507
-> TCPParameters
503508
-> IO (Either IOException Transport)
504-
createTransport host port params =
505-
either Left (Right . fst) <$> createTransportExposeInternals host port params
509+
createTransport bindHost bindPort mkExternal params =
510+
either Left (Right . fst) <$>
511+
createTransportExposeInternals bindHost bindPort mkExternal params
506512

507513
-- | You should probably not use this function (used for unit testing only)
508514
createTransportExposeInternals
509515
:: N.HostName
510516
-> N.ServiceName
517+
-> (N.ServiceName -> (N.HostName, N.ServiceName))
511518
-> TCPParameters
512519
-> IO (Either IOException (Transport, TransportInternals))
513-
createTransportExposeInternals host port params = do
520+
createTransportExposeInternals bindHost bindPort mkExternal params = do
514521
state <- newMVar . TransportValid $ ValidTransportState
515522
{ _localEndPoints = Map.empty
516523
, _nextEndPointId = 0
@@ -526,14 +533,17 @@ createTransportExposeInternals host port params = do
526533
-- completes (see description of 'forkServer'), yet we need the port to
527534
-- construct a transport. So we tie a recursive knot.
528535
(port', result) <- do
529-
let transport = TCPTransport { transportState = state
530-
, transportHost = host
531-
, transportPort = port'
532-
, transportParams = params
536+
let (externalHost, externalPort) = mkExternal port'
537+
let transport = TCPTransport { transportState = state
538+
, transportHost = externalHost
539+
, transportPort = externalPort
540+
, transportBindHost = bindHost
541+
, transportBindPort = port'
542+
, transportParams = params
533543
}
534544
bracketOnError (forkServer
535-
host
536-
port
545+
bindHost
546+
bindPort
537547
(tcpBacklog params)
538548
(tcpReuseServerAddr params)
539549
(terminationHandler transport)

tests/TestTCP.hs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE RebindableSyntax, TemplateHaskell #-}
2+
{-# LANGUAGE BangPatterns #-}
23
{-# OPTIONS_GHC -fno-warn-orphans #-}
34
module Main where
45

@@ -111,7 +112,7 @@ testEarlyDisconnect = do
111112
server :: MVar EndPointAddress -> MVar EndPointAddress -> MVar () -> IO ()
112113
server serverAddr clientAddr serverDone = do
113114
tlog "Server"
114-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
115+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
115116
Right endpoint <- newEndPoint transport
116117
putMVar serverAddr (address endpoint)
117118
theirAddr <- readMVar clientAddr
@@ -216,7 +217,7 @@ testEarlyCloseSocket = do
216217
server :: MVar EndPointAddress -> MVar EndPointAddress -> MVar () -> IO ()
217218
server serverAddr clientAddr serverDone = do
218219
tlog "Server"
219-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
220+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
220221
Right endpoint <- newEndPoint transport
221222
putMVar serverAddr (address endpoint)
222223
theirAddr <- readMVar clientAddr
@@ -324,13 +325,13 @@ testEarlyCloseSocket = do
324325
-- | Test the creation of a transport with an invalid address
325326
testInvalidAddress :: IO ()
326327
testInvalidAddress = do
327-
Left _ <- createTransport "invalidHostName" "0" defaultTCPParameters
328+
Left _ <- createTransport "invalidHostName" "0" ((,) "invalidHostName") defaultTCPParameters
328329
return ()
329330

330331
-- | Test connecting to invalid or non-existing endpoints
331332
testInvalidConnect :: IO ()
332333
testInvalidConnect = do
333-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
334+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
334335
Right endpoint <- newEndPoint transport
335336

336337
-- Syntax error in the endpoint address
@@ -361,7 +362,7 @@ testIgnoreCloseSocket = do
361362
clientDone <- newEmptyMVar
362363
serverDone <- newEmptyMVar
363364
connectionEstablished <- newEmptyMVar
364-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
365+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
365366

366367
-- Server
367368
forkTry $ do
@@ -451,7 +452,7 @@ testBlockAfterCloseSocket = do
451452
clientDone <- newEmptyMVar
452453
serverDone <- newEmptyMVar
453454
connectionEstablished <- newEmptyMVar
454-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
455+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
455456

456457
-- Server
457458
forkTry $ do
@@ -531,7 +532,7 @@ testUnnecessaryConnect numThreads = do
531532
serverAddr <- newEmptyMVar
532533

533534
forkTry $ do
534-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
535+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
535536
Right endpoint <- newEndPoint transport
536537
putMVar serverAddr (address endpoint)
537538

@@ -570,11 +571,11 @@ testUnnecessaryConnect numThreads = do
570571
-- | Test that we can create "many" transport instances
571572
testMany :: IO ()
572573
testMany = do
573-
Right masterTransport <- createTransport "127.0.0.1" "0" defaultTCPParameters
574+
Right masterTransport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
574575
Right masterEndPoint <- newEndPoint masterTransport
575576

576577
replicateM_ 10 $ do
577-
mTransport <- createTransport "127.0.0.1" "0" defaultTCPParameters
578+
mTransport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
578579
case mTransport of
579580
Left ex -> do
580581
putStrLn $ "IOException: " ++ show ex ++ "; errno = " ++ show (ioe_errno ex)
@@ -591,7 +592,7 @@ testMany = do
591592
-- | Test what happens when the transport breaks completely
592593
testBreakTransport :: IO ()
593594
testBreakTransport = do
594-
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" defaultTCPParameters
595+
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
595596
Right endpoint <- newEndPoint transport
596597

597598
killThread (transportThread internals) -- Uh oh
@@ -647,7 +648,7 @@ testReconnect = do
647648

648649
-- Client
649650
forkTry $ do
650-
Right transport <- createTransport "127.0.0.1" "0" defaultTCPParameters
651+
Right transport <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
651652
Right endpoint <- newEndPoint transport
652653
let theirAddr = encodeEndPointAddress "127.0.0.1" serverPort 0
653654

@@ -723,7 +724,7 @@ testUnidirectionalError = do
723724

724725
-- Client
725726
forkTry $ do
726-
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" defaultTCPParameters
727+
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
727728
Right endpoint <- newEndPoint transport
728729
let theirAddr = encodeEndPointAddress "127.0.0.1" serverPort 0
729730

@@ -778,7 +779,7 @@ testUnidirectionalError = do
778779

779780
testInvalidCloseConnection :: IO ()
780781
testInvalidCloseConnection = do
781-
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" defaultTCPParameters
782+
Right (transport, internals) <- createTransportExposeInternals "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
782783
serverAddr <- newEmptyMVar
783784
clientDone <- newEmptyMVar
784785
serverDone <- newEmptyMVar
@@ -820,9 +821,10 @@ testUseRandomPort :: IO ()
820821
testUseRandomPort = do
821822
testDone <- newEmptyMVar
822823
forkTry $ do
823-
Right transport1 <- createTransport "127.0.0.1" "0" defaultTCPParameters
824+
Right transport1 <- createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters
824825
Right ep1 <- newEndPoint transport1
825-
Right transport2 <- createTransport "127.0.0.1" "0" defaultTCPParameters
826+
-- Same as transport1, but is strict in the port.
827+
Right transport2 <- createTransport "127.0.0.1" "0" (\(!port) -> ("127.0.0.1", port)) defaultTCPParameters
826828
Right ep2 <- newEndPoint transport2
827829
Right conn1 <- connect ep2 (address ep1) ReliableOrdered defaultConnectHints
828830
ConnectionOpened _ _ _ <- receive ep1
@@ -848,7 +850,7 @@ main = do
848850
]
849851
-- Run the generic tests even if the TCP specific tests failed..
850852
testTransport (either (Left . show) (Right) <$>
851-
createTransport "127.0.0.1" "0" defaultTCPParameters)
853+
createTransport "127.0.0.1" "0" ((,) "127.0.0.1") defaultTCPParameters)
852854
-- ..but if the generic tests pass, still fail if the specific tests did not
853855
case tcpResult of
854856
Left err -> throwIO err

0 commit comments

Comments
 (0)