@@ -5,26 +5,41 @@ module Network.Transport.TCP
6import Network.Transport
6import Network.Transport
8+import Control.Applicative
8import Control.Concurrent (forkIO, ThreadId, killThread)
10import Control.Concurrent (forkIO, ThreadId, killThread)
9import Control.Concurrent.Chan
11import Control.Concurrent.Chan
10import Control.Concurrent.MVar
12import Control.Concurrent.MVar
11import Control.Monad (forever, forM_)
13import Control.Monad (forever, forM_)
12−import Data.ByteString.Lazy.Char8 (ByteString)
15+import Data.ByteString (ByteString)
16+import qualified Data.ByteString as BS
19+import qualified Data.Conduit.Binary as CB
20+import Data.Conduit.Network
13import Data.IntMap (IntMap)
22import Data.IntMap (IntMap)
23+import qualified Data.IntMap as IntMap
14import Data.Int
25import Data.Int
15import Data.Word
27import Data.Word
16import Network.Socket
29import Network.Socket
17 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
30 ( AddrInfoFlag (AI_PASSIVE), HostName, ServiceName, Socket
18 , SocketType (Stream), SocketOption (ReuseAddr)
31 , SocketType (Stream), SocketOption (ReuseAddr)
19 , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
32 , accept, addrAddress, addrFlags, addrFamily, bindSocket, defaultProtocol
20 , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
33 , getAddrInfo, listen, setSocketOption, socket, sClose, withSocketsDo )
34+import qualified Network.Socket as N
35+import qualified Network.Socket.ByteString as NBS
21import Safe
39import Safe
23import qualified Data.Binary as B
41import qualified Data.Binary as B
24−import qualified Data.ByteString.Lazy.Char8 as BS
42+
25−import qualified Data.IntMap as IntMap
26−import qualified Network.Socket as N
27−import qualified Network.Socket.ByteString.Lazy as NBS
29type ChanId = Int
44type ChanId = Int
30type Chans = MVar (ChanId, IntMap (Chan [ByteString], [(ThreadId, Socket)]))
45type Chans = MVar (ChanId, IntMap (Chan [ByteString], [(ThreadId, Socket)]))
@@ -65,7 +80,8 @@ mkTransport (TCPConfig _hints host service) = withSocketsDo $ do
65 return (mkSourceAddr host service chanId, mkTargetEnd chans chanId chan)
80 return (mkSourceAddr host service chanId, mkTargetEnd chans chanId chan)
66 , newMulticastWith = error "newMulticastWith: not defined"
81 , newMulticastWith = error "newMulticastWith: not defined"
67 , deserialize = {-# SCC "deserialize" #-} \bs ->
82 , deserialize = {-# SCC "deserialize" #-} \bs ->
68− let (host, service, chanId) = B.decode bs in
83+ let (host, service, chanId) =
84+ either (error $ printf "deserialize: %s") id $ decode bs in
69 Just $ mkSourceAddr host service chanId
85 Just $ mkSourceAddr host service chanId
70 , closeTransport = {-# SCC "closeTransport" #-} do
86 , closeTransport = {-# SCC "closeTransport" #-} do
71 -- Kill the transport channel process
87 -- Kill the transport channel process
@@ -82,28 +98,30 @@ mkTransport (TCPConfig _hints host service) = withSocketsDo $ do
82mkSourceAddr :: HostName -> ServiceName -> ChanId -> SourceAddr
98mkSourceAddr :: HostName -> ServiceName -> ChanId -> SourceAddr
83mkSourceAddr host service chanId = SourceAddr
99mkSourceAddr host service chanId = SourceAddr
84 { connectWith = {-# SCC "connectWith" #-} \_ -> mkSourceEnd host service chanId
100 { connectWith = {-# SCC "connectWith" #-} \_ -> mkSourceEnd host service chanId
85− , serialize = {-# SCC "serialize" #-} B.encode (host, service, chanId)
101+ , serialize = {-# SCC "serialize" #-} encode (host, service, chanId)
88mkSourceEnd :: HostName -> ServiceName -> ChanId -> IO SourceEnd
104mkSourceEnd :: HostName -> ServiceName -> ChanId -> IO SourceEnd
89mkSourceEnd host service chanId = withSocketsDo $ do
105mkSourceEnd host service chanId = withSocketsDo $ do
106+ let err = error $ printf "mkSourceEnd: %s"
90 serverAddrs <- getAddrInfo Nothing (Just host) (Just service)
107 serverAddrs <- getAddrInfo Nothing (Just host) (Just service)
91 let serverAddr = case serverAddrs of
108 let serverAddr = case serverAddrs of
92− [] -> error "mkSourceEnd: getAddrInfo returned []"
109+ [] -> err "getAddrInfo returned []"
93 as -> head as
110 as -> head as
94 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
111 sock <- socket (addrFamily serverAddr) Stream defaultProtocol
95 setSocketOption sock ReuseAddr 1
112 setSocketOption sock ReuseAddr 1
96 N.connect sock (addrAddress serverAddr)
113 N.connect sock (addrAddress serverAddr)
114+-- let sink = sinkSocket sock :: Sink ByteString IO ()
97− NBS.sendAll sock $ B.encode (fromIntegral chanId :: Int64)
115+ NBS.sendAll sock $ encode (fromIntegral chanId :: Int64)
98 return SourceEnd
116 return SourceEnd
99 { send = {-# SCC "send" #-} \bss -> do
117 { send = {-# SCC "send" #-} \bss -> do
100 let size = fromIntegral (sum . map BS.length $ bss) :: Int64
118 let size = fromIntegral (sum . map BS.length $ bss) :: Int64
101 if size < 255
119 if size < 255
103− NBS.sendAll sock (B.encode (fromIntegral size :: Word8))
121+ NBS.sendAll sock (encode (fromIntegral size :: Word8))
105− NBS.sendAll sock (B.encode (255 :: Word8))
123+ NBS.sendAll sock (encode (255 :: Word8))
106− NBS.sendAll sock (B.encode size)
124+ NBS.sendAll sock (encode size)
107 mapM_ (NBS.sendAll sock) bss
125 mapM_ (NBS.sendAll sock) bss
108 , closeSourceEnd = {-# SCC "closeSourceEnd" #-} sClose sock
126 , closeSourceEnd = {-# SCC "closeSourceEnd" #-} sClose sock
@@ -128,19 +146,20 @@ mkTargetEnd chans chanId chan = TargetEnd
128-- for some reason, an error is raised.
146-- for some reason, an error is raised.
129procConnections :: Chans -> Socket -> IO ()
147procConnections :: Chans -> Socket -> IO ()
130procConnections chans sock = forever $ do
148procConnections chans sock = forever $ do
149+ let err = error $ printf "procConnections: %s"
131 (clientSock, _clientAddr) <- accept sock
150 (clientSock, _clientAddr) <- accept sock
132 -- decode the first message to find the correct chanId
151 -- decode the first message to find the correct chanId
133 bss <- recvExact clientSock 8
152 bss <- recvExact clientSock 8
134 case bss of
153 case bss of
135− [] -> error "procConnections: inbound chanId aborted"
154+ [] -> err "inbound chanId aborted"
136 bss -> do
155 bss -> do
137 let bs = BS.concat bss
156 let bs = BS.concat bss
138− let chanId = fromIntegral (B.decode bs :: Int64)
157+ let chanId = either err fromIntegral (decode bs :: Either String Int64)
139 (chanId', chanMap) <- takeMVar chans
158 (chanId', chanMap) <- takeMVar chans
140 case IntMap.lookup chanId chanMap of
159 case IntMap.lookup chanId chanMap of
141 Nothing -> do
160 Nothing -> do
142 putMVar chans (chanId', chanMap)
161 putMVar chans (chanId', chanMap)
143− error "procConnections: cannot find chanId"
162+ err "cannot find chanId"
144 Just (chan, socks) -> do
163 Just (chan, socks) -> do
145 threadId <- forkIO $ procMessages chans chanId chan clientSock
164 threadId <- forkIO $ procMessages chans chanId chan clientSock
146 let chanMap' = IntMap.insert chanId (chan, (threadId, clientSock):socks) chanMap
165 let chanMap' = IntMap.insert chanId (chan, (threadId, clientSock):socks) chanMap
@@ -159,29 +178,30 @@ procMessages chans chanId chan sock = do
159 case sizeBSs of
178 case sizeBSs of
160 [] -> closeSocket
179 [] -> closeSocket
162− let size = fromIntegral (B.decode . BS.concat $ sizeBSs :: Word8)
181+ case decode . BS.concat $ sizeBSs :: Either String Word8 of
163− if size == 255
182+ Right 255 -> do
165 sizeBSs' <- recvExact sock 8
183 sizeBSs' <- recvExact sock 8
166 case sizeBSs' of
184 case sizeBSs' of
167 [] -> closeSocket
185 [] -> closeSocket
168− _ -> procMessage (B.decode . BS.concat $ sizeBSs' :: Int64)
186+ _ -> procMessage (decode . BS.concat $ sizeBSs')
169− else procMessage size
187+ esize -> procMessage (fromIntegral <$> esize)
189+ err = error $ printf "procMessages: %s"
171 closeSocket :: IO ()
190 closeSocket :: IO ()
172 closeSocket = do
191 closeSocket = do
173 (chanId', chanMap) <- takeMVar chans
192 (chanId', chanMap) <- takeMVar chans
174 case IntMap.lookup chanId chanMap of
193 case IntMap.lookup chanId chanMap of
175 Nothing -> do
194 Nothing -> do
176 putMVar chans (chanId', chanMap)
195 putMVar chans (chanId', chanMap)
177− error "procMessages: chanId not found."
196+ err "chanId not found."
178 Just (chan, socks) -> do
197 Just (chan, socks) -> do
179 let socks' = filter ((/= sock) . snd) socks
198 let socks' = filter ((/= sock) . snd) socks
180 let chanMap' = IntMap.insert chanId (chan, socks') chanMap
199 let chanMap' = IntMap.insert chanId (chan, socks') chanMap
181 putMVar chans (chanId', chanMap')
200 putMVar chans (chanId', chanMap')
182 sClose sock
201 sClose sock
183− procMessage :: Int64 -> IO ()
202+ procMessage :: Either String Int64 -> IO ()
184− procMessage size = do
203+ procMessage (Left msg) = err msg
204+ procMessage (Right size) = do
185 bss <- recvExact sock size
205 bss <- recvExact sock size
186 case bss of
206 case bss of
187 [] -> closeSocket
207 [] -> closeSocket
@@ -202,13 +222,13 @@ procMessages chans chanId chan sock = do
202-- indicates success. This hasn't been implemented, since a Transport `receive`
222-- indicates success. This hasn't been implemented, since a Transport `receive`
203-- represents an atomic receipt of a message.
223-- represents an atomic receipt of a message.
204recvExact :: Socket -> Int64 -> IO [ByteString]
224recvExact :: Socket -> Int64 -> IO [ByteString]
205−recvExact sock n = go [] sock n
225+recvExact sock n = go [] sock (fromIntegral n)
207− go :: [ByteString] -> Socket -> Int64 -> IO [ByteString]
227+ go :: [ByteString] -> Socket -> Int -> IO [ByteString]
208 go bss _ 0 = return (reverse bss)
228 go bss _ 0 = return (reverse bss)
209 go bss sock n = do
229 go bss sock n = do
210 bs <- NBS.recv sock n
230 bs <- NBS.recv sock n
211 if BS.null bs
231 if BS.null bs
212 then return []
232 then return []
213− else go (bs:bss) sock (n - BS.length bs)
233+ else go (bs:bss) sock (n - (fromIntegral $ BS.length bs))