module Network.HTTP.Lucu.Httpd
( FallbackHandler
, runHttpd
)
where
import Control.Concurrent
import Network
import qualified Network.Socket as So
import Network.HTTP.Lucu.Config
import Network.HTTP.Lucu.Interaction
import Network.HTTP.Lucu.RequestReader
import Network.HTTP.Lucu.Resource.Tree
import Network.HTTP.Lucu.ResponseWriter
import qualified OpenSSL.Session as SSL
import System.IO
import System.Posix.Signals
runHttpd :: Config -> ResTree -> [FallbackHandler] -> IO ()
runHttpd cnf tree fbs
= withSocketsDo $
do installHandler sigPIPE Ignore Nothing
case cnfSSLConfig cnf of
Nothing
-> return ()
Just scnf
-> do so <- listenOn (sslServerPort scnf)
_loopTID <- forkIO $ httpsLoop (sslContext scnf) so
return ()
httpLoop =<< listenOn (cnfServerPort cnf)
where
httpLoop :: Socket -> IO ()
httpLoop so
= do (h, addr) <- acceptHTTP so
tQueue <- newInteractionQueue
readerTID <- forkIO $ requestReader cnf tree fbs h addr tQueue
_writerTID <- forkIO $ responseWriter cnf h tQueue readerTID
httpLoop so
httpsLoop :: SSL.SSLContext -> Socket -> IO ()
httpsLoop ctx so
= do (ssl, addr) <- acceptHTTPS ctx so
tQueue <- newInteractionQueue
readerTID <- forkIO $ requestReader cnf tree fbs ssl addr tQueue
_writerTID <- forkIO $ responseWriter cnf ssl tQueue readerTID
httpsLoop ctx so
acceptHTTP :: Socket -> IO (Handle, So.SockAddr)
acceptHTTP soSelf
= do (soPeer, addr) <- So.accept soSelf
hPeer <- So.socketToHandle soPeer ReadWriteMode
return (hPeer, addr)
acceptHTTPS :: SSL.SSLContext -> Socket -> IO (SSL.SSL, So.SockAddr)
acceptHTTPS ctx so
= do (so', addr) <- So.accept so
ssl <- SSL.connection ctx so'
SSL.accept ssl
return (ssl, addr)