-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A sensible and clean way to write WebSocket-capable servers in Haskell. -- -- This library allows you to write WebSocket-capable servers. -- -- An example server: -- https://github.com/jaspervdj/websockets/blob/master/example/server.lhs -- -- An example client: -- https://github.com/jaspervdj/websockets/blob/master/example/client.hs -- -- See also: -- -- @package websockets @version 0.11.0.0 -- | Lightweight abstraction over an input/output stream. module Network.WebSockets.Stream -- | Lightweight abstraction over an input/output stream. data Stream -- | Create a stream from a "receive" and "send" action. The following -- properties apply: -- -- makeStream :: IO (Maybe ByteString) -> (Maybe ByteString -> IO ()) -> IO Stream makeSocketStream :: Socket -> IO Stream makeEchoStream :: IO Stream parse :: Stream -> Parser a -> IO (Maybe a) write :: Stream -> ByteString -> IO () close :: Stream -> IO () module Network.WebSockets.Extensions data ExtensionDescription ExtensionDescription :: !ByteString -> ![ExtensionParam] -> ExtensionDescription [extName] :: ExtensionDescription -> !ByteString [extParams] :: ExtensionDescription -> ![ExtensionParam] type ExtensionDescriptions = [ExtensionDescription] parseExtensionDescriptions :: ByteString -> Either String ExtensionDescriptions type NegotiateExtension = ExtensionDescriptions -> Either String Extension -- | An extension is currently allowed to set extra headers and transform -- the parse/write functions of Connection. -- -- This type is very likely to change as other extensions are introduced. data Extension Extension :: Headers -> (IO (Maybe Message) -> IO (IO (Maybe Message))) -> (([Message] -> IO ()) -> IO ([Message] -> IO ())) -> Extension [extHeaders] :: Extension -> Headers [extParse] :: Extension -> IO (Maybe Message) -> IO (IO (Maybe Message)) [extWrite] :: Extension -> ([Message] -> IO ()) -> IO ([Message] -> IO ()) -- | This module exposes connection internals and should only be used if -- you really know what you are doing. module Network.WebSockets.Connection -- | A new client connected to the server. We haven't accepted the -- connection yet, though. data PendingConnection PendingConnection :: !ConnectionOptions -> !RequestHead -> !(Connection -> IO ()) -> !Stream -> PendingConnection -- | Options, passed as-is to the Connection [pendingOptions] :: PendingConnection -> !ConnectionOptions -- | Useful for e.g. inspecting the request path. [pendingRequest] :: PendingConnection -> !RequestHead -- | One-shot callback fired when a connection is accepted, i.e., *after* -- the accepting response is sent to the client. [pendingOnAccept] :: PendingConnection -> !(Connection -> IO ()) -- | Input/output stream [pendingStream] :: PendingConnection -> !Stream -- | Accept a pending connection, turning it into a Connection. acceptRequest :: PendingConnection -> IO Connection -- | This datatype allows you to set options for acceptRequestWith. -- It is strongly recommended to use defaultAcceptRequest and then -- modify the various fields, that way new fields introduced in the -- library do not break your code. data AcceptRequest AcceptRequest :: !(Maybe ByteString) -> !Headers -> AcceptRequest -- | The subprotocol to speak with the client. If -- pendingSubprotcols is non-empty, acceptSubprotocol -- must be one of the subprotocols from the list. [acceptSubprotocol] :: AcceptRequest -> !(Maybe ByteString) -- | Extra headers to send with the response. [acceptHeaders] :: AcceptRequest -> !Headers defaultAcceptRequest :: AcceptRequest -- | This function is like acceptRequest but allows you to set -- custom options using the AcceptRequest datatype. acceptRequestWith :: PendingConnection -> AcceptRequest -> IO Connection rejectRequest :: PendingConnection -> ByteString -> IO () -- | Parameters that allow you to tweak how a request is rejected. Please -- use defaultRejectRequest and modify fields using record syntax -- so your code will not break when new fields are added. data RejectRequest RejectRequest :: !Int -> !ByteString -> Headers -> !ByteString -> RejectRequest -- | The status code, 400 by default. [rejectCode] :: RejectRequest -> !Int -- | The message, "Bad Request" by default [rejectMessage] :: RejectRequest -> !ByteString -- | Extra headers to be sent with the response. [rejectHeaders] :: RejectRequest -> Headers -- | Reponse body of the rejection. [rejectBody] :: RejectRequest -> !ByteString defaultRejectRequest :: RejectRequest rejectRequestWith :: PendingConnection -> RejectRequest -> IO () data Connection Connection :: !ConnectionOptions -> !ConnectionType -> !Protocol -> !(IO (Maybe Message)) -> !([Message] -> IO ()) -> !(IORef Bool) -> Connection [connectionOptions] :: Connection -> !ConnectionOptions [connectionType] :: Connection -> !ConnectionType [connectionProtocol] :: Connection -> !Protocol [connectionParse] :: Connection -> !(IO (Maybe Message)) [connectionWrite] :: Connection -> !([Message] -> IO ()) -- | According to the RFC, both the client and the server MUST send a close -- control message to each other. Either party can initiate the first -- close message but then the other party must respond. Finally, the -- server is in charge of closing the TCP connection. This IORef tracks -- if we have sent a close message and are waiting for the peer to -- respond. [connectionSentClose] :: Connection -> !(IORef Bool) -- | Set options for a Connection. data ConnectionOptions ConnectionOptions :: !(IO ()) -> !CompressionOptions -> !Bool -> ConnectionOptions -- | Whenever a pong is received, this IO action is executed. It -- can be used to tickle connections or fire missiles. [connectionOnPong] :: ConnectionOptions -> !(IO ()) -- | Enable PermessageDeflate. [connectionCompressionOptions] :: ConnectionOptions -> !CompressionOptions -- | Enable strict unicode on the connection. This means that if a client -- (or server) sends invalid UTF-8, we will throw a -- UnicodeException rather than replacing it by the unicode -- replacement character U+FFFD. [connectionStrictUnicode] :: ConnectionOptions -> !Bool defaultConnectionOptions :: ConnectionOptions receive :: Connection -> IO Message -- | Receive an application message. Automatically respond to control -- messages. -- -- When the peer sends a close control message, an exception of type -- CloseRequest is thrown. The peer can send a close control -- message either to initiate a close or in response to a close message -- we have sent to the peer. In either case the CloseRequest -- exception will be thrown. The RFC specifies that the server is -- responsible for closing the TCP connection, which should happen after -- receiving the CloseRequest exception from this function. -- -- This will throw ConnectionClosed if the TCP connection dies -- unexpectedly. receiveDataMessage :: Connection -> IO DataMessage -- | Receive a message, converting it to whatever format is needed. receiveData :: WebSocketsData a => Connection -> IO a send :: Connection -> Message -> IO () -- | Send a DataMessage sendDataMessage :: Connection -> DataMessage -> IO () -- | Send a collection of DataMessages sendDataMessages :: Connection -> [DataMessage] -> IO () -- | Send a message as text sendTextData :: WebSocketsData a => Connection -> a -> IO () -- | Send a collection of messages as text sendTextDatas :: WebSocketsData a => Connection -> [a] -> IO () -- | Send a message as binary data sendBinaryData :: WebSocketsData a => Connection -> a -> IO () -- | Send a collection of messages as binary data sendBinaryDatas :: WebSocketsData a => Connection -> [a] -> IO () -- | Send a friendly close message. Note that after sending this message, -- you should still continue calling receiveDataMessage to process -- any in-flight messages. The peer will eventually respond with a close -- control message of its own which will cause receiveDataMessage -- to throw the CloseRequest exception. This exception is when you -- can finally consider the connection closed. sendClose :: WebSocketsData a => Connection -> a -> IO () -- | Send a friendly close message and close code. Similar to -- sendClose, you should continue calling -- receiveDataMessage until you receive a CloseRequest -- exception. -- -- See http://tools.ietf.org/html/rfc6455#section-7.4 for a list -- of close codes. sendCloseCode :: WebSocketsData a => Connection -> Word16 -> a -> IO () -- | Send a ping sendPing :: WebSocketsData a => Connection -> a -> IO () -- | Forks a ping thread, sending a ping message every n seconds -- over the connection. The thread dies silently if the connection -- crashes or is closed. forkPingThread :: Connection -> Int -> IO () data CompressionOptions NoCompression :: CompressionOptions PermessageDeflateCompression :: PermessageDeflate -> CompressionOptions -- | Four extension parameters are defined for "permessage-deflate" to help -- endpoints manage per-connection resource usage. -- -- data PermessageDeflate PermessageDeflate :: Bool -> Bool -> Int -> Int -> Int -> PermessageDeflate [serverNoContextTakeover] :: PermessageDeflate -> Bool [clientNoContextTakeover] :: PermessageDeflate -> Bool [serverMaxWindowBits] :: PermessageDeflate -> Int [clientMaxWindowBits] :: PermessageDeflate -> Int [pdCompressionLevel] :: PermessageDeflate -> Int defaultPermessageDeflate :: PermessageDeflate instance GHC.Show.Show Network.WebSockets.Connection.CompressionOptions instance GHC.Classes.Eq Network.WebSockets.Connection.CompressionOptions module Network.WebSockets -- | A new client connected to the server. We haven't accepted the -- connection yet, though. data PendingConnection -- | Useful for e.g. inspecting the request path. pendingRequest :: PendingConnection -> RequestHead -- | Accept a pending connection, turning it into a Connection. acceptRequest :: PendingConnection -> IO Connection -- | This datatype allows you to set options for acceptRequestWith. -- It is strongly recommended to use defaultAcceptRequest and then -- modify the various fields, that way new fields introduced in the -- library do not break your code. data AcceptRequest AcceptRequest :: !(Maybe ByteString) -> !Headers -> AcceptRequest -- | The subprotocol to speak with the client. If -- pendingSubprotcols is non-empty, acceptSubprotocol -- must be one of the subprotocols from the list. [acceptSubprotocol] :: AcceptRequest -> !(Maybe ByteString) -- | Extra headers to send with the response. [acceptHeaders] :: AcceptRequest -> !Headers defaultAcceptRequest :: AcceptRequest -- | This function is like acceptRequest but allows you to set -- custom options using the AcceptRequest datatype. acceptRequestWith :: PendingConnection -> AcceptRequest -> IO Connection rejectRequest :: PendingConnection -> ByteString -> IO () -- | Parameters that allow you to tweak how a request is rejected. Please -- use defaultRejectRequest and modify fields using record syntax -- so your code will not break when new fields are added. data RejectRequest RejectRequest :: !Int -> !ByteString -> Headers -> !ByteString -> RejectRequest -- | The status code, 400 by default. [rejectCode] :: RejectRequest -> !Int -- | The message, "Bad Request" by default [rejectMessage] :: RejectRequest -> !ByteString -- | Extra headers to be sent with the response. [rejectHeaders] :: RejectRequest -> Headers -- | Reponse body of the rejection. [rejectBody] :: RejectRequest -> !ByteString defaultRejectRequest :: RejectRequest rejectRequestWith :: PendingConnection -> RejectRequest -> IO () data Connection -- | Set options for a Connection. data ConnectionOptions ConnectionOptions :: !(IO ()) -> !CompressionOptions -> !Bool -> ConnectionOptions -- | Whenever a pong is received, this IO action is executed. It -- can be used to tickle connections or fire missiles. [connectionOnPong] :: ConnectionOptions -> !(IO ()) -- | Enable PermessageDeflate. [connectionCompressionOptions] :: ConnectionOptions -> !CompressionOptions -- | Enable strict unicode on the connection. This means that if a client -- (or server) sends invalid UTF-8, we will throw a -- UnicodeException rather than replacing it by the unicode -- replacement character U+FFFD. [connectionStrictUnicode] :: ConnectionOptions -> !Bool defaultConnectionOptions :: ConnectionOptions data CompressionOptions NoCompression :: CompressionOptions PermessageDeflateCompression :: PermessageDeflate -> CompressionOptions -- | Four extension parameters are defined for "permessage-deflate" to help -- endpoints manage per-connection resource usage. -- -- data PermessageDeflate PermessageDeflate :: Bool -> Bool -> Int -> Int -> Int -> PermessageDeflate [serverNoContextTakeover] :: PermessageDeflate -> Bool [clientNoContextTakeover] :: PermessageDeflate -> Bool [serverMaxWindowBits] :: PermessageDeflate -> Int [clientMaxWindowBits] :: PermessageDeflate -> Int [pdCompressionLevel] :: PermessageDeflate -> Int defaultPermessageDeflate :: PermessageDeflate receive :: Connection -> IO Message -- | Receive an application message. Automatically respond to control -- messages. -- -- When the peer sends a close control message, an exception of type -- CloseRequest is thrown. The peer can send a close control -- message either to initiate a close or in response to a close message -- we have sent to the peer. In either case the CloseRequest -- exception will be thrown. The RFC specifies that the server is -- responsible for closing the TCP connection, which should happen after -- receiving the CloseRequest exception from this function. -- -- This will throw ConnectionClosed if the TCP connection dies -- unexpectedly. receiveDataMessage :: Connection -> IO DataMessage -- | Receive a message, converting it to whatever format is needed. receiveData :: WebSocketsData a => Connection -> IO a send :: Connection -> Message -> IO () -- | Send a DataMessage sendDataMessage :: Connection -> DataMessage -> IO () -- | Send a message as text sendTextData :: WebSocketsData a => Connection -> a -> IO () -- | Send a collection of messages as text sendTextDatas :: WebSocketsData a => Connection -> [a] -> IO () -- | Send a message as binary data sendBinaryData :: WebSocketsData a => Connection -> a -> IO () -- | Send a friendly close message. Note that after sending this message, -- you should still continue calling receiveDataMessage to process -- any in-flight messages. The peer will eventually respond with a close -- control message of its own which will cause receiveDataMessage -- to throw the CloseRequest exception. This exception is when you -- can finally consider the connection closed. sendClose :: WebSocketsData a => Connection -> a -> IO () -- | Send a ping sendPing :: WebSocketsData a => Connection -> a -> IO () -- | Request headers type Headers = [(CI ByteString, ByteString)] -- | A request with a body data Request Request :: RequestHead -> ByteString -> Request -- | An HTTP request. The request body is not yet read. data RequestHead RequestHead :: !ByteString -> Headers -> Bool -> RequestHead [requestPath] :: RequestHead -> !ByteString [requestHeaders] :: RequestHead -> Headers [requestSecure] :: RequestHead -> Bool -- | List of subprotocols specified by the client, in order of preference. -- If the client did not specify a list of subprotocols, this will be the -- empty list. getRequestSubprotocols :: RequestHead -> [ByteString] -- | A response including a body data Response Response :: ResponseHead -> ByteString -> Response -- | HTTP response, without body. data ResponseHead ResponseHead :: !Int -> !ByteString -> Headers -> ResponseHead [responseCode] :: ResponseHead -> !Int [responseMessage] :: ResponseHead -> !ByteString [responseHeaders] :: ResponseHead -> Headers -- | The kind of message a server application typically deals with data Message ControlMessage :: ControlMessage -> Message -- | Reserved bits, actual message DataMessage :: Bool -> Bool -> Bool -> DataMessage -> Message -- | Different control messages data ControlMessage Close :: Word16 -> ByteString -> ControlMessage Ping :: ByteString -> ControlMessage Pong :: ByteString -> ControlMessage -- | For an end-user of this library, dealing with Frames would be -- a bit low-level. This is why define another type on top of it, which -- represents data for the application layer. data DataMessage -- | A textual message. The second field might contain the decoded -- UTF-8 text for caching reasons. This field is computed lazily so if -- it's not accessed, it should have no performance impact. Text :: ByteString -> (Maybe Text) -> DataMessage -- | A binary message. Binary :: ByteString -> DataMessage -- | In order to have an even more high-level API, we define a typeclass -- for values the user can receive from and send to the socket. A few -- warnings apply: -- -- class WebSocketsData a fromDataMessage :: WebSocketsData a => DataMessage -> a fromLazyByteString :: WebSocketsData a => ByteString -> a toLazyByteString :: WebSocketsData a => a -> ByteString -- | Error in case of failed handshake. Will be thrown as an -- Exception. -- -- TODO: This should probably be in the Handshake module, and is solely -- here to prevent a cyclic dependency. data HandshakeException -- | We don't have a match for the protocol requested by the client. todo: -- version parameter NotSupported :: HandshakeException -- | The request was somehow invalid (missing headers or wrong security -- token) MalformedRequest :: RequestHead -> String -> HandshakeException -- | The servers response was somehow invalid (missing headers or wrong -- security token) MalformedResponse :: ResponseHead -> String -> HandshakeException -- | The request was well-formed, but the library user rejected it. (e.g. -- "unknown path") RequestRejected :: Request -> String -> HandshakeException -- | for example "EOF came too early" (which is actually a parse error) or -- for your own errors. (like "unknown path"?) OtherHandshakeException :: String -> HandshakeException -- | Various exceptions that can occur while receiving or transmitting -- messages data ConnectionException -- | The peer has requested that the connection be closed, and included a -- close code and a reason for closing. When receiving this exception, no -- more messages can be sent. Also, the server is responsible for closing -- the TCP connection once this exception is received. -- -- See http://tools.ietf.org/html/rfc6455#section-7.4 for a list -- of close codes. CloseRequest :: Word16 -> ByteString -> ConnectionException -- | The peer unexpectedly closed the connection while we were trying to -- receive some data. This is a violation of the websocket RFC since the -- TCP connection should only be closed after sending and receiving close -- control messages. ConnectionClosed :: ConnectionException -- | The client sent garbage, i.e. we could not parse the WebSockets -- stream. ParseException :: String -> ConnectionException -- | The client sent invalid UTF-8. Note that this exception will only be -- thrown if strict decoding is set in the connection options. UnicodeException :: String -> ConnectionException -- | WebSockets application that can be ran by a server. Once this -- IO action finishes, the underlying socket is closed -- automatically. type ServerApp = PendingConnection -> IO () -- | Provides a simple server. This function blocks forever. Note that this -- is merely provided for quick-and-dirty standalone applications, for -- real applications, you should use a real server. -- -- Glue for using this package with real servers is provided by: -- -- runServer :: String -> Int -> ServerApp -> IO () -- | A version of runServer which allows you to customize some -- options. runServerWith :: String -> Int -> ConnectionOptions -> ServerApp -> IO () -- | Create a standardized socket on which you can listen for incomming -- connections. Should only be used for a quick and dirty solution! -- Should be preceded by the call withSocketsDo. makeListenSocket :: String -> Int -> IO Socket -- | Turns a socket, connected to some client, into a -- PendingConnection. The PendingConnection should be -- closed using close later. makePendingConnection :: Socket -> ConnectionOptions -> IO PendingConnection -- | More general version of makePendingConnection for Stream -- instead of a Socket. makePendingConnectionFromStream :: Stream -> ConnectionOptions -> IO PendingConnection -- | A client application interacting with a single server. Once this -- IO action finished, the underlying socket is closed -- automatically. type ClientApp a = Connection -> IO a runClient :: String -> Int -> String -> ClientApp a -> IO a runClientWith :: String -> Int -> String -> ConnectionOptions -> Headers -> ClientApp a -> IO a runClientWithSocket :: Socket -> String -> String -> ConnectionOptions -> Headers -> ClientApp a -> IO a runClientWithStream :: Stream -> String -> String -> ConnectionOptions -> Headers -> ClientApp a -> IO a -- | Forks a ping thread, sending a ping message every n seconds -- over the connection. The thread dies silently if the connection -- crashes or is closed. forkPingThread :: Connection -> Int -> IO ()