-- 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:
--   <a>https://github.com/jaspervdj/websockets/blob/master/example/server.lhs</a>
--   
--   An example client:
--   <a>https://github.com/jaspervdj/websockets/blob/master/example/client.hs</a>
--   
--   See also:
--   
--   <ul>
--   <li>The specification of the WebSocket protocol:
--   <a>http://www.whatwg.org/specs/web-socket-protocol/</a></li>
--   <li>The JavaScript API for dealing with WebSockets:
--   <a>http://www.w3.org/TR/websockets/</a></li>
--   </ul>
@package websockets
@version 0.10.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:
--   
--   <ul>
--   <li>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.</li>
--   <li>Reading from or writing or to a closed <a>Stream</a> will always
--   throw an exception, even if the underlying "receive" and "send"
--   functions do not (we do the bookkeeping).</li>
--   <li>Streams should always be closed.</li>
--   </ul>
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 <a>Connection</a>
[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 <a>Connection</a>.
acceptRequest :: PendingConnection -> IO Connection

-- | This datatype allows you to set options for <a>acceptRequestWith</a>.
--   It is strongly recommended to use <a>defaultAcceptRequest</a> 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
--   <tt>pendingSubprotcols</tt> is non-empty, <a>acceptSubprotocol</a>
--   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 <a>acceptRequest</a> but allows you to set
--   custom options using the <a>AcceptRequest</a> datatype.
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 <a>Connection</a>.
data ConnectionOptions
ConnectionOptions :: !(IO ()) -> ConnectionOptions

-- | Whenever a <tt>pong</tt> 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
--   <a>CloseRequest</a> 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 <a>CloseRequest</a>
--   exception will be thrown. The RFC specifies that the server is
--   responsible for closing the TCP connection, which should happen after
--   receiving the <a>CloseRequest</a> exception from this function.
--   
--   This will throw <a>ConnectionClosed</a> 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 <a>DataMessage</a>
sendDataMessage :: Connection -> DataMessage -> IO ()

-- | Send a collection of <a>DataMessage</a>s
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 <a>receiveDataMessage</a> to process
--   any in-flight messages. The peer will eventually respond with a close
--   control message of its own which will cause <a>receiveDataMessage</a>
--   to throw the <a>CloseRequest</a> 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
--   <a>sendClose</a>, you should continue calling
--   <a>receiveDataMessage</a> until you receive a <a>CloseRequest</a>
--   exception.
--   
--   See <a>http://tools.ietf.org/html/rfc6455#section-7.4</a> 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 <tt>n</tt> 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

-- | Accept a pending connection, turning it into a <a>Connection</a>.
acceptRequest :: PendingConnection -> IO Connection

-- | This datatype allows you to set options for <a>acceptRequestWith</a>.
--   It is strongly recommended to use <a>defaultAcceptRequest</a> 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
--   <tt>pendingSubprotcols</tt> is non-empty, <a>acceptSubprotocol</a>
--   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 <a>acceptRequest</a> but allows you to set
--   custom options using the <a>AcceptRequest</a> datatype.
acceptRequestWith :: PendingConnection -> AcceptRequest -> IO Connection
rejectRequest :: PendingConnection -> ByteString -> IO ()
data Connection

-- | Set options for a <a>Connection</a>.
data ConnectionOptions
ConnectionOptions :: !(IO ()) -> ConnectionOptions

-- | Whenever a <tt>pong</tt> 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
--   <a>CloseRequest</a> 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 <a>CloseRequest</a>
--   exception will be thrown. The RFC specifies that the server is
--   responsible for closing the TCP connection, which should happen after
--   receiving the <a>CloseRequest</a> exception from this function.
--   
--   This will throw <a>ConnectionClosed</a> 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 <a>DataMessage</a>
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 <a>receiveDataMessage</a> to process
--   any in-flight messages. The peer will eventually respond with a close
--   control message of its own which will cause <a>receiveDataMessage</a>
--   to throw the <a>CloseRequest</a> 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 <tt>Frame</tt>s 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:
--   
--   <ul>
--   <li>Natively, everything is represented as a <a>ByteString</a>, so
--   this is the fastest instance</li>
--   <li>You should only use the <a>Text</a> or the <a>Text</a> instance
--   when you are sure that the data is UTF-8 encoded (which is the case
--   for <a>Text</a> messages).</li>
--   <li>Messages can be very large. If this is the case, it might be
--   inefficient to use the strict <a>ByteString</a> and <a>Text</a>
--   instances.</li>
--   </ul>
class WebSocketsData a
fromLazyByteString :: WebSocketsData a => ByteString -> a
toLazyByteString :: WebSocketsData a => a -> ByteString

-- | Error in case of failed handshake. Will be thrown as an
--   <a>Exception</a>.
--   
--   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 <a>http://tools.ietf.org/html/rfc6455#section-7.4</a> 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
--   <a>IO</a> 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:
--   
--   <ul>
--   <li><a>https://hackage.haskell.org/package/wai-websockets</a></li>
--   <li><a>https://hackage.haskell.org/package/websockets-snap</a></li>
--   </ul>
runServer :: String -> Int -> ServerApp -> IO ()

-- | A version of <a>runServer</a> 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 <a>withSocketsDo</a>.
makeListenSocket :: String -> Int -> IO Socket

-- | Turns a socket, connected to some client, into a
--   <a>PendingConnection</a>. The <a>PendingConnection</a> should be
--   closed using <a>close</a> later.
makePendingConnection :: Socket -> ConnectionOptions -> IO PendingConnection

-- | More general version of <a>makePendingConnection</a> for <a>Stream</a>
--   instead of a <a>Socket</a>.
makePendingConnectionFromStream :: Stream -> ConnectionOptions -> IO PendingConnection

-- | A client application interacting with a single server. Once this
--   <a>IO</a> 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 <tt>n</tt> seconds
--   over the connection. The thread dies silently if the connection
--   crashes or is closed.
forkPingThread :: Connection -> Int -> IO ()
