Network.hs (2378B)
1 module Pipes.Network ( 2 N.Socket(..) 3 , N.SockAddr(..) 4 , NT.HostPreference(..) 5 , N.ServiceName 6 , Protocol 7 8 , fromSocket 9 , toSocket 10 , session 11 , dance 12 13 , NT.connect 14 , NT.serve 15 , NT.send 16 , NT.recv 17 , NT.closeSock 18 ) where 19 20 import Control.Monad.IO.Class 21 import qualified Data.Binary as DB 22 import qualified Data.ByteString as BS 23 import Pipes 24 import qualified Pipes.Binary as PB 25 import qualified Pipes.Parse as PP 26 import qualified Pipes.Prelude as P 27 import qualified Network.Simple.TCP as NT 28 import qualified Network.Socket as N 29 import qualified Network.Socket.ByteString as NB 30 import GHC.Word (Word32) 31 32 type Protocol m b c = b -> m c 33 34 -- receive on socket 35 fromSocket 36 :: MonadIO m 37 => N.Socket 38 -> Word32 39 -> Producer' BS.ByteString m () 40 fromSocket s n = loop where 41 loop = do 42 b <- liftIO (NB.recv s (fromIntegral n)) 43 if BS.null b 44 then pure () 45 else do 46 yield b 47 loop 48 49 -- send on socket 50 toSocket 51 :: MonadIO m 52 => N.Socket 53 -> Consumer' BS.ByteString m r 54 toSocket s = for cat (NT.send s) 55 56 -- receive on alternate sockets 57 rhumba 58 :: MonadIO m 59 => N.Socket 60 -> N.Socket 61 -> Word32 62 -> Producer' BS.ByteString m () 63 rhumba a b n = loop True where 64 loop lip = do 65 let s = if lip then a else b 66 b <- liftIO (NB.recv s (fromIntegral n)) 67 if BS.null b 68 then pure () 69 else do 70 yield b 71 loop (not lip) 72 73 -- send on alternate sockets 74 foxtrot 75 :: MonadIO m 76 => N.Socket 77 -> N.Socket 78 -> Consumer BS.ByteString m b 79 foxtrot asock bsock = loop True where 80 loop lip = do 81 b <- await 82 let s = if lip then asock else bsock 83 liftIO $ NT.send s b 84 loop (not lip) 85 86 -- basic TCP coordination 87 session 88 :: (MonadIO m, DB.Binary b, DB.Binary c) 89 => N.Socket 90 -> Protocol m b c 91 -> Effect m (PB.DecodingError, Producer BS.ByteString m ()) 92 session sock eval = 93 deco 94 >-> P.mapM eval 95 >-> for cat PB.encode 96 >-> send 97 where 98 recv = fromSocket sock 4096 99 deco = PP.parsed PB.decode recv 100 send = toSocket sock 101 102 -- MITM TCP coordination 103 dance 104 :: (MonadIO m, DB.Binary b, DB.Binary c) 105 => N.Socket 106 -> N.Socket 107 -> Protocol m b c 108 -> Effect m (PB.DecodingError, Producer BS.ByteString m ()) 109 dance asock bsock eval = 110 PP.parsed PB.decode recv 111 >-> P.mapM eval 112 >-> for cat PB.encode 113 >-> foxtrot bsock asock 114 where 115 recv = rhumba asock bsock 4096 116