2023-12-09 12:58:59 +00:00
|
|
|
module Server.Communication where
|
|
|
|
|
|
|
|
import Control.Monad
|
|
|
|
|
|
|
|
import Network.Socket
|
|
|
|
|
|
|
|
import System.Posix.Signals
|
|
|
|
|
|
|
|
-- internal imports
|
|
|
|
|
|
|
|
import Server.Util
|
|
|
|
|
2023-12-09 13:18:10 +00:00
|
|
|
-- | Function which determines whether the given filePath is a supported socket path and
|
|
|
|
-- subsequently creates a socket in said location.
|
|
|
|
bindSocket
|
|
|
|
:: FilePath -- ^ File Path for socket to be created (e.g.: "/tmp/wizard.sock")
|
|
|
|
-> IO Socket -- ^ resulting Socket
|
2023-12-09 12:58:59 +00:00
|
|
|
bindSocket path = do
|
|
|
|
let sockAddr = SockAddrUnix path
|
|
|
|
unless (isSupportedSockAddr sockAddr)
|
|
|
|
(error $ "invalid socket path " <> path)
|
2023-12-09 13:18:10 +00:00
|
|
|
-- aremoveIfExists path
|
2023-12-09 12:58:59 +00:00
|
|
|
sock <- socket AF_UNIX Stream 0
|
|
|
|
bind sock sockAddr
|
|
|
|
pure sock
|
|
|
|
|
2023-12-09 13:18:10 +00:00
|
|
|
-- | Function that installs a handler on SIGINT to close and remove the given socket
|
|
|
|
terminateSocketOnSigint
|
|
|
|
:: Socket -- ^ Socket to terminate on termination
|
|
|
|
-> IO ()
|
|
|
|
terminateSocketOnSigint sock =
|
2023-12-09 12:58:59 +00:00
|
|
|
void $ installHandler
|
|
|
|
keyboardSignal
|
|
|
|
(CatchOnce $ do
|
|
|
|
(SockAddrUnix path) <- getSocketName sock
|
|
|
|
close' sock
|
|
|
|
removeIfExists path
|
2023-12-09 13:11:37 +00:00
|
|
|
-- Raise SIGINT again so it does not get blocked
|
2023-12-09 12:58:59 +00:00
|
|
|
raiseSignal keyboardSignal
|
|
|
|
)
|
|
|
|
Nothing
|