-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(runtime): Add unix domain socket transport
- Loading branch information
1 parent
93c74a2
commit b9cc0f7
Showing
9 changed files
with
183 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
src/runtime-prototype/src/StuntDouble/Transport/NamedPipeCodec.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
{-# language OverloadedStrings #-} | ||
module StuntDouble.Transport.NamedPipeCodec where | ||
|
||
import qualified Data.ByteString.Lazy as BSL | ||
import qualified Data.ByteString.Lazy.Char8 as BSLC | ||
import Control.Concurrent.Async | ||
import Control.Exception | ||
import System.Directory | ||
import System.FilePath | ||
import System.IO | ||
import System.IO.Error | ||
import System.Posix.Files | ||
import System.Timeout | ||
|
||
import StuntDouble.Codec | ||
import StuntDouble.Envelope | ||
import StuntDouble.Message | ||
import StuntDouble.Reference | ||
import StuntDouble.Transport | ||
|
||
------------------------------------------------------------------------ | ||
|
||
namedPipeTransport :: FilePath -> EventLoopName -> Codec ->IO (Transport IO) | ||
namedPipeTransport fp name (Codec encode decode) = do | ||
safeCreateNamedPipe (fp </> getEventLoopName name) | ||
h <- openFile (fp </> getEventLoopName name) ReadWriteMode | ||
putStrLn $ "Listening on: " <> (fp </> getEventLoopName name) | ||
hSetBuffering h LineBuffering | ||
return Transport { transportSend = \e -> | ||
let Encode addr _corrId payload = encode e in | ||
withFile (fp </> addr) WriteMode $ \h' -> do | ||
hSetBuffering h' LineBuffering | ||
BSL.hPutStr h' (payload <> "\n") | ||
, transportReceive = do | ||
m <- hMaybeGetLine h | ||
case m of | ||
Nothing -> return Nothing | ||
Just resp -> do | ||
putStrLn "Found input" | ||
case decode resp of | ||
Left err -> error ("transportReceive: couldn't parse response: " ++ show err) | ||
Right envelope -> return . pure $ envelope | ||
, transportShutdown = cleanUpNamedPipe fp name | ||
} | ||
|
||
safeCreateNamedPipe :: FilePath -> IO () | ||
safeCreateNamedPipe fp = | ||
catchJust | ||
(\e -> if isAlreadyExistsErrorType (ioeGetErrorType e) | ||
then Just () | ||
else Nothing) | ||
(createNamedPipe fp | ||
(namedPipeMode `unionFileModes` | ||
ownerReadMode `unionFileModes` | ||
ownerWriteMode)) | ||
return | ||
|
||
cleanUpNamedPipe :: FilePath -> EventLoopName -> IO () | ||
cleanUpNamedPipe fp name = | ||
catchJust | ||
(\e -> if isDoesNotExistErrorType (ioeGetErrorType e) | ||
then Just () | ||
else Nothing) | ||
(removeFile (fp </> getEventLoopName name)) | ||
return | ||
|
||
hMaybeGetLine :: Handle -> IO (Maybe BSL.ByteString) | ||
hMaybeGetLine = timeout 10 . fmap BSLC.pack . hGetLine |
87 changes: 87 additions & 0 deletions
87
src/runtime-prototype/src/StuntDouble/Transport/UnixSocket.hs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
module StuntDouble.Transport.UnixSocket where | ||
|
||
import qualified Data.ByteString.Lazy as BSL | ||
import qualified Data.ByteString.Lazy.Char8 as BSLC | ||
import Control.Concurrent (forkFinally) | ||
import Control.Concurrent.Async | ||
import Control.Concurrent.STM | ||
import Control.Exception | ||
import qualified Control.Exception as E | ||
import Control.Monad(forever) | ||
import qualified Data.Aeson as Aeson | ||
import System.Directory | ||
import System.FilePath | ||
import System.IO | ||
import System.IO.Error | ||
import System.Posix.Files | ||
import System.Timeout | ||
import Network.Socket | ||
import Network.Socket.ByteString.Lazy (recv, sendAll) | ||
|
||
import StuntDouble.Codec | ||
import StuntDouble.Envelope | ||
import StuntDouble.Message | ||
import StuntDouble.Reference | ||
import StuntDouble.Transport | ||
|
||
------------------------------------------------------------------------ | ||
|
||
unixSocketTransport :: FilePath -> EventLoopName -> Codec -> IO (Transport IO) | ||
unixSocketTransport fp name c@(Codec encode _) = withSocketsDo $ do | ||
queue <- newTBQueueIO 128 -- XXX: when/how does this grow? | ||
let udsFP = fp </> getEventLoopName name <> ".sock" | ||
putStrLn $ "Listening on: " <> udsFP | ||
cleanUpUnixDomainSocket udsFP | ||
aServer <- async (runServer udsFP c queue) | ||
-- maybe we need to block until server is up? | ||
return Transport { transportSend = \e -> | ||
let Encode addr _corrId payload = encode e in | ||
transportSend' (fp </> addr <> ".sock") payload | ||
, transportReceive = atomically (tryReadTBQueue queue) | ||
, transportShutdown = do | ||
cancel aServer | ||
cleanUpUnixDomainSocket udsFP | ||
} | ||
|
||
uSocket = socket AF_UNIX Stream defaultProtocol | ||
|
||
runServer :: FilePath -> Codec -> TBQueue Envelope -> IO () | ||
runServer fp (Codec _ decode) queue = do | ||
E.bracket open close loop | ||
where | ||
open = E.bracketOnError uSocket close $ \s -> do | ||
setSocketOption s ReuseAddr 1 | ||
withFdSocket s setCloseOnExecIfNeeded | ||
putStrLn $ "Binding socket for: " <> fp | ||
bind s (SockAddrUnix fp) | ||
listen s 1024 | ||
return s | ||
loop s = forever $ E.bracketOnError (accept s) (close . fst) $ \ (conn, peer) -> do | ||
forkFinally (server conn) (const $ gracefulClose conn 5000) | ||
server conn = do | ||
msg <- recv conn 1024 | ||
case decode msg of | ||
Left err -> error err | ||
Right envelope -> do | ||
atomically $ writeTBQueue queue envelope | ||
server conn | ||
|
||
-- we should have open connections? | ||
transportSend' :: FilePath -> BSL.ByteString -> IO () | ||
transportSend' addr payload = do | ||
withSocketsDo $ E.bracket open close client | ||
where | ||
client c = do | ||
sendAll c payload | ||
open = E.bracketOnError uSocket close $ \s -> do | ||
connect s (SockAddrUnix addr) | ||
return s | ||
|
||
cleanUpUnixDomainSocket :: FilePath -> IO () | ||
cleanUpUnixDomainSocket fp = | ||
catchJust | ||
(\e -> if isDoesNotExistErrorType (ioeGetErrorType e) | ||
then Just () | ||
else Nothing) | ||
(removeFile fp) | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters