Add support for Unix domain socket connection
Update corresponding parser in readHostPortM Update showHostPort
This commit is contained in:
parent
76d5f84f8a
commit
4d1b2a0108
2 changed files with 38 additions and 11 deletions
|
@ -29,10 +29,10 @@ import Data.List (intersect, partition, (\\), delete)
|
||||||
import Control.Applicative ((<$>))
|
import Control.Applicative ((<$>))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
import Control.Monad (forM_)
|
import Control.Monad (forM_, guard)
|
||||||
import System.IO.Unsafe (unsafePerformIO)
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
import System.Timeout (timeout)
|
import System.Timeout (timeout)
|
||||||
import Text.ParserCombinators.Parsec (parse, many1, letter, digit, char, eof,
|
import Text.ParserCombinators.Parsec (parse, many1, letter, digit, char, anyChar, eof,
|
||||||
spaces, try, (<|>))
|
spaces, try, (<|>))
|
||||||
import qualified Data.List as List
|
import qualified Data.List as List
|
||||||
|
|
||||||
|
@ -76,14 +76,15 @@ host hostname = Host hostname defaultPort
|
||||||
|
|
||||||
showHostPort :: Host -> String
|
showHostPort :: Host -> String
|
||||||
-- ^ Display host as \"host:port\"
|
-- ^ Display host as \"host:port\"
|
||||||
-- TODO: Distinguish Service and UnixSocket port
|
-- TODO: Distinguish Service port
|
||||||
showHostPort (Host hostname port) = hostname ++ ":" ++ portname where
|
showHostPort (Host hostname (PortNumber port)) = hostname ++ ":" ++ show port
|
||||||
portname = case port of
|
#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
|
||||||
PortNumber p -> show p
|
showHostPort (Host _ (UnixSocket path)) = "unix:" ++ path
|
||||||
|
#endif
|
||||||
|
|
||||||
readHostPortM :: (Monad m) => String -> m Host
|
readHostPortM :: (Monad m) => String -> m Host
|
||||||
-- ^ Read string \"hostname:port\" as @Host hosthame (PortNumber port)@ or \"hostname\" as @host hostname@ (default port). Fail if string does not match either syntax.
|
-- ^ Read string \"hostname:port\" as @Host hosthame (PortNumber port)@ or \"hostname\" as @host hostname@ (default port). Fail if string does not match either syntax.
|
||||||
-- TODO: handle Service and UnixSocket port
|
-- TODO: handle Service port
|
||||||
readHostPortM = either (fail . show) return . parse parser "readHostPort" where
|
readHostPortM = either (fail . show) return . parse parser "readHostPort" where
|
||||||
hostname = many1 (letter <|> digit <|> char '-' <|> char '.')
|
hostname = many1 (letter <|> digit <|> char '-' <|> char '.')
|
||||||
parser = do
|
parser = do
|
||||||
|
@ -91,9 +92,15 @@ readHostPortM = either (fail . show) return . parse parser "readHostPort" where
|
||||||
h <- hostname
|
h <- hostname
|
||||||
try (spaces >> eof >> return (host h)) <|> do
|
try (spaces >> eof >> return (host h)) <|> do
|
||||||
_ <- char ':'
|
_ <- char ':'
|
||||||
port :: Int <- read <$> many1 digit
|
try ( do port :: Int <- read <$> many1 digit
|
||||||
spaces >> eof
|
spaces >> eof
|
||||||
return $ Host h (PortNumber $ fromIntegral port)
|
return $ Host h (PortNumber $ fromIntegral port))
|
||||||
|
#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
|
||||||
|
<|> do guard (h == "unix")
|
||||||
|
p <- many1 anyChar
|
||||||
|
eof
|
||||||
|
return $ Host "" (UnixSocket p)
|
||||||
|
#endif
|
||||||
|
|
||||||
readHostPort :: String -> Host
|
readHostPort :: String -> Host
|
||||||
-- ^ Read string \"hostname:port\" as @Host hostname (PortNumber port)@ or \"hostname\" as @host hostname@ (default port). Error if string does not match either syntax.
|
-- ^ Read string \"hostname:port\" as @Host hostname (PortNumber port)@ or \"hostname\" as @host hostname@ (default port). Error if string does not match either syntax.
|
||||||
|
|
|
@ -21,7 +21,11 @@ import System.IO (Handle, IOMode(ReadWriteMode))
|
||||||
|
|
||||||
-- | Wraps network's 'PortNumber'
|
-- | Wraps network's 'PortNumber'
|
||||||
-- Used to ease compatibility between older and newer network versions.
|
-- Used to ease compatibility between older and newer network versions.
|
||||||
newtype PortID = PortNumber N.PortNumber deriving (Enum, Eq, Integral, Num, Ord, Read, Real, Show)
|
data PortID = PortNumber N.PortNumber
|
||||||
|
#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
|
||||||
|
| UnixSocket String
|
||||||
|
#endif
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
|
||||||
#if !MIN_VERSION_network(2, 9, 0)
|
#if !MIN_VERSION_network(2, 9, 0)
|
||||||
|
@ -32,6 +36,10 @@ connectTo :: N.HostName -- Hostname
|
||||||
-> IO Handle -- Connected Socket
|
-> IO Handle -- Connected Socket
|
||||||
connectTo hostname (PortNumber port) = N.connectTo hostname (N.PortNumber port)
|
connectTo hostname (PortNumber port) = N.connectTo hostname (N.PortNumber port)
|
||||||
|
|
||||||
|
#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
|
||||||
|
connectTo _ (UnixSocket path) = N.connectTo "" (N.UnixSocket path)
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
-- Copied implementation from network 2.8's 'connectTo', but using our 'PortID' newtype.
|
-- Copied implementation from network 2.8's 'connectTo', but using our 'PortID' newtype.
|
||||||
|
@ -49,4 +57,16 @@ connectTo hostname (PortNumber port) = do
|
||||||
N.connect sock (N.SockAddrInet port (hostAddress he))
|
N.connect sock (N.SockAddrInet port (hostAddress he))
|
||||||
N.socketToHandle sock ReadWriteMode
|
N.socketToHandle sock ReadWriteMode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#if !defined(mingw32_HOST_OS) && !defined(cygwin32_HOST_OS) && !defined(_WIN32)
|
||||||
|
connectTo _ (UnixSocket path) = do
|
||||||
|
bracketOnError
|
||||||
|
(N.socket N.AF_UNIX N.Stream 0)
|
||||||
|
(N.close)
|
||||||
|
(\sock -> do
|
||||||
|
N.connect sock (N.SockAddrUnix path)
|
||||||
|
N.socketToHandle sock ReadWriteMode
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue