diff options
author | Joe Crayne <joe@jerkface.net> | 2018-12-01 13:46:39 -0500 |
---|---|---|
committer | Joe Crayne <joe@jerkface.net> | 2018-12-16 14:08:26 -0500 |
commit | 04f629c7452d4db3400fc82793317cfec52b4680 (patch) | |
tree | 58ec039c2ffb81b34745b45b895b8a9d6d9f9d52 | |
parent | da35152c9a0da38f815798c5f6b6b9a0362fd330 (diff) |
StreamServer: Support for fall-back bind-addresses.
-rw-r--r-- | Connection/Tcp.hs | 2 | ||||
-rw-r--r-- | examples/dhtd.hs | 2 | ||||
-rw-r--r-- | examples/toxrelay.hs | 31 | ||||
-rw-r--r-- | src/Data/Tox/Relay.hs | 2 | ||||
-rw-r--r-- | src/Network/StreamServer.hs | 30 |
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) |
26 | import Data.Tox.Relay | 26 | import Data.Tox.Relay |
27 | import Network.Address (getBindAddress) | 27 | import Network.Address (getBindAddress) |
28 | import Network.SocketLike | ||
28 | import Network.StreamServer | 29 | import Network.StreamServer |
29 | import Network.Tox (newCrypto) | 30 | import Network.Tox (newCrypto) |
30 | import Network.Tox.Onion.Transport hiding (encrypt,decrypt) | 31 | import 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 | ||
212 | main :: IO () | 213 | sendTCP_ :: TVar (IntMap (RelayPacket -> IO ())) -> Int -> OnionResponse N1 -> IO () |
213 | main = do | 214 | sendTCP_ st addr x = join $ atomically |
215 | $ IntMap.lookup addr <$> readTVar st >>= \case | ||
216 | Nothing -> return $ return () | ||
217 | Just send -> return $ send $ OnionPacketResponse x | ||
218 | |||
219 | tcpRelay :: SockAddr -> (SockAddr -> OnionRequest N1 -> IO ()) -> IO (ServerHandle, Int -> OnionResponse N1 -> IO ()) | ||
220 | tcpRelay 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 | |||
235 | main :: IO () | ||
236 | main = 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 | ||
54 | packetNumber :: RelayPacket -> Word8 | 54 | packetNumber :: 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 | ||
16 | import Data.Monoid | 17 | import Data.Monoid |
@@ -48,6 +49,8 @@ import DebugTag | |||
48 | 49 | ||
49 | data ServerHandle = ServerHandle Socket (Weak ThreadId) | 50 | data ServerHandle = ServerHandle Socket (Weak ThreadId) |
50 | 51 | ||
52 | listenSocket :: ServerHandle -> RestrictedSocket | ||
53 | listenSocket (ServerHandle sock _) = restrictSocket sock | ||
51 | 54 | ||
52 | -- | Create a useless do-nothing 'ServerHandle'. | 55 | -- | Create a useless do-nothing 'ServerHandle'. |
53 | dummyServerHandle :: IO ServerHandle | 56 | dummyServerHandle :: 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. |
100 | streamServer :: ServerConfig -> SockAddr -> IO ServerHandle | 103 | streamServer :: ServerConfig -> [SockAddr] -> IO ServerHandle |
101 | streamServer cfg addr = do | 104 | streamServer 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" |