Portability | portable |
---|---|
Stability | unstable |
Maintainer | info@jonkri.com |
Safe Haskell | None |
The Extensible Messaging and Presence Protocol (XMPP) is an open technology for near-real-time communication, which powers a wide range of applications including instant messaging, presence, multi-party chat, voice and video calls, collaboration, lightweight middleware, content syndication, and generalized routing of XML data. XMPP provides a technology for the asynchronous, end-to-end exchange of structured data by means of direct, persistent XML streams among a distributed network of globally addressable, presence-aware clients and servers.
Pontarius is an XMPP client library, implementing the core capabilities of XMPP (RFC 6120): setup and teardown of XML streams, channel encryption, authentication, error handling, and communication primitives for messaging.
Note that we are not recommending anyone to use Pontarius XMPP at this time as it's still in an experimental stage and will have its API and data types modified frequently.
- data Session
- newSession :: IO Session
- withConnection :: XmppConMonad a -> Session -> IO (Either StreamError a)
- connect :: HostName -> Text -> XmppConMonad (Either StreamError ())
- simpleConnect :: HostName -> Text -> Text -> Maybe Text -> XmppConMonad Jid
- startTLS :: TLSParams -> XmppConMonad (Either XmppTLSError ())
- simpleAuth :: Text -> Text -> Maybe Text -> XmppConMonad (Either AuthError Jid)
- auth :: [SaslHandler] -> Maybe Text -> XmppConMonad (Either AuthError Jid)
- closeConnection :: Session -> IO ()
- endSession :: Session -> IO ()
- setConnectionClosedHandler :: (StreamError -> Session -> IO ()) -> Session -> IO ()
- data Jid = Jid {
- localpart :: !(Maybe Text)
- domainpart :: !Text
- resourcepart :: !(Maybe Text)
- isBare :: Jid -> Bool
- isFull :: Jid -> Bool
- getStanzaChan :: Session -> IO (TChan Stanza)
- data Message = Message {
- messageID :: !(Maybe StanzaId)
- messageFrom :: !(Maybe Jid)
- messageTo :: !(Maybe Jid)
- messageLangTag :: !(Maybe LangTag)
- messageType :: !MessageType
- messagePayload :: ![Element]
- data MessageError = MessageError {
- messageErrorID :: !(Maybe StanzaId)
- messageErrorFrom :: !(Maybe Jid)
- messageErrorTo :: !(Maybe Jid)
- messageErrorLangTag :: !(Maybe LangTag)
- messageErrorStanzaError :: !StanzaError
- messageErrorPayload :: ![Element]
- data MessageType
- answerMessage :: Message -> [Element] -> Maybe Message
- sendMessage :: Message -> Session -> IO ()
- pullMessage :: Session -> IO (Either MessageError Message)
- waitForMessage :: (Message -> Bool) -> Session -> IO Message
- waitForMessageError :: (MessageError -> Bool) -> Session -> IO MessageError
- filterMessages :: (MessageError -> Bool) -> (Message -> Bool) -> Session -> IO (Either MessageError Message)
- data Presence = Presence {
- presenceID :: !(Maybe StanzaId)
- presenceFrom :: !(Maybe Jid)
- presenceTo :: !(Maybe Jid)
- presenceLangTag :: !(Maybe LangTag)
- presenceType :: !(Maybe PresenceType)
- presencePayload :: ![Element]
- data PresenceError = PresenceError {
- presenceErrorID :: !(Maybe StanzaId)
- presenceErrorFrom :: !(Maybe Jid)
- presenceErrorTo :: !(Maybe Jid)
- presenceErrorLangTag :: !(Maybe LangTag)
- presenceErrorStanzaError :: !StanzaError
- presenceErrorPayload :: ![Element]
- presTo :: Presence -> Jid -> Presence
- sendPresence :: Presence -> Session -> IO ()
- pullPresence :: Session -> IO (Either PresenceError Presence)
- waitForPresence :: (Presence -> Bool) -> Session -> IO Presence
- data IQRequest = IQRequest {
- iqRequestID :: !StanzaId
- iqRequestFrom :: !(Maybe Jid)
- iqRequestTo :: !(Maybe Jid)
- iqRequestLangTag :: !(Maybe LangTag)
- iqRequestType :: !IQRequestType
- iqRequestPayload :: !Element
- data IQRequestTicket
- iqRequestBody :: IQRequestTicket -> IQRequest
- data IQRequestType
- data IQResult = IQResult {
- iqResultID :: !StanzaId
- iqResultFrom :: !(Maybe Jid)
- iqResultTo :: !(Maybe Jid)
- iqResultLangTag :: !(Maybe LangTag)
- iqResultPayload :: !(Maybe Element)
- data IQError = IQError {
- iqErrorID :: !StanzaId
- iqErrorFrom :: !(Maybe Jid)
- iqErrorTo :: !(Maybe Jid)
- iqErrorLangTag :: !(Maybe LangTag)
- iqErrorStanzaError :: !StanzaError
- iqErrorPayload :: !(Maybe Element)
- data IQResponse
- sendIQ :: Maybe Int -> Maybe Jid -> IQRequestType -> Maybe LangTag -> Element -> Session -> IO (TMVar IQResponse)
- sendIQ' :: Maybe Jid -> IQRequestType -> Maybe LangTag -> Element -> Session -> IO IQResponse
- answerIQ :: IQRequestTicket -> Either StanzaError (Maybe Element) -> Session -> IO Bool
- listenIQChan :: IQRequestType -> Text -> Session -> IO (Either (TChan IQRequestTicket) (TChan IQRequestTicket))
- forkSession :: Session -> IO Session
- data LangTag = LangTag {
- primaryTag :: !Text
- subtags :: ![Text]
- exampleParams :: TLSParams
Session management
newSession :: IO SessionSource
Initializes a new XMPP session.
withConnection :: XmppConMonad a -> Session -> IO (Either StreamError a)Source
Run an XmppConMonad action in isolation. Reader and writer workers will be temporarily stopped and resumed with the new session details once the action returns. The action will run in the calling thread. Any uncaught exceptions will be interpreted as connection failure.
connect :: HostName -> Text -> XmppConMonad (Either StreamError ())Source
Connect to host with given address.
:: HostName | Target host name |
-> Text | User name (authcid) |
-> Text | Password |
-> Maybe Text | Desired resource (or Nothing to let the server decide) |
-> XmppConMonad Jid |
The quick and easy way to set up a connection to an XMPP server
This will * connect to the host * secure the connection with TLS * authenticate to the server using either SCRAM-SHA1 (preferred) or Digest-MD5 * bind a resource * return the full JID you have been assigned
Note that the server might assign a different resource even when we send a preference.
startTLS :: TLSParams -> XmppConMonad (Either XmppTLSError ())Source
:: Text | The username |
-> Text | The password |
-> Maybe Text | The desired resource or |
-> XmppConMonad (Either AuthError Jid) |
Authenticate to the server with the given username and password and bind a resource.
Prefers SCRAM-SHA1 over DIGEST-MD5.
auth :: [SaslHandler] -> Maybe Text -> XmppConMonad (Either AuthError Jid)Source
Authenticate to the server using the first matching method and bind a resource.
closeConnection :: Session -> IO ()Source
Close the connection to the server. Closes the stream (by enforcing a write lock and sending a /stream:stream element), waits (blocks) for three seconds, and then closes the connection.
endSession :: Session -> IO ()Source
End the current Xmpp session.
setConnectionClosedHandler :: (StreamError -> Session -> IO ()) -> Session -> IO ()Source
Sets the handler to be executed when the server connection is closed.
JID
A JID is XMPP's native format for addressing entities in the network. It is somewhat similar to an e-mail address but contains three parts instead of two.
Jid | |
|
Stanzas
The basic protocol data unit in XMPP is the XML stanza. The stanza is
essentially a fragment of XML that is sent over a stream. Stanzas
come in
3 flavors:
-
, for traditional push-style message passing between peersMessage
-
, for communicating status updatesPresence
- IQ (info/query), for request-response semantics communication
All stanza types have the following attributes in common:
- The id attribute is used by the originating entity to track any
response or error stanza that it might receive in relation to the
generated stanza from another entity (such as an intermediate server or
the intended recipient). It is up to the originating entity whether the
value of the
id
attribute is unique only within its current stream or unique globally. - The from attribute specifies the JID of the sender.
- The to attribute specifies the JID of the intended recipient for the stanza.
- The type attribute specifies the purpose or context of the message, presence, or IQ stanza. The particular allowable values for the 'type' attribute vary depending on whether the stanza is a message, presence, or IQ stanza.
getStanzaChan :: Session -> IO (TChan Stanza)Source
Get a duplicate of the stanza channel
Messages
The message stanza is a push mechanism whereby one entity pushes information to another entity, similar to the communications that occur in a system such as email.
The message stanza. Used for push type communication.
Message | |
|
data MessageError Source
An error stanza generated in response to a Message
.
MessageError | |
|
data MessageType Source
The type of a Message being sent (http://xmpp.org/rfcs/rfc6121.html#message-syntax-type)
Chat | The message is sent in the context of a one-to-one chat session. Typically an interactive client will present a message of type chat in an interface that enables one-to-one chat between the two parties, including an appropriate conversation history. |
GroupChat | The message is sent in the context of a multi-user chat
environment (similar to that of |
Headline | The message provides an alert, a notification, or other transient information to which no reply is expected (e.g., news headlines, sports updates, near-real-time market data, or syndicated content). Because no reply to the message is expected, typically a receiving client will present a message of type headline in an interface that appropriately differentiates the message from standalone messages, chat messages, and groupchat messages (e.g., by not providing the recipient with the ability to reply). |
Normal | The message is a standalone message that is sent outside the context of a one-to-one conversation or groupchat, and to which it is expected that the recipient will reply. Typically a receiving client will present a message of type normal in an interface that enables the recipient to reply, but without a conversation history. This is the default value. |
Creating
Sending
sendMessage :: Message -> Session -> IO ()Source
Send a message stanza.
Receiving
pullMessage :: Session -> IO (Either MessageError Message)Source
Read an element from the inbound stanza channel, acquiring a copy of the channel as necessary.
waitForMessage :: (Message -> Bool) -> Session -> IO MessageSource
Pulls a (non-error) message and returns it if the given predicate returns
True
.
waitForMessageError :: (MessageError -> Bool) -> Session -> IO MessageErrorSource
Pulls an error message and returns it if the given predicate returns True
.
filterMessages :: (MessageError -> Bool) -> (Message -> Bool) -> Session -> IO (Either MessageError Message)Source
Pulls a message and returns it if the given predicate returns True
.
Presence
XMPP includes the ability for an entity to advertise its network availability, or presence, to other entities. In XMPP, this availability for communication is signaled end-to-end by means of a dedicated communication primitive: the presence stanza.
The presence stanza. Used for communicating status updates.
Presence | |
|
data PresenceError Source
An error stanza generated in response to a Presence
.
PresenceError | |
|
Creating
Sending
Sends a presence stanza. In general, the presence stanza should have no
to
attribute, in which case the server to which the client is connected
will broadcast that stanza to all subscribed entities. However, a
publishing client may also send a presence stanza with a to
attribute, in
which case the server will route or deliver that stanza to the intended
recipient.
sendPresence :: Presence -> Session -> IO ()Source
Send a presence stanza.
Receiving
pullPresence :: Session -> IO (Either PresenceError Presence)Source
Read an element from the inbound stanza channel, acquiring a copy of the channel as necessary.
waitForPresence :: (Presence -> Bool) -> Session -> IO PresenceSource
Pulls a (non-error) presence and returns it if the given predicate returns
True
.
IQ
Info/Query, or IQ, is a request-response mechanism, similar in some
ways to the Hypertext Transfer Protocol HTTP
. The semantics of IQ enable
an entity to make a request of, and receive a response from, another
entity. The data content and precise semantics of the request and response
is defined by the schema or other structural definition associated with the
XML namespace that qualifies the direct child element of the IQ element. IQ
interactions follow a common pattern of structured data exchange such as
get/result or set/result (although an error can be returned in reply to a
request if appropriate)
A request Info/Query (IQ) stanza is one with either get or set as type. It always contains an xml payload.
IQRequest | |
|
data IQRequestTicket Source
Contains whether or not a reply has been sent, and the IQ request body to reply to.
data IQRequestType Source
The type of IQ request that is made.
The (non-error) answer to an IQ request.
IQResult | |
|
The answer to an IQ request that generated an error.
IQError | |
|
data IQResponse Source
:: Maybe Int | Timeout |
-> Maybe Jid | Recipient (to) |
-> IQRequestType | IQ type ( |
-> Maybe LangTag | Language tag of the payload ( |
-> Element | The IQ body (there has to be exactly one) |
-> Session | |
-> IO (TMVar IQResponse) |
Sends an IQ, returns a TMVar
that will be filled with the first inbound
IQ with a matching ID that has type result
or error
.
sendIQ' :: Maybe Jid -> IQRequestType -> Maybe LangTag -> Element -> Session -> IO IQResponseSource
Like sendIQ
, but waits for the answer IQ. Times out after 3 seconds
:: IQRequestType | Type of IQs to receive ( |
-> Text | Namespace of the child element |
-> Session | |
-> IO (Either (TChan IQRequestTicket) (TChan IQRequestTicket)) |
Retrieves an IQ listener channel. If the namespace/IQRequestType
is not
already handled, a new TChan
is created and returned as a Right
value.
Otherwise, the already existing channel will be returned wrapped in a Left
value. Note that the Left
channel might need to be duplicated in order not
to interfere with existing consumers.
Threads
forkSession :: Session -> IO SessionSource
Create a forked session object