Skip to content

Instantly share code, notes, and snippets.

@paul-r-ml
Created December 12, 2010 13:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • 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.
simple Haskell TCP proxy
module Main where
import Control.Concurrent (forkIO)
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 }
setting :: Setting
setting = Setting 9900 "ftp.free.fr" "80"
main :: IO ()
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
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 $ 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 ()
@paul-r-ml
Copy link
Author

See also this question on StackOverflow : http://stackoverflow.com/questions/9459043/how-to-write-a-minimal-overhead-proxy-to-localhost3389-in-haskell (relevant even if you plan to proxy to an other port than 3389 ;p)

@dungvn3000
Copy link

dungvn3000 commented Aug 6, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment