最佳答案
我试图弄清楚如何在并发上下文中正确使用 OpenSSL.Session API
例如,假设我想实现一个 stunnel-style ssl-wrapper
,我希望具有以下基本框架结构,它实现一个初级的 full-duplex tcp-port-forwarder:
runProxy :: PortID -> AddrInfo -> IO ()
runProxy localPort@(PortNumber lpn) serverAddrInfo = do
listener <- listenOn localPort
forever $ do
(sClient, clientAddr) <- accept listener
let finalize sServer = do
sClose sServer
sClose sClient
forkIO $ do
tidToServer <- myThreadId
bracket (connectToServer serverAddrInfo) finalize $ \sServer -> do
-- execute one 'copySocket' thread for each data direction
-- and make sure that if one direction dies, the other gets
-- pulled down as well
bracket (forkIO (copySocket sServer sClient
`finally` killThread tidToServer))
(killThread) $ \_ -> do
copySocket sClient sServer -- "controlling" thread
where
-- |Copy data from source to dest until EOF occurs on source
-- Copying may also be aborted due to exceptions
copySocket :: Socket -> Socket -> IO ()
copySocket src dst = go
where
go = do
buf <- B.recv src 4096
unless (B.null buf) $ do
B.sendAll dst buf
go
-- |Create connection to given AddrInfo target and return socket
connectToServer saddr = do
sServer <- socket (addrFamily saddr) Stream defaultProtocol
connect sServer (addrAddress saddr)
return sServer
如何将上述骨架转换为 full-duplex ssl-wrapping tcp-forwarding proxy
?W.R.T 对 HsOpenSSL API 提供的函数调用的并发/并行执行(在上述用例的上下文中)的危险在哪里?
PS: 我仍然在努力完全理解如何使代码对异常和资源泄漏变得健壮。因此,尽管不是这个问题的主要焦点,如果您注意到上面的代码中有不好的地方,请留下注释。