@@ -17,6 +17,7 @@ import Network.Transport.TCP ( createTransport
17
17
, createTransportExposeInternals
18
18
, TransportInternals (.. )
19
19
, encodeEndPointAddress
20
+ , TCPParameters (.. )
20
21
, defaultTCPParameters
21
22
, LightweightConnectionId
22
23
)
@@ -164,7 +165,7 @@ testEarlyDisconnect = do
164
165
(clientPort, _) <- forkServer " 127.0.0.1" " 0" 5 True throwIO $ \ sock -> do
165
166
-- Initial setup
166
167
0 <- recvWord32 sock
167
- _ <- recvWithLength sock
168
+ _ <- recvWithLength maxBound sock
168
169
sendMany sock [encodeWord32 (encodeConnectionRequestResponse ConnectionRequestAccepted )]
169
170
170
171
-- Server opens a logical connection
@@ -173,7 +174,7 @@ testEarlyDisconnect = do
173
174
174
175
-- Server sends a message
175
176
1024 <- recvWord32 sock
176
- [" ping" ] <- recvWithLength sock
177
+ [" ping" ] <- recvWithLength maxBound sock
177
178
178
179
-- Reply
179
180
sendMany sock [
@@ -276,7 +277,7 @@ testEarlyCloseSocket = do
276
277
(clientPort, _) <- forkServer " 127.0.0.1" " 0" 5 True throwIO $ \ sock -> do
277
278
-- Initial setup
278
279
0 <- recvWord32 sock
279
- _ <- recvWithLength sock
280
+ _ <- recvWithLength maxBound sock
280
281
sendMany sock [encodeWord32 (encodeConnectionRequestResponse ConnectionRequestAccepted )]
281
282
282
283
-- Server opens a logical connection
@@ -285,7 +286,7 @@ testEarlyCloseSocket = do
285
286
286
287
-- Server sends a message
287
288
1024 <- recvWord32 sock
288
- [" ping" ] <- recvWithLength sock
289
+ [" ping" ] <- recvWithLength maxBound sock
289
290
290
291
-- Reply
291
292
sendMany sock [
@@ -619,7 +620,7 @@ testReconnect = do
619
620
(serverPort, _) <- forkServer " 127.0.0.1" " 0" 5 True throwIO $ \ sock -> do
620
621
-- Accept the connection
621
622
Right 0 <- tryIO $ recvWord32 sock
622
- Right _ <- tryIO $ recvWithLength sock
623
+ Right _ <- tryIO $ recvWithLength maxBound sock
623
624
624
625
-- The first time we close the socket before accepting the logical connection
625
626
count <- modifyMVar counter $ \ i -> return (i + 1 , i)
@@ -638,7 +639,7 @@ testReconnect = do
638
639
-- Client sends a message
639
640
Right connId' <- tryIO $ (recvWord32 sock :: IO LightweightConnectionId )
640
641
True <- return $ connId == connId'
641
- Right [" ping" ] <- tryIO $ recvWithLength sock
642
+ Right [" ping" ] <- tryIO $ recvWithLength maxBound sock
642
643
putMVar serverDone ()
643
644
644
645
Right () <- tryIO $ N. sClose sock
@@ -711,15 +712,15 @@ testUnidirectionalError = do
711
712
-- would shutdown the socket in the other direction)
712
713
void . (try :: IO () -> IO (Either SomeException () )) $ do
713
714
0 <- recvWord32 sock
714
- _ <- recvWithLength sock
715
+ _ <- recvWithLength maxBound sock
715
716
() <- sendMany sock [encodeWord32 (encodeConnectionRequestResponse ConnectionRequestAccepted )]
716
717
717
718
Just CreatedNewConnection <- decodeControlHeader <$> recvWord32 sock
718
719
connId <- recvWord32 sock :: IO LightweightConnectionId
719
720
720
721
connId' <- recvWord32 sock :: IO LightweightConnectionId
721
722
True <- return $ connId == connId'
722
- [" ping" ] <- recvWithLength sock
723
+ [" ping" ] <- recvWithLength maxBound sock
723
724
putMVar serverGotPing ()
724
725
725
726
-- Client
@@ -831,10 +832,77 @@ testUseRandomPort = do
831
832
putMVar testDone ()
832
833
takeMVar testDone
833
834
835
+ -- | Verify that if a peer sends an address or data which exceeds the maximum
836
+ -- length, that peer's connection will be terminated, but other peers will
837
+ -- not be affected.
838
+ testMaxLength :: IO ()
839
+ testMaxLength = do
840
+
841
+ Right serverTransport <- createTransport " 127.0.0.1" " 9998" ((,) " 127.0.0.1" ) $ defaultTCPParameters {
842
+ -- 17 bytes should fit every valid address at 127.0.0.1.
843
+ -- Port is at most 5 bytes (65536) and id is a base-10 Word32 so
844
+ -- at most 10 bytes. We'll have one client with a 5-byte port to push it
845
+ -- over the chosen limit of 16
846
+ tcpMaxAddressLength = 16
847
+ , tcpMaxReceiveLength = 8
848
+ }
849
+ Right goodClientTransport <- createTransport " 127.0.0.1" " 9999" ((,) " 127.0.0.1" ) defaultTCPParameters
850
+ Right badClientTransport <- createTransport " 127.0.0.1" " 10000" ((,) " 127.0.0.1" ) defaultTCPParameters
851
+
852
+ serverAddress <- newEmptyMVar
853
+ testDone <- newEmptyMVar
854
+ goodClientConnected <- newEmptyMVar
855
+ goodClientDone <- newEmptyMVar
856
+ badClientDone <- newEmptyMVar
857
+
858
+ forkTry $ do
859
+ Right serverEp <- newEndPoint serverTransport
860
+ putMVar serverAddress (address serverEp)
861
+ readMVar badClientDone
862
+ ConnectionOpened _ _ _ <- receive serverEp
863
+ Received _ _ <- receive serverEp
864
+ -- Will lose the connection when the good client sends 9 bytes.
865
+ ErrorEvent (TransportError (EventConnectionLost _) _) <- receive serverEp
866
+ readMVar goodClientDone
867
+ putMVar testDone ()
868
+
869
+ forkTry $ do
870
+ Right badClientEp <- newEndPoint badClientTransport
871
+ address <- readMVar serverAddress
872
+ -- Wait until the good client connects, then try to connect. It'll fail,
873
+ -- but the good client should still be OK.
874
+ readMVar goodClientConnected
875
+ Left (TransportError ConnectFailed _)
876
+ <- connect badClientEp address ReliableOrdered defaultConnectHints
877
+ closeEndPoint badClientEp
878
+ putMVar badClientDone ()
879
+
880
+ forkTry $ do
881
+ Right goodClientEp <- newEndPoint goodClientTransport
882
+ address <- readMVar serverAddress
883
+ Right conn <- connect goodClientEp address ReliableOrdered defaultConnectHints
884
+ putMVar goodClientConnected ()
885
+ -- Wait until the bad client has tried and failed to connect before
886
+ -- attempting a send, to ensure that its failure did not affect us.
887
+ readMVar badClientDone
888
+ Right () <- send conn [" 00000000" ]
889
+ -- The send which breaches the limit does not appear to fail, but the
890
+ -- (heavyweight) connection is now severed. We can reliably determine that
891
+ -- by receiving.
892
+ Right () <- send conn [" 000000000" ]
893
+ ErrorEvent (TransportError (EventConnectionLost _) _) <- receive goodClientEp
894
+ closeEndPoint goodClientEp
895
+ putMVar goodClientDone ()
896
+
897
+ readMVar testDone
898
+ closeTransport badClientTransport
899
+ closeTransport goodClientTransport
900
+ closeTransport serverTransport
901
+
834
902
main :: IO ()
835
903
main = do
836
904
tcpResult <- tryIO $ runTests
837
- [ (" Use random port" , testUseRandomPort)
905
+ [ (" Use random port" , testUseRandomPort)
838
906
, (" EarlyDisconnect" , testEarlyDisconnect)
839
907
, (" EarlyCloseSocket" , testEarlyCloseSocket)
840
908
, (" IgnoreCloseSocket" , testIgnoreCloseSocket)
@@ -847,6 +915,7 @@ main = do
847
915
, (" Reconnect" , testReconnect)
848
916
, (" UnidirectionalError" , testUnidirectionalError)
849
917
, (" InvalidCloseConnection" , testInvalidCloseConnection)
918
+ , (" MaxLength" , testMaxLength)
850
919
]
851
920
-- Run the generic tests even if the TCP specific tests failed..
852
921
testTransport (either (Left . show ) (Right ) <$>
0 commit comments