Copyright | (c) Justin Le 2015 |
---|---|
License | MIT |
Maintainer | justin@jle.im |
Stability | unstable |
Portability | ghcjs |
Safe Haskell | None |
Language | Haskell2010 |
Low-level API for the Connection
socket wrapper, for situations like
debugging when things exported by JavaScript.WebSockets is not enough.
Most everyday usage should be covered by the aforementioned module, so
don't import this unless you really really have to.
- data Connection = Connection {
- _connSocket :: Socket
- _connQueue :: ConnectionQueue
- _connWaiters :: ConnectionWaiters
- _connOrigin :: Text
- _connClosed :: IORef (Maybe ConnClosing)
- _connBlock :: MVar ()
- data SocketMsg
- data ConnClosing
- = ManualClose
- | JSClose (Maybe Bool) (Maybe Int) (Maybe Text)
- | OpenInterruptedClose
- | UnexpectedClose Text
- class WSSendable s where
- wrapSendable :: s -> SocketMsg
- class WSReceivable s where
- unwrapReceivable :: SocketMsg -> Either SocketMsg s
- data ConnectionException = ConnectionClosed {}
- openConnectionImmediate :: Text -> IO (MVar Connection)
- closeConnection :: Connection -> IO ()
- closeConnectionLeftovers :: Connection -> IO [SocketMsg]
- clearConnectionQueue :: Connection -> IO ()
- dumpConnectionQueue :: Connection -> IO [SocketMsg]
- connectionClosed :: Connection -> IO Bool
- connectionCloseReason :: Connection -> IO (Maybe ConnClosing)
- connectionStateCode :: Connection -> IO Int
- sendMessage :: Connection -> SocketMsg -> IO Bool
- receiveMessageMaybe :: Connection -> IO (Maybe SocketMsg)
- withConnBlock :: Connection -> IO a -> IO a
- withConnBlockMasked :: Connection -> IO a -> IO a
Types
Data types
data Connection
Encapsulates a (reference to a) Javascript Websocket connection. Can
be created/accessed with either openConnection
or (preferably)
withUrl
.
Care must be taken to close the connection once you are done if using
openConnection
, or unprocessed messages and callbacks will continue to
queue up.
Connection | |
|
data SocketMsg
Sum type over the data that can be sent or received through a JavaScript websocket.
What an incoming message is classified as depends on the Javascript Websockets API http://www.w3.org/TR/websockets/, which provides a "typed" input channel of either text or binary blob.
There are several convenience functions to help you never have to deal
with this explicitly; its main purpose is if you want to explicitly
branch on a receiveMessage
depending on what kind of message you
receive and do separate things. receiveText
and receiveData
will
both allow you to "filter" incoming messages by their type.
data ConnClosing
Data type containing information on Connection
closes.
ManualClose
: Closed by the HaskellWebSockets
interface, usingcloseConnection
or variants.JSClose
: Closed on the Javascript end, either by a connection error or server request, or what have you. Contains information from the Javascript Websockets API http://www.w3.org/TR/websockets/#event-definitions.The first field is whether or not it was a clean close; the second field is the closing reason code; the third field is a
Text
with the reason given by the Websockets API.OpenInterupptedClose
: There was an unexpected error encountered when attempting to open the connection.UnexpectedClose
: Otherwise uncategorized closed status, with aText
field offering a reason.
Typeclasses
class WSSendable s where
A typeclass offering a gratuitous abstraction over what can be sent
through a Connection
. Allows you to wrap things in a SocketMsg
automatically. The only instances that should really ever exist are
Text
and instances of Binary
.
wrapSendable :: s -> SocketMsg
Binary a => WSSendable a | |
WSSendable Text |
class WSReceivable s where
A typeclass offering a gratuitous abstraction over what can be
received through a Connection
. Allows you to unwrap things in
a SocketMsg
automatically. The only instances that should really ever
exist are Text
and instances of Binary
.
unwrapReceivable :: SocketMsg -> Either SocketMsg s
Binary a => WSReceivable a | |
WSReceivable Text |
Exceptions
data ConnectionException
An exception that may be thrown when using the various Connection
operations. Right now, only includes ConnectionClosed
, which is
thrown when using an "unsafe" receive
on a closed Connection
, or if
a Connection
closes while an unsafe receive
is waiting.
Manipulating and inspecting Connection
s
openConnectionImmediate :: Text -> IO (MVar Connection)
A version of openConnection
that doesn't wait for the connection to
be opened. Returns an MVar
where the connection can be expected to be
placed when it is opened.
closeConnection :: Connection -> IO ()
Manually closes the given Connection
. Will un-block all threads
currently waiting on the Connection
for messages (releasing their
callbacks) and disable sending and receiving in the future.
All leftover messages that were never processed on the Haskell end will
be deleted; use dumpConnectionQueue
to manually fetch them before
closing, or closeConnectionLeftovers
to recover them while closing.
closeConnectionLeftovers :: Connection -> IO [SocketMsg]
Manually closes the given Connection
. It un-blocks all threads
currently waiting on the connection and disables all sending and
receiving in the future.
The result is a list of all messages received by the connection but not
yet retrieved by receive
, etc. on the Haskell end.
To close and ignore leftovers, use closeConnection
.
clearConnectionQueue :: Connection -> IO ()
Clears the message queue (messages waiting to be receive
d) on the
given Connection
. Is essentially a no-op on closed connections.
dumpConnectionQueue :: Connection -> IO [SocketMsg]
Returns all incoming messages received by the socket and queued for
retrieval using receive
functions. Empties the queue.
connectionClosed :: Connection -> IO Bool
Check if the given Connection
is closed. Returns a Bool
. To
check *why* it was closed, see connectionCloseReason
.
connectionCloseReason :: Connection -> IO (Maybe ConnClosing)
Returns Nothing
if the given Connection
is still open, or Just
closing
containing a ConnClosing
with information on why the
connection was closed.
For just a Bool
saying whether or not the connection is closed, try
connectionClosed
.
connectionStateCode :: Connection -> IO Int
Returns the "readyState" of the connection's javascript websockets
API: 0 is connecting, 1 is open, 2 is closing, and 3 is closed.
Shouldn't really be used except for debugging purposes. Use
connectionCloseReason
whenever possible to get information in a nice
haskelley sum type.
Sending and receiving
sendMessage :: Connection -> SocketMsg -> IO Bool
Sends the given SocketMsg
through the given Connection
.
A SocketMsg
is a sum type of either 'SocketMsgText t', containing
(strict) Text
, or 'SocketMsgData d', containing a (lazy) ByteString
.
Returns True
if the connection is open, and False
if it is closed.
In the future will return more feedback about whether or not the send
was completed succesfully.
receiveMessageMaybe :: Connection -> IO (Maybe SocketMsg)
Block and wait until the Connection
receives any message, and
returns the message wrapped in a SocketMsg
. A SocketMsg
is a sum
type of either 'SocketMsgText t', containing (strict) Text
, or
'SocketMsgData d', containing a (lazy) ByteString
.
Will return 'Just msg' as soon as any message is received, or Nothing
if the Connection
closes first. Returns Nothing
immediately if the
Connection
is already closed.
Connection mutex
withConnBlock :: Connection -> IO a -> IO a
Execute process with the connection mutex lock in effect. Will wait until the lock is released before starting, if lock was already in place.
Will break almost every Connection
function if you run one while this
is in effect, because almost all of them require the lock to begin.
withConnBlockMasked :: Connection -> IO a -> IO a
Execute process with the connection mutex lock in effect, with asynchronos exceptions masked (See Control.Exception). Will wait until the lock is released before starting, if lock was already in place.
Will break almost every Connection
function if you run one while this
is in effect, because almost all of them require the lock to begin.