Skip to content

Instantly share code, notes, and snippets.

@paul-r-ml
Created December 12, 2010 13:06
Show Gist options
  • Save paul-r-ml/738025 to your computer and use it in GitHub Desktop.
Save paul-r-ml/738025 to your computer and use it in GitHub Desktop.

Revisions

  1. paul-r-ml revised this gist Mar 2, 2012. 1 changed file with 7 additions and 4 deletions.
    11 changes: 7 additions & 4 deletions haskellTcpProxy.hs
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,11 @@
    module Main where

    import Control.Concurrent (forkIO)
    import Control.Monad (forever)
    import Control.Monad (forever, unless)
    import Network (PortID(PortNumber),listenOn)
    import Network.Socket hiding (listen,recv,send)
    import Network.Socket.ByteString (recv,sendAll)
    import qualified Data.ByteString as S
    import System.Posix (Handler(Ignore),installHandler,sigPIPE)

    data Setting = Setting { locPort :: PortNumber , remHost :: String, remPort :: String }
    @@ -25,7 +26,9 @@ main = installHandler sigPIPE Ignore Nothing >> do
    (servAddr:_) <- getAddrInfo Nothing (Just $ remHost setting) (Just $ remPort setting)
    server <- socket (addrFamily servAddr) Stream defaultProtocol
    connect server (addrAddress servAddr) >> return server
    p1 <~~> p2 = ignore $ (p1 `proxyTo` p2) >> (p2 `proxyTo` p1)
    proxyTo from to = forkIO $ closing from to $ forever $ recv from 4096 >>= sendAll to
    closing a b = flip catch (const $ sClose a >> sClose b)
    p1 <~~> p2 = ignore $ forkIO (p1 `proxyTo` p2) >> forkIO (p2 `proxyTo` p1)
    proxyTo from to = flip catch (const $ sClose from >> sClose to) $ mapData from to
    mapData from to = do
    content <- recv from 4096
    unless (S.null content) $ sendAll to content >> mapData from to
    ignore x = x >> return ()
  2. paul-r-ml revised this gist Mar 2, 2012. 1 changed file with 19 additions and 40 deletions.
    59 changes: 19 additions & 40 deletions haskellTcpProxy.hs
    Original file line number Diff line number Diff line change
    @@ -4,49 +4,28 @@ import Control.Concurrent (forkIO)
    import Control.Monad (forever)
    import Network (PortID(PortNumber),listenOn)
    import Network.Socket hiding (listen,recv,send)
    import Network.Socket.ByteString (recv,send)
    import Network.Socket.ByteString (recv,sendAll)
    import System.Posix (Handler(Ignore),installHandler,sigPIPE)

    localPort :: PortNumber
    localPort = 8000
    data Setting = Setting { locPort :: PortNumber , remHost :: String, remPort :: String }

    remoteHost :: String
    remoteHost = "ftp.free.fr"

    remotePort :: Integer
    remotePort = 80
    setting :: Setting
    setting = Setting 9900 "ftp.free.fr" "80"

    main :: IO ()
    main = do
    ignore $ installHandler sigPIPE Ignore Nothing
    start

    start :: IO ()
    start = withSocketsDo $ do
    listener <- listenOn $ PortNumber localPort
    forever $ do
    (client,_) <- accept listener
    ignore $ forkIO $ do
    server <- connectToServer
    client `proxyTo` server
    server `proxyTo` client
    return ()
    main = installHandler sigPIPE Ignore Nothing >> do
    withSocketsDo $ do
    listener <- listenOn $ PortNumber (locPort setting)
    forever $ accept listener >>= \(client,_) ->
    ignore $ forkIO $ do
    server <- getServerSocket
    client <~~> server
    where
    connectToServer = do
    addrinfos <- getAddrInfo Nothing (Just remoteHost) (Just $ show remotePort)
    let serveraddr = head addrinfos
    server <- socket (addrFamily serveraddr) Stream defaultProtocol
    connect server (addrAddress serveraddr)
    return server
    proxyTo from to = do
    ignore $ forkIO $ flip catch (close from to) $ forever $ do
    content <- recv from 4096
    ignore $ send to content
    return ()
    close a b _ = do
    sClose a
    sClose b

    -- | Run an action and ignore the result.
    ignore :: Monad m => m a -> m ()
    ignore m = m >> return ()
    getServerSocket = do
    (servAddr:_) <- getAddrInfo Nothing (Just $ remHost setting) (Just $ remPort setting)
    server <- socket (addrFamily servAddr) Stream defaultProtocol
    connect server (addrAddress servAddr) >> return server
    p1 <~~> p2 = ignore $ (p1 `proxyTo` p2) >> (p2 `proxyTo` p1)
    proxyTo from to = forkIO $ closing from to $ forever $ recv from 4096 >>= sendAll to
    closing a b = flip catch (const $ sClose a >> sClose b)
    ignore x = x >> return ()
  3. @invalid-email-address Anonymous created this gist Dec 12, 2010.
    52 changes: 52 additions & 0 deletions haskellTcpProxy.hs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    module Main where

    import Control.Concurrent (forkIO)
    import Control.Monad (forever)
    import Network (PortID(PortNumber),listenOn)
    import Network.Socket hiding (listen,recv,send)
    import Network.Socket.ByteString (recv,send)
    import System.Posix (Handler(Ignore),installHandler,sigPIPE)

    localPort :: PortNumber
    localPort = 8000

    remoteHost :: String
    remoteHost = "ftp.free.fr"

    remotePort :: Integer
    remotePort = 80

    main :: IO ()
    main = do
    ignore $ installHandler sigPIPE Ignore Nothing
    start

    start :: IO ()
    start = withSocketsDo $ do
    listener <- listenOn $ PortNumber localPort
    forever $ do
    (client,_) <- accept listener
    ignore $ forkIO $ do
    server <- connectToServer
    client `proxyTo` server
    server `proxyTo` client
    return ()
    where
    connectToServer = do
    addrinfos <- getAddrInfo Nothing (Just remoteHost) (Just $ show remotePort)
    let serveraddr = head addrinfos
    server <- socket (addrFamily serveraddr) Stream defaultProtocol
    connect server (addrAddress serveraddr)
    return server
    proxyTo from to = do
    ignore $ forkIO $ flip catch (close from to) $ forever $ do
    content <- recv from 4096
    ignore $ send to content
    return ()
    close a b _ = do
    sClose a
    sClose b

    -- | Run an action and ignore the result.
    ignore :: Monad m => m a -> m ()
    ignore m = m >> return ()