aboutsummaryrefslogtreecommitdiffstats
path: root/src/Network/Socket/Extended.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/Socket/Extended.hs')
-rw-r--r--src/Network/Socket/Extended.hs78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/Network/Socket/Extended.hs b/src/Network/Socket/Extended.hs
new file mode 100644
index 0000000..8d71956
--- /dev/null
+++ b/src/Network/Socket/Extended.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE RecordWildCards #-}
+module Network.Socket.Extended
+ ( module Exports
+ , openSocket
+ , closeSocket
+ , getAddrFamily
+ , getAddrPort
+ , readListenString
+ ) where
+
+import qualified Network.Socket as Exports
+
+import Network.Socket
+import Network.URI
+import Network.Wai.Handler.Warp (Port)
+import System.Posix.Files.Extended (removeIfExists)
+
+openSocket :: SockAddr -> IO Socket
+openSocket sockAddr = do
+ let family = getAddrFamily sockAddr
+ case sockAddr of
+ SockAddrUnix sockFile -> removeIfExists sockFile
+ _ -> return ()
+ socket family Stream defaultProtocol
+
+closeSocket :: Socket -> IO ()
+closeSocket sock = do
+ name <- getSocketName sock
+ close sock
+ case name of
+ SockAddrUnix sockFile -> removeIfExists sockFile
+ _ -> return ()
+
+getAddrFamily :: SockAddr -> Family
+getAddrFamily = \case
+ SockAddrInet _ _ -> AF_INET
+ SockAddrInet6 _ _ _ _ -> AF_INET6
+ SockAddrUnix _ -> AF_UNIX
+ sockAddr -> error ("getAddrFamily: don't know family of " <> show sockAddr)
+
+getAddrPort :: SockAddr -> Port
+getAddrPort = \case
+ SockAddrInet portNumber _ -> fromIntegral portNumber
+ SockAddrInet6 portNumber _ _ _ -> fromIntegral portNumber
+ _ -> 0
+
+readListenString :: String -> IO (Either String SockAddr)
+readListenString cListen =
+ case parseURI cListen of
+ Just URI{..} ->
+ case uriScheme of
+ "inet:" ->
+ case uriAuthority of
+ Just URIAuth{..} -> do
+ let
+ hostName =
+ if uriRegName == "" then
+ Nothing
+ else
+ Just uriRegName
+ serviceName =
+ if uriPort == "" then
+ Nothing
+ else
+ Just (tail uriPort)
+ AddrInfo{..}:_ <-
+ getAddrInfo Nothing hostName serviceName
+ return (Right addrAddress)
+ Nothing ->
+ return (Left "could not parse inet listen string")
+ "unix:" ->
+ return (Right (SockAddrUnix uriPath))
+ invalid ->
+ return (Left ("unsupported listen scheme: " <> invalid))
+ Nothing ->
+ return (Left "could not parse listen string")
+