summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Crayne <joe@jerkface.net>2018-12-01 13:46:39 -0500
committerJoe Crayne <joe@jerkface.net>2018-12-16 14:08:26 -0500
commit04f629c7452d4db3400fc82793317cfec52b4680 (patch)
tree58ec039c2ffb81b34745b45b895b8a9d6d9f9d52
parentda35152c9a0da38f815798c5f6b6b9a0362fd330 (diff)
StreamServer: Support for fall-back bind-addresses.
-rw-r--r--Connection/Tcp.hs2
-rw-r--r--examples/dhtd.hs2
-rw-r--r--examples/toxrelay.hs31
-rw-r--r--src/Data/Tox/Relay.hs2
-rw-r--r--src/Network/StreamServer.hs30
5 files changed, 47 insertions, 20 deletions
diff --git a/Connection/Tcp.hs b/Connection/Tcp.hs
index a59f35d1..fd5d333b 100644
--- a/Connection/Tcp.hs
+++ b/Connection/Tcp.hs
@@ -303,7 +303,7 @@ server allocate sessionConduits = do
303 303
304 dput XMisc $ "Started listening on "++show port 304 dput XMisc $ "Started listening on "++show port
305 305
306 sserv <- flip streamServer port ServerConfig 306 sserv <- flip streamServer [port] ServerConfig
307 { serverWarn = dput XMisc 307 { serverWarn = dput XMisc
308 , serverSession = \sock _ h -> do 308 , serverSession = \sock _ h -> do
309 (conkey,u) <- makeConnKey params sock 309 (conkey,u) <- makeConnKey params sock
diff --git a/examples/dhtd.hs b/examples/dhtd.hs
index 7562f2ad..1d897894 100644
--- a/examples/dhtd.hs
+++ b/examples/dhtd.hs
@@ -1675,7 +1675,7 @@ main = do
1675 , announcer = announcer 1675 , announcer = announcer
1676 , mbTox = mbtox 1676 , mbTox = mbtox
1677 } 1677 }
1678 srv <- streamServer (withSession session) (SockAddrUnix "dht.sock") 1678 srv <- streamServer (withSession session) [SockAddrUnix "dht.sock"]
1679 return ( do atomically $ readTVar signalQuit >>= check 1679 return ( do atomically $ readTVar signalQuit >>= check
1680 quitListening srv 1680 quitListening srv
1681 , readTVar signalQuit >>= check 1681 , readTVar signalQuit >>= check
diff --git a/examples/toxrelay.hs b/examples/toxrelay.hs
index 953b230b..2743c5d8 100644
--- a/examples/toxrelay.hs
+++ b/examples/toxrelay.hs
@@ -25,6 +25,7 @@ import qualified Data.IntervalSet as IntSet
25 ;import Data.IntervalSet (IntSet) 25 ;import Data.IntervalSet (IntSet)
26import Data.Tox.Relay 26import Data.Tox.Relay
27import Network.Address (getBindAddress) 27import Network.Address (getBindAddress)
28import Network.SocketLike
28import Network.StreamServer 29import Network.StreamServer
29import Network.Tox (newCrypto) 30import Network.Tox (newCrypto)
30import Network.Tox.Onion.Transport hiding (encrypt,decrypt) 31import Network.Tox.Onion.Transport hiding (encrypt,decrypt)
@@ -209,18 +210,36 @@ handlePacket cons thistcp me crypto sendOnion sendToMe session = \case
209 _ -> return () 210 _ -> return ()
210 211
211 212
212main :: IO () 213sendTCP_ :: TVar (IntMap (RelayPacket -> IO ())) -> Int -> OnionResponse N1 -> IO ()
213main = do 214sendTCP_ st addr x = join $ atomically
215 $ IntMap.lookup addr <$> readTVar st >>= \case
216 Nothing -> return $ return ()
217 Just send -> return $ send $ OnionPacketResponse x
218
219tcpRelay :: SockAddr -> (SockAddr -> OnionRequest N1 -> IO ()) -> IO (ServerHandle, Int -> OnionResponse N1 -> IO ())
220tcpRelay udp_addr sendOnion = do
214 crypto <- newCrypto 221 crypto <- newCrypto
215 cons <- newTVarIO Map.empty 222 cons <- newTVarIO Map.empty
216 a <- getBindAddress "33445" True 223 clients <- newTVarIO IntMap.empty
217 let sendOnion :: SockAddr -> OnionRequest N1 -> IO () 224 b443 <- getBindAddress "443" True
218 sendOnion _ _ = return () 225 b80 <- getBindAddress "80" True
226 b33445 <- getBindAddress "33445" True
227 bany <- getBindAddress "" True
219 h <- streamServer ServerConfig 228 h <- streamServer ServerConfig
220 { serverWarn = hPutStrLn stderr 229 { serverWarn = hPutStrLn stderr
221 , serverSession = relaySession crypto cons sendOnion 230 , serverSession = relaySession crypto cons sendOnion
222 } 231 }
223 a 232 [b443,b80,udp_addr,b33445,bany]
233 return (h,sendTCP_ clients)
234
235main :: IO ()
236main = do
237 udp_addr <- getBindAddress "33445" True
238 let sendOnion :: SockAddr -> OnionRequest N1 -> IO ()
239 sendOnion _ _ = return ()
240 (h,sendTCP) <- tcpRelay udp_addr sendOnion
241 boundPort <- socketPort $ listenSocket h
242 putStrLn $ "Listening on port: " ++ show boundPort
224 243
225 putStrLn $ "ENTER to quit..." 244 putStrLn $ "ENTER to quit..."
226 s <- getLine 245 s <- getLine
diff --git a/src/Data/Tox/Relay.hs b/src/Data/Tox/Relay.hs
index 82fef126..72a05660 100644
--- a/src/Data/Tox/Relay.hs
+++ b/src/Data/Tox/Relay.hs
@@ -48,7 +48,7 @@ data RelayPacket
48 | OnionPacket (OnionRequest N0) 48 | OnionPacket (OnionRequest N0)
49 | OnionPacketResponse (OnionResponse N1) 49 | OnionPacketResponse (OnionResponse N1)
50 -- 0x0A through 0x0F reserved for future use. 50 -- 0x0A through 0x0F reserved for future use.
51 | RelayData ByteString ConId -- Word8 is a connection id. Encoded as number 16 to 255. 51 | RelayData ByteString ConId
52 deriving (Eq,Ord,Show,Data) 52 deriving (Eq,Ord,Show,Data)
53 53
54packetNumber :: RelayPacket -> Word8 54packetNumber :: RelayPacket -> Word8
diff --git a/src/Network/StreamServer.hs b/src/Network/StreamServer.hs
index afa35675..80ed4ee2 100644
--- a/src/Network/StreamServer.hs
+++ b/src/Network/StreamServer.hs
@@ -11,6 +11,7 @@ module Network.StreamServer
11 , withSession 11 , withSession
12 , quitListening 12 , quitListening
13 , dummyServerHandle 13 , dummyServerHandle
14 , listenSocket
14 ) where 15 ) where
15 16
16import Data.Monoid 17import Data.Monoid
@@ -48,6 +49,8 @@ import DebugTag
48 49
49data ServerHandle = ServerHandle Socket (Weak ThreadId) 50data ServerHandle = ServerHandle Socket (Weak ThreadId)
50 51
52listenSocket :: ServerHandle -> RestrictedSocket
53listenSocket (ServerHandle sock _) = restrictSocket sock
51 54
52-- | Create a useless do-nothing 'ServerHandle'. 55-- | Create a useless do-nothing 'ServerHandle'.
53dummyServerHandle :: IO ServerHandle 56dummyServerHandle :: IO ServerHandle
@@ -97,20 +100,25 @@ withSession session = ServerConfig warnStderr session
97-- The returned handle can be used with 'quitListening' to terminate the 100-- The returned handle can be used with 'quitListening' to terminate the
98-- thread and prevent any new sessions from starting. Currently active 101-- thread and prevent any new sessions from starting. Currently active
99-- session threads will not be terminated or signaled in any way. 102-- session threads will not be terminated or signaled in any way.
100streamServer :: ServerConfig -> SockAddr -> IO ServerHandle 103streamServer :: ServerConfig -> [SockAddr] -> IO ServerHandle
101streamServer cfg addr = do 104streamServer cfg addrs = do
102 let warn = serverWarn cfg 105 let warn = serverWarn cfg
103 family = case addr of 106 family = case addrs of
104 SockAddrInet {} -> AF_INET 107 SockAddrInet {}:_ -> AF_INET
105 SockAddrInet6 {} -> AF_INET6 108 SockAddrInet6 {}:_ -> AF_INET6
106 SockAddrUnix {} -> AF_UNIX 109 SockAddrUnix {}:_ -> AF_UNIX
110 [] -> AF_INET6
107 sock <- socket family Stream 0 111 sock <- socket family Stream 0
108 setSocketOption sock ReuseAddr 1 112 setSocketOption sock ReuseAddr 1
109 fix $ \loop -> 113 let tryBind addr next _ = do
110 tryIOError (removeSocketFile addr) >> bind sock addr 114 tryIOError (removeSocketFile addr)
111 `catchIOError` \e -> do warn $ "bind-error: " <> bshow addr <> " " <> bshow e 115 bind sock addr
112 threadDelay 5000000 116 `catchIOError` \e -> next (Just e)
113 loop 117 fix $ \loop -> let again mbe = do
118 forM_ mbe $ \e -> warn $ "bind-error: " <> bshow addrs <> " " <> bshow e
119 threadDelay 5000000
120 loop
121 in foldr tryBind again addrs Nothing
114 listen sock maxListenQueue 122 listen sock maxListenQueue
115 thread <- mkWeakThreadId <=< forkIO $ do 123 thread <- mkWeakThreadId <=< forkIO $ do
116 myThreadId >>= flip labelThread "StreamServer.acceptLoop" 124 myThreadId >>= flip labelThread "StreamServer.acceptLoop"