Skip to content

Commit

Permalink
Add actions for getting 1 or 2 sockets
Browse files Browse the repository at this point in the history
Also added a re-export of the Socket type
  • Loading branch information
chris-martin committed May 28, 2018
1 parent db6a14d commit 18a9c51
Showing 1 changed file with 67 additions and 1 deletion.
68 changes: 67 additions & 1 deletion Network/Socket/Activation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,20 @@
-- | This is a module for systemd socket activation. See
-- <http://0pointer.de/blog/projects/socket-activation.html> and
-- <http://www.freedesktop.org/software/systemd/man/systemd.socket.html>
module Network.Socket.Activation (getActivatedSockets) where
module Network.Socket.Activation
(
-- * Getting all activated sockets
getActivatedSockets

-- * Getting a fixed numbers of sockets
-- $fixed
, getExactlyOneActivatedSocket
, getExactlyTwoActivatedSockets

-- * Re-exported types
, Socket

) where

import Control.Applicative
import Control.Monad
Expand All @@ -24,6 +37,10 @@ fdStart = 3
-- the associated @.socket@ file. The sockets will have their family, type,
-- and status set appropriately. Returns @Nothing@ in systems without socket activation (or
-- when the program was not socket activated).
--
-- If your program requires being started with some small fixed number of
-- sockets, you may want to use 'getExactlyOneActivatedSocket' or
-- 'getExactlyTwoActivatedSockets'.
getActivatedSockets :: IO (Maybe [Socket])
getActivatedSockets = runMaybeT $ do
listenPid <- read <$> MaybeT (getEnv "LISTEN_PID")
Expand All @@ -38,6 +55,55 @@ getActivatedSockets = runMaybeT $ do
stat <- socketStatus fd
lift $ mkSocket fd fam typ defaultProtocol stat

-- $fixed
-- Often a program using socket activation will require being activated
-- some fixed number of sockets. Here we provide some actions to make it
-- convenient to get the number of activated sockets your program expects
-- or otherwise fail with an informative error message.

-- | Return an activated socket, if the program was started with exactly
-- one activated socket. The socket will have its family, type, and
-- status set appropriately. Returns @Left@ containing an error message
-- if the program was not started with exactly one activated socket.
--
-- The more general version of this for any number of sockets is
-- 'getActivatedSockets'. If you need two sockets instead of one, use
-- 'getExactlyTwoActivatedSockets'.
getExactlyOneActivatedSocket :: IO (Either String Socket)
getExactlyOneActivatedSocket = do
socketsMaybe <- getActivatedSockets
return $ case socketsMaybe of
Nothing -> Left "This program is not socket activated."
Just xs -> case xs of
[] -> Left "This program is socket activated, but \
\there are no sockets. Exactly one is required."
[x] -> Right x
_ -> Left $ "There are too many activated sockets; \
\expected 1, got " ++ show (length xs)

-- | Return two activated sockets, if the program was started with exactly
-- two activated sockets. The sockets are in the same order as in
-- the associated @.socket@ file. The sockets will have their family, type,
-- and status set appropriately. Returns @Left@ containing an error message
-- if the program was not started with exactly two activated sockets.
--
-- The more general version of this for any number of sockets is
-- 'getActivatedSockets'. If you need one socket instead of two, use
-- 'getExactlyOneActivatedSocket'.
getExactlyTwoActivatedSockets :: IO (Either String (Socket, Socket))
getExactlyTwoActivatedSockets = do
socketsMaybe <- getActivatedSockets
return $ case socketsMaybe of
Nothing -> Left "This program is not socket activated."
Just xs -> case xs of
[] -> Left "This program is socket activated, but \
\there are no sockets. Exactly two are required."
[_] -> Left "This program was started with only one activated \
\socket. Exactly two are required."
[x, y] -> Right (x, y)
_ -> Left $ "There are too many activated sockets; \
\expected 2, got " ++ show (length xs)

socketFamily :: CInt -> MaybeT IO Family
socketFamily fd = do
familyInt <- lift $ c_socket_family fd
Expand Down

0 comments on commit 18a9c51

Please sign in to comment.