-- 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.9.7.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:
--
--
-- - Regardless of the provided "receive" and "send" functions, reading
-- and writing from the stream will be thread-safe, i.e. this function
-- will create a receive and write lock to be used internally.
-- - Reading from or writing or to a closed Stream will always
-- throw an exception, even if the underlying "receive" and "send"
-- functions do not (we do the bookkeeping).
-- - Streams should always be closed.
--
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 ()
-- | 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
data AcceptRequest
AcceptRequest :: !(Maybe ByteString) -> 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)
acceptRequest :: PendingConnection -> IO Connection
acceptRequestWith :: PendingConnection -> AcceptRequest -> IO Connection
rejectRequest :: PendingConnection -> ByteString -> 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 ()) -> ConnectionOptions
-- | Whenever a pong is received, this IO action is executed. It
-- can be used to tickle connections or fire missiles.
[connectionOnPong] :: ConnectionOptions -> !(IO ())
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 message as text
sendTextData :: 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 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 ()
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
data AcceptRequest
AcceptRequest :: !(Maybe ByteString) -> 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)
acceptRequest :: PendingConnection -> IO Connection
acceptRequestWith :: PendingConnection -> AcceptRequest -> IO Connection
rejectRequest :: PendingConnection -> ByteString -> IO ()
data Connection
-- | Set options for a Connection.
data ConnectionOptions
ConnectionOptions :: !(IO ()) -> ConnectionOptions
-- | Whenever a pong is received, this IO action is executed. It
-- can be used to tickle connections or fire missiles.
[connectionOnPong] :: ConnectionOptions -> !(IO ())
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 message as text
sendTextData :: 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
DataMessage :: 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
Text :: ByteString -> DataMessage
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:
--
--
-- - Natively, everything is represented as a ByteString, so
-- this is the fastest instance
-- - You should only use the Text or the Text instance
-- when you are sure that the data is UTF-8 encoded (which is the case
-- for Text messages).
-- - Messages can be very large. If this is the case, it might be
-- inefficient to use the strict ByteString and Text
-- instances.
--
class WebSocketsData 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
-- | 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 ()