-- 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
--   
--   This package only supports insecure (ws://...) WebSockets. If
--   you need secure (wss://...) websockets, consider using Wuss:
--   https://hackage.haskell.org/package/wuss
--   
--   See also:
--   
--   
--   
- The specification of the WebSocket protocol:
--   http://www.whatwg.org/specs/web-socket-protocol/
--   
- The JavaScript API for dealing with WebSockets:
--   http://www.w3.org/TR/websockets/
--   
@package websockets
@version 0.13.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:
--   
--   
--   
- 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 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)
parseBin :: Stream -> Get 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
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

-- | Requires calling pendingStream and close.
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 -> !MVar () -> !IO (Maybe Message) -> ![Message] -> IO () -> !IORef Bool -> Connection
[connectionOptions] :: Connection -> !ConnectionOptions
[connectionType] :: Connection -> !ConnectionType
[connectionProtocol] :: Connection -> !Protocol

-- | This MVar is filled whenever a pong is received. This is used by
--   withPingPong to timeout the connection if a pong is not
--   received.
[connectionHeartbeat] :: Connection -> !MVar ()
[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. Please do not use this
--   constructor directly, but rather use defaultConnectionOptions
--   and then set the fields you want, e.g.:
--   
--   
--   myOptions = defaultConnectionOptions {connectionStrictUnicode = True}
--   
--   
--   This way your code does not break if the library introduces new
--   fields.
data ConnectionOptions
ConnectionOptions :: !IO () -> !Int -> !CompressionOptions -> !Bool -> !SizeLimit -> !SizeLimit -> ConnectionOptions

-- | Whenever a pong is received, this IO action is executed. It
--   can be used to tickle connections or fire missiles.
[connectionOnPong] :: ConnectionOptions -> !IO ()

-- | Timeout for connection establishment in seconds. Only used in the
--   client.
[connectionTimeout] :: ConnectionOptions -> !Int

-- | 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

-- | The maximum size for incoming frame payload size in bytes. If a frame
--   exceeds this limit, a ParseException is thrown.
[connectionFramePayloadSizeLimit] :: ConnectionOptions -> !SizeLimit

-- | connectionFrameSizeLimit is often not enough since a
--   malicious client can send many small frames to create a huge message.
--   This limit allows you to protect from that. If a message exceeds this
--   limit, a ParseException is thrown.
--   
--   Note that, if compression is enabled, we check the size of the
--   compressed messages, as well as the size of the uncompressed messages
--   as we are deflating them to ensure we don't use too much memory in any
--   case.
[connectionMessageDataSizeLimit] :: ConnectionOptions -> !SizeLimit

-- | The default connection options:
--   
--   
--   
- Nothing happens when a pong is received.
--   
- Compression is disabled.
--   
- Lenient unicode decoding.
--   
- 30 second timeout for connection establishment.
--   
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. This allows you send both human-readable
--   text and binary data. This is a slightly more low-level interface than
--   sendTextData or sendBinaryData.
sendDataMessage :: Connection -> DataMessage -> IO ()

-- | Send a collection of DataMessages. This is more efficient than
--   calling sendDataMessage many times.
sendDataMessages :: Connection -> [DataMessage] -> IO ()

-- | Send a textual message. The message will be encoded as UTF-8. This
--   should be the default choice for human-readable text-based protocols
--   such as JSON.
sendTextData :: WebSocketsData a => Connection -> a -> IO ()

-- | Send a number of textual messages. This is more efficient than calling
--   sendTextData many times.
sendTextDatas :: WebSocketsData a => Connection -> [a] -> IO ()

-- | Send a binary message. This is useful for sending binary blobs, e.g.
--   images, data encoded with MessagePack, images...
sendBinaryData :: WebSocketsData a => Connection -> a -> IO ()

-- | Send a number of binary messages. This is more efficient than calling
--   sendBinaryData many times.
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 ()

-- | Send a pong
sendPong :: WebSocketsData a => Connection -> a -> IO ()

-- | Forks a ping thread, sending a ping message every n seconds
--   over the connection. The thread is killed when the inner IO action is
--   finished.
--   
--   This is useful to keep idle connections open through proxies and
--   whatnot. Many (but not all) proxies have a 60 second default timeout,
--   so based on that sending a ping every 30 seconds is a good idea.
--   
--   Note that usually you want to use withPingPong to timeout the
--   connection if a pong is not received.
withPingThread :: Connection -> Int -> IO () -> IO a -> IO a

-- | DEPRECATED: Use withPingThread instead.
--   
--   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.
--   
--   This is useful to keep idle connections open through proxies and
--   whatnot. Many (but not all) proxies have a 60 second default timeout,
--   so based on that sending a ping every 30 seconds is a good idea.

-- | Deprecated: Use withPingThread instead
forkPingThread :: Connection -> Int -> IO ()

-- | Use this if you want to run the ping thread yourself.
--   
--   See also withPingThread.
pingThread :: Connection -> Int -> IO () -> IO ()
data CompressionOptions
NoCompression :: CompressionOptions
PermessageDeflateCompression :: PermessageDeflate -> CompressionOptions

-- | Four extension parameters are defined for "permessage-deflate" to help
--   endpoints manage per-connection resource usage.
--   
--   
--   
- "server_no_context_takeover"
--   
- "client_no_context_takeover"
--   
- "server_max_window_bits"
--   
- "client_max_window_bits"
--   
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

-- | A size limit, in bytes. The Monoid instance takes the minimum
--   limit.
data SizeLimit
NoSizeLimit :: SizeLimit
SizeLimit :: !Int64 -> SizeLimit

module Network.WebSockets.Connection.PingPong

-- | Run an application with ping-pong enabled. Raises PongTimeout if a
--   pong is not received.
--   
--   Can used with Client and Server connections.
withPingPong :: PingPongOptions -> Connection -> (Connection -> IO ()) -> IO ()

-- | Options for ping-pong
--   
--   Make sure that the ping interval is less than the pong timeout, for
--   example N/2.
data PingPongOptions
PingPongOptions :: Int -> Int -> IO () -> PingPongOptions

-- | Interval in seconds
[pingInterval] :: PingPongOptions -> Int

-- | Timeout in seconds
[pongTimeout] :: PingPongOptions -> Int

-- | Action to perform after sending a ping
[pingAction] :: PingPongOptions -> IO ()

-- | Exception type used to kill connections if there is a pong timeout.
data PongTimeout
PongTimeout :: PongTimeout

-- | Default options for ping-pong
--   
--   Ping every 15 seconds, timeout after 30 seconds
defaultPingPongOptions :: PingPongOptions
instance GHC.Internal.Exception.Type.Exception Network.WebSockets.Connection.PingPong.PongTimeout
instance GHC.Internal.Show.Show Network.WebSockets.Connection.PingPong.PongTimeout

-- | This part of the library provides you with utilities to create
--   WebSockets clients (in addition to servers).
module Network.WebSockets.Client

-- | 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

-- | Build a new Connection from the client's point of view.
--   
--   WARNING: Be sure to call close on the given
--   Stream after you are done using the Connection in order
--   to properly close the communication channel.
--   runClientWithStream handles this for you, prefer to use it when
--   possible.
newClientConnection :: Stream -> String -> String -> ConnectionOptions -> Headers -> IO Connection
createRequest :: Protocol -> ByteString -> ByteString -> Bool -> Headers -> IO RequestHead
data Protocol
Hybi13 :: Protocol
defaultProtocol :: Protocol

-- | Check the response from the server. Throws
--   OtherHandshakeException on failure
checkServerResponse :: Stream -> RequestHead -> IO ()

-- | Build a Connection from a pre-established stream with already
--   finished handshake.
--   
--   NB: this will not perform any handshaking.
streamToClientConnection :: Stream -> ConnectionOptions -> IO Connection

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

-- | Requires calling pendingStream and close.
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. Please do not use this
--   constructor directly, but rather use defaultConnectionOptions
--   and then set the fields you want, e.g.:
--   
--   
--   myOptions = defaultConnectionOptions {connectionStrictUnicode = True}
--   
--   
--   This way your code does not break if the library introduces new
--   fields.
data ConnectionOptions
ConnectionOptions :: !IO () -> !Int -> !CompressionOptions -> !Bool -> !SizeLimit -> !SizeLimit -> ConnectionOptions

-- | Whenever a pong is received, this IO action is executed. It
--   can be used to tickle connections or fire missiles.
[connectionOnPong] :: ConnectionOptions -> !IO ()

-- | Timeout for connection establishment in seconds. Only used in the
--   client.
[connectionTimeout] :: ConnectionOptions -> !Int

-- | 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

-- | The maximum size for incoming frame payload size in bytes. If a frame
--   exceeds this limit, a ParseException is thrown.
[connectionFramePayloadSizeLimit] :: ConnectionOptions -> !SizeLimit

-- | connectionFrameSizeLimit is often not enough since a
--   malicious client can send many small frames to create a huge message.
--   This limit allows you to protect from that. If a message exceeds this
--   limit, a ParseException is thrown.
--   
--   Note that, if compression is enabled, we check the size of the
--   compressed messages, as well as the size of the uncompressed messages
--   as we are deflating them to ensure we don't use too much memory in any
--   case.
[connectionMessageDataSizeLimit] :: ConnectionOptions -> !SizeLimit

-- | The default connection options:
--   
--   
--   
- Nothing happens when a pong is received.
--   
- Compression is disabled.
--   
- Lenient unicode decoding.
--   
- 30 second timeout for connection establishment.
--   
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.
--   
--   
--   
- "server_no_context_takeover"
--   
- "client_no_context_takeover"
--   
- "server_max_window_bits"
--   
- "client_max_window_bits"
--   
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

-- | A size limit, in bytes. The Monoid instance takes the minimum
--   limit.
data SizeLimit
NoSizeLimit :: SizeLimit
SizeLimit :: !Int64 -> SizeLimit
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. This allows you send both human-readable
--   text and binary data. This is a slightly more low-level interface than
--   sendTextData or sendBinaryData.
sendDataMessage :: Connection -> DataMessage -> IO ()

-- | Send a collection of DataMessages. This is more efficient than
--   calling sendDataMessage many times.
sendDataMessages :: Connection -> [DataMessage] -> IO ()

-- | Send a textual message. The message will be encoded as UTF-8. This
--   should be the default choice for human-readable text-based protocols
--   such as JSON.
sendTextData :: WebSocketsData a => Connection -> a -> IO ()

-- | Send a number of textual messages. This is more efficient than calling
--   sendTextData many times.
sendTextDatas :: WebSocketsData a => Connection -> [a] -> IO ()

-- | Send a binary message. This is useful for sending binary blobs, e.g.
--   images, data encoded with MessagePack, images...
sendBinaryData :: WebSocketsData a => Connection -> a -> IO ()

-- | Send a number of binary messages. This is more efficient than calling
--   sendBinaryData many times.
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 ()

-- | 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.
--   
--   There are currently two kinds of data messages supported by the
--   WebSockets protocol:
--   
--   
--   
- Textual UTF-8 encoded data. This corresponds roughly to sending a
--   String in JavaScript.
--   
- Binary data. This corresponds roughly to send an ArrayBuffer in
--   JavaScript.
--   
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:
--   
--   
--   
- 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
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 :: RequestHead -> ResponseHead -> HandshakeException

-- | The connection timed out
ConnectionTimeout :: 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 or internal applications, but
--   for real applications, you should use a real server.
--   
--   For example:
--   
--   
--   
- Performance is reasonable under load, but:
--   
- No protection against DoS attacks is provided.
--   
- No logging is performed.
--   
- ...
--   
--   
--   Glue for using this package with real servers is provided by:
--   
--   
--   
- https://hackage.haskell.org/package/wai-websockets
--   
- https://hackage.haskell.org/package/websockets-snap
--   
runServer :: String -> Int -> ServerApp -> IO ()

-- | A version of runServer which allows you to customize some
--   options.

-- | Deprecated: Use runServerWithOptions instead
runServerWith :: String -> Int -> ConnectionOptions -> ServerApp -> IO ()
data ServerOptions
ServerOptions :: String -> Int -> ConnectionOptions -> ServerOptions
[serverHost] :: ServerOptions -> String
[serverPort] :: ServerOptions -> Int
[serverConnectionOptions] :: ServerOptions -> ConnectionOptions
defaultServerOptions :: ServerOptions

-- | Customizable version of runServer. Never returns until killed.
--   
--   Please use the defaultServerOptions combined with record
--   updates to set the fields you want. This way your code is unlikely to
--   break on future changes.
runServerWithOptions :: ServerOptions -> ServerApp -> IO a

-- | 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 pendingStream and 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

-- | Build a new Connection from the client's point of view.
--   
--   WARNING: Be sure to call close on the given
--   Stream after you are done using the Connection in order
--   to properly close the communication channel.
--   runClientWithStream handles this for you, prefer to use it when
--   possible.
newClientConnection :: Stream -> String -> String -> ConnectionOptions -> Headers -> IO Connection

-- | Options for ping-pong
--   
--   Make sure that the ping interval is less than the pong timeout, for
--   example N/2.
data PingPongOptions
PingPongOptions :: Int -> Int -> IO () -> PingPongOptions

-- | Interval in seconds
[pingInterval] :: PingPongOptions -> Int

-- | Timeout in seconds
[pongTimeout] :: PingPongOptions -> Int

-- | Action to perform after sending a ping
[pingAction] :: PingPongOptions -> IO ()

-- | Default options for ping-pong
--   
--   Ping every 15 seconds, timeout after 30 seconds
defaultPingPongOptions :: PingPongOptions

-- | Run an application with ping-pong enabled. Raises PongTimeout if a
--   pong is not received.
--   
--   Can used with Client and Server connections.
withPingPong :: PingPongOptions -> Connection -> (Connection -> IO ()) -> IO ()

-- | Forks a ping thread, sending a ping message every n seconds
--   over the connection. The thread is killed when the inner IO action is
--   finished.
--   
--   This is useful to keep idle connections open through proxies and
--   whatnot. Many (but not all) proxies have a 60 second default timeout,
--   so based on that sending a ping every 30 seconds is a good idea.
--   
--   Note that usually you want to use withPingPong to timeout the
--   connection if a pong is not received.
withPingThread :: Connection -> Int -> IO () -> IO a -> IO a

-- | DEPRECATED: Use withPingThread instead.
--   
--   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.
--   
--   This is useful to keep idle connections open through proxies and
--   whatnot. Many (but not all) proxies have a 60 second default timeout,
--   so based on that sending a ping every 30 seconds is a good idea.

-- | Deprecated: Use withPingThread instead
forkPingThread :: Connection -> Int -> IO ()
