Safe Haskell | None |
---|
Implementation of the Ganeti Unix Domain Socket JSON server interface.
Synopsis
- withTimeout :: Int -> String -> IO a -> IO a
- data RecvResult
- = RecvConnClosed
- | RecvError String
- | RecvOk String
- eOM :: Word8
- bEOM :: ByteString
- data MsgKeys
- strOfKey :: MsgKeys -> String
- data ServerConfig = ServerConfig {}
- data ConnectConfig = ConnectConfig {}
- data Client = Client {
- rsocket :: Handle
- wsocket :: Handle
- rbuf :: IORef ByteString
- clientConfig :: ConnectConfig
- data Server = Server {
- sSocket :: Socket
- sPath :: FilePath
- serverConfig :: ConnectConfig
- openClientSocket :: Int -> FilePath -> IO Handle
- closeClientSocket :: Handle -> IO ()
- openServerSocket :: FilePath -> IO Socket
- closeServerSocket :: Socket -> FilePath -> IO ()
- acceptSocket :: Socket -> IO Handle
- connectClient :: ConnectConfig -> Int -> FilePath -> IO Client
- connectServer :: ServerConfig -> Bool -> FilePath -> IO Server
- pipeClient :: ConnectConfig -> IO (Client, Client)
- closeServer :: MonadBase IO m => Server -> m ()
- acceptClient :: Server -> IO Client
- closeClient :: Client -> IO ()
- clientToFd :: Client -> IO (Fd, Fd)
- clientToHandle :: Client -> (Handle, Handle)
- sendMsg :: Client -> String -> IO ()
- recvUpdate :: ConnectConfig -> Handle -> ByteString -> IO (ByteString, ByteString)
- recvMsg :: Client -> IO String
- recvMsgExt :: Client -> IO RecvResult
- buildCall :: (JSON mth, JSON args) => mth -> args -> String
- parseCall :: (JSON mth, JSON args) => String -> Result (mth, args)
- buildResponse :: Bool -> JSValue -> String
- decodeError :: JSValue -> ErrorResult JSValue
- parseResponse :: String -> ErrorResult JSValue
- logMsg :: (Show e, JSON e, MonadLog m) => Handler i m o -> i -> GenericResult e JSValue -> m ()
- prepareMsg :: JSON e => GenericResult e JSValue -> (Bool, JSValue)
- type HandlerResult m o = m (Bool, GenericResult GanetiException o)
- data Handler i m o = Handler {
- hParse :: JSValue -> JSValue -> Result i
- hInputLogShort :: i -> String
- hInputLogLong :: i -> String
- hExec :: i -> HandlerResult m o
- handleJsonMessage :: (JSON o, Monad m) => Handler i m o -> i -> HandlerResult m JSValue
- handleRawMessage :: (JSON o, MonadLog m) => Handler i m o -> String -> m (Bool, String)
- isRisky :: RecvResult -> Bool
- handleClient :: (JSON o, MonadBase IO m, MonadLog m) => Handler i m o -> Client -> m Bool
- clientLoop :: (JSON o, MonadBase IO m, MonadLog m) => Handler i m o -> Client -> m ()
- listener :: (JSON o, MonadBaseControl IO m, MonadLog m) => Handler i m o -> Server -> m ()
Utility functions
withTimeout :: Int -> String -> IO a -> IO a Source #
Wrapper over System.Timeout.timeout that fails in the IO monad.
Generic protocol functionality
data RecvResult Source #
Result of receiving a message from the socket.
RecvConnClosed | Connection closed |
RecvError String | Any other error |
RecvOk String | Successfull receive |
Instances
Eq RecvResult # | |
Defined in Ganeti.UDSServer (==) :: RecvResult -> RecvResult -> Bool (/=) :: RecvResult -> RecvResult -> Bool | |
Show RecvResult # | |
Defined in Ganeti.UDSServer showsPrec :: Int -> RecvResult -> ShowS show :: RecvResult -> String showList :: [RecvResult] -> ShowS |
data ServerConfig Source #
A client encapsulation. Note that it has separate read and write handle. For sockets it is the same handle. It is required for bi-directional inter-process pipes though.
Client | |
|
A server encapsulation.
Server | |
|
Unix sockets
:: Int | connection timeout |
-> FilePath | socket path |
-> IO Handle |
Creates a Unix socket and connects it to the specified path
,
where timeout
specifies the connection timeout.
closeClientSocket :: Handle -> IO () Source #
Closes the handle. Performing the operation on a handle that has already been closed has no effect; doing so is not an error. All other operations on a closed handle will fail.
openServerSocket :: FilePath -> IO Socket Source #
Creates a Unix socket and binds it to the specified path
.
closeServerSocket :: Socket -> FilePath -> IO () Source #
acceptSocket :: Socket -> IO Handle Source #
Client and server
:: ConnectConfig | configuration for the client |
-> Int | connection timeout |
-> FilePath | socket path |
-> IO Client |
Connects to the master daemon and returns a Client.
connectServer :: ServerConfig -> Bool -> FilePath -> IO Server Source #
Creates and returns a server endpoint.
pipeClient :: ConnectConfig -> IO (Client, Client) Source #
Creates a new bi-directional client pipe. The two returned clients talk to each other through the pipe.
closeServer :: MonadBase IO m => Server -> m () Source #
Closes a server endpoint.
acceptClient :: Server -> IO Client Source #
Accepts a client
closeClient :: Client -> IO () Source #
Closes the client socket. Performing the operation on a client that has already been closed has no effect; doing so is not an error. All other operations on a closed client will fail with an exception.
clientToFd :: Client -> IO (Fd, Fd) Source #
Extracts the read (the first) and the write (the second) file descriptor
of a client. This closes the underlying Handle
s, therefore the original
client is closed and unusable after the call.
The purpose of this function is to keep the communication channel open,
while replacing a Client
with some other means.
clientToHandle :: Client -> (Handle, Handle) Source #
Extracts the read (first) and the write (second) handles of a client. The purpose of this function is to allow using a client's handles as input/output streams elsewhere.
recvUpdate :: ConnectConfig -> Handle -> ByteString -> IO (ByteString, ByteString) Source #
Given a current buffer and the handle, it will read from the network until we get a full message, and it will return that message and the leftover buffer contents.
recvMsgExt :: Client -> IO RecvResult Source #
Extended wrapper over recvMsg.
:: (JSON mth, JSON args) | |
=> mth | The method |
-> args | The arguments |
-> String | The serialized form |
Serialize a request to String.
parseCall :: (JSON mth, JSON args) => String -> Result (mth, args) Source #
Parse the required keys out of a call.
:: Bool | Success |
-> JSValue | The arguments |
-> String | The serialized form |
Serialize the response to String.
decodeError :: JSValue -> ErrorResult JSValue Source #
Try to decode an error from the server response. This function will always fail, since it's called only on the error path (when status is False).
parseResponse :: String -> ErrorResult JSValue Source #
Check that luxi responses contain the required keys and that the call was successful.
:: (Show e, JSON e, MonadLog m) | |
=> Handler i m o | |
-> i | the received request (used for logging) |
-> GenericResult e JSValue | A message to be sent |
-> m () |
Logs an outgoing message.
:: JSON e | |
=> GenericResult e JSValue | A message to be sent |
-> (Bool, JSValue) |
Prepares an outgoing message.
Processing client requests
type HandlerResult m o = m (Bool, GenericResult GanetiException o) Source #
Handler | |
|
:: (JSON o, Monad m) | |
=> Handler i m o | handler |
-> i | parsed input |
-> HandlerResult m JSValue |
Takes a request as a String
, parses it, passes it to a handler and
formats its response.
isRisky :: RecvResult -> Bool Source #
handleClient :: (JSON o, MonadBase IO m, MonadLog m) => Handler i m o -> Client -> m Bool Source #
Reads a request, passes it to a handler and sends a response back to the client.
clientLoop :: (JSON o, MonadBase IO m, MonadLog m) => Handler i m o -> Client -> m () Source #
Main client loop: runs one loop of handleClient
, and if that
doesn't report a finished (closed) connection, restarts itself.