summaryrefslogtreecommitdiff
path: root/mini-http/Network/HTTP/Server/Mini.hs
diff options
context:
space:
mode:
Diffstat (limited to 'mini-http/Network/HTTP/Server/Mini.hs')
-rw-r--r--mini-http/Network/HTTP/Server/Mini.hs76
1 files changed, 0 insertions, 76 deletions
diff --git a/mini-http/Network/HTTP/Server/Mini.hs b/mini-http/Network/HTTP/Server/Mini.hs
deleted file mode 100644
index 3c5c3f6..0000000
--- a/mini-http/Network/HTTP/Server/Mini.hs
+++ /dev/null
@@ -1,76 +0,0 @@
-{-# LANGUAGE TypeApplications #-}
-module Network.HTTP.Server.Mini (
- run,
- module Network.HTTP.Server.Mini.Types,
-) where
-
-import Control.Concurrent
-import Control.Concurrent.STM
-import Control.Exception
-import Control.Monad
-import Data.List.NonEmpty qualified as NE
-import Network.Socket
-import Network.Socket.ByteString
-
-import Network.HTTP.Server.Mini.Parser
-import Network.HTTP.Server.Mini.Printer
-import Network.HTTP.Server.Mini.Types
-
-
--- | The request handler will run in a forkIO thread.
-run :: Settings -> (Request -> IO Response) -> IO ()
-run settings handler = do
- let hints = defaultHints { addrFlags = [AI_NUMERICHOST, AI_NUMERICSERV, AI_PASSIVE]
- , addrSocketType = Stream }
- addrs <- getAddrInfo @NE.NonEmpty (Just hints) Nothing (Just (show (setPort settings)))
-
- semaphore <- newTVarIO (setMaxParallelRequests settings)
- finishVar <- newEmptyMVar
-
- threads <- forM addrs $ \addr ->
- forkIO $
- bracket
- (openSocket addr)
- (\sock -> close sock `finally` putMVar finishVar ())
- (\sock -> do
- setSocketOption sock ReusePort 1
- bind sock (addrAddress addr)
- listen sock (setListenQueue settings)
- acceptLoop sock semaphore)
-
- takeMVar finishVar
- forM_ threads killThread
- where
- -- Put the forever _outside_ the mask_ to unmask briefly between iterations
- -- (when it's safe because we have nothing ongoing).
- acceptLoop sock semaphore = forever $ mask_ $ do
- -- Because we're masked, if atomically exits with an async exception, it
- -- was while blocking so the transaction failed, so nothing happened, so
- -- no cleanup necessary.
- atomically $ do
- n <- readTVar semaphore
- when (n == 0) retry
- writeTVar semaphore $! n - 1
- let increment = atomically (modifyTVar' semaphore (+1))
-
- (conn, _peer) <- accept sock `onException` increment
- let cleanup = close conn `finally` increment
-
- onException
- (do allowInterrupt -- we're masked but we just blocked (in `accept` in FFI), so let exceptions through
- -- Now either the forkIO succeeds (and the responsibility for
- -- closing and incrementing is passed to the thread) or it fails
- -- (and we retain both responsibilities).
- void $ forkIO $
- handleConnection settings conn handler `finally` cleanup)
- cleanup
-
--- | Will not close the connection, instead will just return, expecting the
--- caller to close the connection then.
-handleConnection :: Settings -> Socket -> (Request -> IO Response) -> IO ()
-handleConnection settings conn handler =
- readRequest (setMaxRequestSize settings) (recv conn) >>= \case
- Nothing -> return ()
- Just req -> do
- resp <- handler req
- sendResponse conn resp