yate/libs/yjabber/yatejingle.h

2172 lines
66 KiB
C++

/**
* yatejingle.h
* Yet Another Jingle Stack
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2023 Null Team
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __YATEJINGLE_H
#define __YATEJINGLE_H
#include <yateclass.h>
#include <yatejabber.h>
/**
* Holds all Telephony Engine related classes.
*/
namespace TelEngine {
class JGRtpMedia; // A Jingle RTP data payload
class JGCrypto; // Content crypto data
class JGRtpMediaList; // A list of Jingle RTP data payloads
class JGRtpCandidate; // A RTP transport candidate
class JGRtpCandidates; // A list of RTP transport candidates
class JGSessionContent; // A Jingle session content
class JGStreamHost; // A Jingle file transfer stream host
class JGSession; // A basic Jingle session
class JGSession0; // A session implementing the old jingle protocol
class JGSession1; // The version 1 of a jingle session
class JGEvent; // An event generated by a Jingle session
class JGEngine; // The Jingle engine
class JGSentStanza; // Sent stanza timeout info
/**
* This class holds a Jingle data payload description
* @short A Jingle data payload
*/
class YJABBER_API JGRtpMedia : public GenObject
{
public:
/**
* Constructor. Fill this object from the given attributes
* @param id The 'id' attribute
* @param name The 'name' attribute
* @param clockrate The 'clockrate' attribute
* @param synonym Application synonym for this payload
* @param channels Optional 'channels' attribute (the number of channels)
* @param pTime Optional "ptime" attribute (packet time)
* @param maxPTime Optional "maxptime" attribute (maximum packet time)
* @param bitRate Optional "bitrate" attribute
*/
inline JGRtpMedia(const char* id, const char* name, const char* clockrate,
const char* synonym, const char* channels = 0,
const char* pTime = 0, const char* maxPTime = 0, const char* bitRate = 0)
: m_params("")
{ set(id,name,clockrate,synonym,channels,pTime,maxPTime,bitRate); }
/**
* Constructor. Fill this object from an XML element
* @param xml The element to fill from
*/
inline JGRtpMedia(XmlElement* xml)
: m_params("")
{ fromXml(xml); }
/**
* Copy constructor
*/
inline JGRtpMedia(const JGRtpMedia& src)
: m_params("") {
set(src.m_id,src.m_name,src.m_clockrate,src.m_synonym,src.m_channels,
src.m_pTime,src.m_maxPTime,src.m_bitRate);
m_params = src.m_params;
}
/**
* Set the data
* @param id The 'id' attribute
* @param name The 'name' attribute
* @param clockrate The 'clockrate' attribute
* @param synonym Application synonym for this payload
* @param channels Optional 'channels' attribute (the number of channels)
* @param pTime Optional "ptime" attribute (packet time)
* @param maxPTime Optional "maxptime" attribute (maximum packet time)
* @param bitRate Optional "bitrate" attribute
*/
inline void set(const char* id, const char* name, const char* clockrate,
const char* synonym = 0, const char* channels = 0,
const char* pTime = 0, const char* maxPTime = 0, const char* bitRate = 0) {
m_id = id;
m_name = name;
m_clockrate = clockrate;
m_synonym = synonym;
m_channels = channels;
m_pTime = pTime;
m_maxPTime = maxPTime;
m_bitRate = bitRate;
m_params.clearParams();
}
/**
* Get the string repreasentation (id) of this payload
* @return The string repreasentation (id) of this payload
*/
virtual const String& toString() const
{ return m_id; }
/**
* Create a 'payload-type' element from this object
* @return Valid XmlElement pointer
*/
XmlElement* toXml() const;
/**
* Fill this object from a given element
* @param xml The element
*/
void fromXml(XmlElement* xml);
/**
* The numeric id of this payload
*/
String m_id;
/**
* The Jingle name of this payload
*/
String m_name;
/**
* The clockrate of this payload
*/
String m_clockrate;
/**
* A synonym of this payload's name
*/
String m_synonym;
/**
* The number of channels
*/
String m_channels;
/**
* Packet time
*/
String m_pTime;
/**
* Maximum packet time
*/
String m_maxPTime;
/**
* Data bit rate
*/
String m_bitRate;
/**
* List of optional parameters
*/
NamedList m_params;
};
/**
* This class holds a content description's crypto data.
* The tag is kept in the String component
* @short Content crypto data
*/
class YJABBER_API JGCrypto : public String
{
public:
/**
* Constructor
* @param tag The tag parameter
* @param suite The crypto-suite paramter
* @param key The key-params parameter
* @param session The session-param parameter
*/
inline JGCrypto(const char* tag = "1", const char* suite = 0,
const char* key = 0, const char* session = 0)
: String(tag),
m_suite(suite), m_keyParams(key), m_sessionParams(session)
{}
/**
* Constructor. Build this element from a received element
* @param xml The received xml element
*/
inline JGCrypto(const XmlElement* xml)
{ fromXml(xml); }
/**
* Create a 'crypto' element from this object
* @return Valid XmlElement pointer
*/
XmlElement* toXml() const;
/**
* Build this element from a received element
* @param xml The received xml element
*/
void fromXml(const XmlElement* xml);
/**
* Build an 'encryption' element from a list of crypto objects
* @param list The list of crypto objects
* @param required True if encryption is required
* @return XmlElement pointer or 0 if the list is empty
*/
static XmlElement* buildEncryption(const ObjList& list, bool required);
/**
* Decode an 'encryption' element. Clear the list before starting
* @param xml The element to decode
* @param list The list to be filled with crypto objects
* @param required Variable to be filled with the value of the 'required' attribute
*/
static void decodeEncryption(const XmlElement* xml, ObjList& list, bool& required);
String m_suite;
String m_keyParams;
String m_sessionParams;
};
/**
* Hold a list of RTP data payloads
* @short A List of Jingle RTP data payloads
*/
class YJABBER_API JGRtpMediaList : public ObjList
{
public:
/**
* Media type enumeration
*/
enum Media {
MediaMissing = -1,
MediaUnknown = 0,
Audio = 1,
};
/**
* Constructor
* @param m Media type as enumeration
* @param cryptoRequired True to require media encryption
*/
inline JGRtpMediaList(Media m = MediaMissing, bool cryptoRequired = false)
: m_media(m), m_bandwidth(0), m_cryptoRequired(cryptoRequired), m_ready(false),
m_telEvent(101), m_telEventName("telephone-event")
{}
/**
* Destructor
*/
inline ~JGRtpMediaList()
{ TelEngine::destruct(m_bandwidth); }
/**
* Get the media type of the payloads owned by this list
* @return Media type as enumeration
*/
inline Media media() const
{ return m_media; }
/**
* Append a new data payload
* @param id The 'id' attribute
* @param name The 'name' attribute
* @param clockrate The 'clockrate' attribute
* @param synonym Optional application synonym for the payload
* @param channels Optional 'channels' attribute (the number of channels)
* @param pTime Optional "ptime" attribute (packet time)
* @param maxPTime Optional "maxptime" attribute (maximum packet time)
* @param bitRate Optional "bitrate" attribute
*/
inline void add(const char* id, const char* name, const char* clockrate,
const char* synonym = 0, const char* channels = 0,
const char* pTime = 0, const char* maxPTime = 0, const char* bitRate = 0)
{ append(new JGRtpMedia(id,name,clockrate,synonym,channels,pTime,maxPTime,bitRate)); }
/**
* Reset the list and data
*/
void reset();
/**
* Set media type and payloads from another list
* @param src Media list to copy into this one
* @param only Optional list of synonyms to set if found in src.
* Copy the whole list if this parameter is empty
*/
void setMedia(const JGRtpMediaList& src, const String& only = String::empty());
/**
* Filter media list preserving only some formats
* @param only List of synonyms to preserve, do not filter media if this parameter is empty
*/
void filterMedia(const String& only);
/**
* Find a data payload by its id
* @param id Identifier of media to find
* @return JGRtpMedia pointer or 0 if not found
*/
JGRtpMedia* findMedia(const String& id);
/**
* Find a data payload by its synonym
* @param value The value to compare with
* @return JGRtpMedia pointer or 0 if not found
*/
JGRtpMedia* findSynonym(const String& value) const;
/**
* Create a 'description' element and add payload children to it
* @return Valid XmlElement pointer
*/
XmlElement* toXml() const;
/**
* Fill this list from an XML element's children. Clear before attempting to fill
* @param xml The source XML element
*/
void fromXml(XmlElement* xml);
/**
* Create a list from data payloads
* @param dest Destination string
* @param synonym True to create from synonyms, false to create from names
* @param sep List item separator
* @return False if the list is empty
*/
bool createList(String& dest, bool synonym, const char* sep = ",");
/**
* Build and add telephone-event media child to a parent xml element.
* Add a second telephone event media child if set
* @param xml Parent element
* @param name Optional event name. Defaults to set event name
*/
void addTelEvent(XmlElement* xml, const char* name = 0) const;
/**
* The list of media type names
*/
static const TokenDict s_media[];
/**
* The media type
*/
Media m_media;
/**
* Synchronization source
*/
String m_ssrc;
/**
* Optional SDP media bandwith. The name of the string keeps the type ('bwtype')
* and its value keeps the actual bandwith
*/
NamedString* m_bandwidth;
/**
* Crypto (SRTP) params
*/
bool m_cryptoRequired;
ObjList m_cryptoLocal;
ObjList m_cryptoRemote;
/**
* Flag indicating wether media was negotiated
*/
bool m_ready;
/**
* Telephone event payload id
*/
int m_telEvent;
/**
* Telephone event payload name
*/
String m_telEventName;
/**
* Second telephone event payload name
*/
String m_telEventName2;
};
/**
* This class holds a RTP transport candidate
* @short A RTP transport candidate
*/
class YJABBER_API JGRtpCandidate : public String
{
public:
/**
* Constructor
*/
inline JGRtpCandidate(const char* id, const char* component = "1",
unsigned int generation = 0, unsigned int net = 0, int prio = 0)
: String(id),
m_port(0), m_component(component), m_generation(generation),
m_network(net), m_priority(prio), m_protocol("udp"), m_type("host")
{}
/**
* Constructor. Build a candidate from received data
* @param xml Received xml element
* @param container The transport container
*/
inline JGRtpCandidate(XmlElement* xml, const JGRtpCandidates& container)
{ fromXml(xml,container); }
/**
* Create a 'candidate' element from this object using local address/port
* @param container The transport container
* @return Valid XmlElement pointer if type is a known one
*/
virtual XmlElement* toXml(const JGRtpCandidates& container) const;
/**
* Fill this object from a candidate element using remote address/port
* @param xml Received xml element
* @param container The transport container
*/
void fromXml(XmlElement* xml, const JGRtpCandidates& container);
String m_address;
String m_port;
String m_component; // Candidate component
String m_generation; // Candidate generation
String m_network; // NIC card (diagnostic only)
String m_priority; // Candidate priority
String m_protocol; // The only allowable value is "udp"
String m_type; // A Candidate Type as defined in ICE-CORE
};
/**
* This class holds a RTP transport candidate
* @short A RTP transport candidate
*/
class YJABBER_API JGRtpCandidateP2P : public JGRtpCandidate
{
YCLASS(JGRtpCandidateP2P,JGRtpCandidate)
public:
/**
* Constructor
*/
inline JGRtpCandidateP2P()
: JGRtpCandidate("")
{}
/**
* Constructor. Build a candidate from received data
* @param xml Received xml element
* @param container The transport container
*/
inline JGRtpCandidateP2P(XmlElement* xml, const JGRtpCandidates& container)
: JGRtpCandidate("")
{ fromXml(xml,container); }
/**
* Create a 'candidate' element from this object using local address/port
* @param container The transport container
* @return Valid XmlElement pointer if type is a known one
*/
virtual XmlElement* toXml(const JGRtpCandidates& container) const;
/**
* Fill this object from a candidate element using remote address/port
* @param xml Received xml element
* @param container The transport container
*/
void fromXml(XmlElement* xml, const JGRtpCandidates& container);
String m_username;
String m_password;
};
/**
* This class holds a list of jingle RTP transport candidates
* @short A list of RTP transport candidates
*/
class YJABBER_API JGRtpCandidates : public ObjList
{
public:
/**
* Enumeration of transport types
*/
enum Type {
Unknown = -1,
RtpIceUdp = 1,
RtpRawUdp,
RtpP2P,
RtpGoogleRawUdp,
};
/**
* Constructor. Fill this object from an XML element
* @param t The transport type
*/
inline JGRtpCandidates(Type t = Unknown)
: m_type(t)
{}
/**
* Get the name of this list's type
* @return The name of this list's type
*/
inline const char* typeName() const
{ return typeName(m_type); }
/**
* Fill password and ufrag data
*/
inline void generateIceAuth() {
generateIceToken(m_password,true);
generateIceToken(m_ufrag,false);
}
/**
* Fill password and ufrag data using old transport restrictions (16 bytes length)
*/
inline void generateOldIceAuth() {
generateOldIceToken(m_password);
generateOldIceToken(m_ufrag);
}
/**
* Find a candidate by its component value
* @param component The value to search
* @return JGRtpCandidate pointer or 0
*/
JGRtpCandidate* findByComponent(unsigned int component);
/**
* Create a 'transport' element from this object. Add candidates
* @param addCandidates True to add the candidate children
* @param addAuth RtpIceUdp only: add auth data
* @return Valid XmlElement pointer
*/
XmlElement* toXml(bool addCandidates, bool addAuth) const;
/**
* Fill this object from a given element
* @param element The element
*/
void fromXml(XmlElement* element);
/**
* Generate a random password or username to be used with ICE-UDP transport
* @param dest Destination string
* @param pwd True to generate a password, false to generate an username (ufrag)
* @param max Maximum number of characters. The maxmimum value is 256.
* The minimum value is 22 for password and 4 for username
*/
static void generateIceToken(String& dest, bool pwd, unsigned int max = 0);
/**
* Generate a random password or username to be used with old ICE-UDP transport
* @param dest Destination string
*/
static void generateOldIceToken(String& dest);
/**
* Get the name associated with a list's type
* @param t The desired type
* @param defVal Default value to return
* @return The name associated with a list's type
*/
static inline const char* typeName(int t, const char* defVal = "unknown")
{ return TelEngine::lookup(t,s_type,defVal); }
/**
* The list of type names
*/
static const TokenDict s_type[];
Type m_type;
String m_password;
String m_ufrag;
};
/**
* This class holds a Jingle content negotiated during a session
* It can be built from a received xml element and
* it can build an xml element from itself
* @short A Jingle session content
*/
class YJABBER_API JGSessionContent : public RefObject
{
public:
/**
* Enumeration of content type
*/
enum Type {
Unknown = -1, // Unknown
UnknownFileTransfer = -2, // Unknown (unsupported) file transfer content
RtpIceUdp = 1, // Audio: RTP ICE-UDP transport
RtpRawUdp, // Audio: RTP RAW-UDP transport
RtpP2P, //
RtpGoogleRawUdp, //
FileBSBOffer, // File offer: byte stream (SOCKS) transport
FileBSBRequest, // File request: byte stream (SOCKS) transport
};
/**
* Enumeration values for the 'senders' attribute (required)
*/
enum Senders {
SendUnknown = 0,
SendBoth = 1,
SendInitiator = 2,
SendResponder = 3
};
/**
* Enumeration values for the 'creator' attribute (required)
*/
enum Creator {
CreatorUnknown = 0,
CreatorInitiator = 1,
CreatorResponder = 2
};
/**
* Constructor
* @param t Content type as enumeration
* @param name Content name
* @param senders Content senders as enumeration
* @param creator Content creator as enumeration
* @param disposition Optional content disposition (defauls to 'session' if empty)
*/
JGSessionContent(Type t, const char* name, Senders senders,
Creator creator, const char* disposition = 0);
/**
* Get the content type
* @return Content type as enumeration
*/
inline Type type() const
{ return m_type; }
/**
* Get the senders
* @return Senders as enumeration
*/
inline Senders senders() const
{ return m_senders; }
/**
* Get the content creator
* @return Content creator as enumeration
*/
inline Creator creator() const
{ return m_creator; }
/**
* Check if this content is a valid audio one: it's media list type is Audio
* and the payload list is not empty
* @return True if this content can be used for audio purposes
*/
inline bool isValidAudio() const
{ return (m_rtpMedia.media() == JGRtpMediaList::Audio) && (0 != m_rtpMedia.skipNull()); }
/**
* Get the name of this content
*/
virtual const String& toString() const
{ return m_name; }
/**
* Check if the content disposition is session
* XEP-0166: true if disposition is missing
* @return True if this content should be processed at session level
*/
inline bool isSession() const
{ return !m_disposition || m_disposition == "session"; }
/**
* Check if the content disposition is early media
* @return True if this content is an early media one
*/
inline bool isEarlyMedia() const
{ return m_disposition == "early-session"; }
/**
* Set this content's disposition to early media
*/
inline void setEarlyMedia()
{ m_disposition = "early-session"; }
/**
* Build a 'content' XML element from this object
* @param minimum Minimum data (only creator and name)
* @param addDesc True to add the description child
* @param addTrans True to add the transport child
* @param addCandidates True to add the transport candidate children
* @param addAuth RtpIceUdp only: add auth data
* @return Valid XmlElement pointer
*/
XmlElement* toXml(bool minimum, bool addDesc,
bool addTrans, bool addCandidates, bool addAuth) const;
/**
* Decode 'content' element attributes
* @param xml The XML element
* @param err The error on failure
* @param error Error text to be sent on failure
* @return Valid JGSessionContent pointer on success
*/
static JGSessionContent* fromXml(XmlElement* xml, XMPPError::Type& err,
String& error);
/**
* The list containing the text values for Senders enumeration
*/
static const TokenDict s_senders[];
/**
* The list containing the text values for Creator enumeration
*/
static const TokenDict s_creator[];
/**
* The RTP media description if used
*/
JGRtpMediaList m_rtpMedia;
/**
* The RTP local candidates
*/
JGRtpCandidates m_rtpLocalCandidates;
/**
* The RTP remote candidates
*/
JGRtpCandidates m_rtpRemoteCandidates;
/**
* File info (for file transfer)
*/
NamedList m_fileTransfer;
private:
Type m_type;
String m_name;
Senders m_senders;
Creator m_creator;
String m_disposition;
};
/**
* This class holds a file transfer stream host definition
* @short A Jingle file transfer stream host
*/
class JGStreamHost : public String
{
public:
/**
* Constructor
* @param local Local stream host
* @param jid Stream host jid (id)
* @param addr Stream host address
* @param port Stream host port
* @param zeroConf Optional zero conf definition (override address/port)
*/
JGStreamHost(bool local, const char* jid, const char* addr, int port, const char* zeroConf = 0)
: String(jid),
m_local(local), m_address(addr), m_port(port), m_zeroConf(zeroConf)
{}
/**
* Copy constructor
* @param src Source stream host to copy from
*/
inline JGStreamHost(const JGStreamHost& src)
: String(src),
m_local(src.m_local), m_address(src.m_address), m_port(src.m_port),
m_zeroConf(src.m_zeroConf)
{}
/**
* Build an XML element from this stream host
* @return Valid XmlElement pointer
*/
XmlElement* toXml();
/**
* Build a stream host from an XML element
* @param xml The element to build from
* @return Valid JGStreamHost pointer or 0 on error
*/
static JGStreamHost* fromXml(XmlElement* xml);
/**
* Build a query XML element carrying a list of stream hosts
* @param hosts List of JGStreamHost objects
* @param sid The query element's sid attribute
* @param mode The query element's mode attribute
* @return Valid XmlElement pointer
*/
static XmlElement* buildHosts(const ObjList& hosts, const char* sid,
const char* mode = "tcp");
/**
* Build a query XML element with a streamhost-used child
* @param jid The jid of the stream host used
* @return Valid XmlElement pointer
*/
static XmlElement* buildRsp(const char* jid);
bool m_local;
String m_address;
int m_port;
String m_zeroConf;
};
/**
* This class is a base class for all specific jingle sessions
* @short A basic Jingle session
*/
class YJABBER_API JGSession : public RefObject, public Mutex
{
friend class JGEvent;
friend class JGEngine;
public:
/**
* Jingle session version
*/
enum Version {
Version0 = 0,
Version1 = 1,
VersionUnknown
};
/**
* Jingle defined reasons and errors
*/
enum Reason {
ReasonUnknown = 0,
// Session termination reason
ReasonOk, // success
ReasonBusy, // busy
ReasonDecline, // decline
ReasonCancel, // cancel
ReasonExpired, // expired
ReasonConn, // connectivity-error
ReasonFailApp, // failed-application
ReasonFailTransport, // failed-transport
ReasonGone, // gone
ReasonParams, // incompatible-parameters
ReasonMedia, // media-error
ReasonTransport, // unsupported-transports
ReasonApp, // unsupported-applications
ReasonSecurity, // security-error
ReasonTimeout, // timeout
ReasonGeneral, // general-error
ReasonAltSess, // alternative-session
// Session transfer (XEP 0251)
Transferred, // transferred
// RTP session errors (XEP 0167)
CryptoRequired, // crypto-required
InvalidCrypto, // invalid-crypto
};
/**
* RTP session info (XEP 0167)
*/
enum RtpInfo {
RtpActive, // active
RtpHold, // hold
RtpMute, // mute
RtpRinging, // ringing
};
/**
* Session state enumeration
*/
enum State {
Idle = 0, // Outgoing stream is waiting for
Pending = 1, // Session is pending, session-initiate sent/received
Active = 2, // Session is active, session-accept sent/received
Ending = 3, // Session terminated: Wait for write result
Destroy = 4, // The session will be destroyed
};
/**
* Jingle action enumeration
*/
enum Action {
ActAccept, // session-accept
ActInitiate, // session-initiate
ActTerminate, // session-terminate
ActReject, // reject
ActInfo, // session-info
ActTransportInfo, // transport-info
ActTransportAccept, // transport-accept
ActTransportReject, // transport-reject
ActTransportReplace, // transport-replace
ActCandidates, // candidates
ActContentAccept, // content-accept
ActContentAdd, // content-add
ActContentModify, // content-modify
ActContentReject, // content-reject
ActContentRemove, // content-remove
ActContentInfo, // content-info
ActDescriptionInfo, // description-info
ActTransfer, // session-info: Transfer
ActRinging, // session-info: Ringing
ActTrying, // session-info: Trying
ActReceived, // session-info: Received
ActHold, // session-info: Hold
ActActive, // session-info: Active
ActMute, // session-info: Mute
ActDtmf, // session-info: Dtmf
ActStreamHost,
ActCount,
};
/**
* Session flags
*/
enum SessionFlag {
FlagNoPing = 0x0001, // Don't send ping
FlagRingNsRtp = 0x0002, // Send ringing using rtp namespace instead of rtp info namespace
FlagNoOkInitiate = 0x0004, // Don't raise a ResultOk when initiate stanza is confirmed
};
/**
* Destructor
*/
virtual ~JGSession();
/**
* Get the session version
* @return The session version
*/
inline Version version() const
{ return m_version; }
/**
* Retrieve the engine owning this session
* @return The engine owning this session
*/
inline JGEngine* engine() const
{ return m_engine; }
/**
* Get the session direction
* @return True if it is an outgoing session
*/
inline bool outgoing() const
{ return m_outgoing; }
/**
* Get the session id
* @return The session id
*/
inline const String& sid() const
{ return m_sid; }
/**
* Get the local peer's JID
* @return The local peer's JID
*/
inline const JabberID& local() const
{ return m_local; }
/**
* Get the remote peer's JID
* @return The remote peer's JID
*/
inline const JabberID& remote() const
{ return m_remote; }
/**
* Get the session state.
* @return The session state as enumeration.
*/
inline State state() const
{ return m_state; }
/**
* Retrieve session flags
* @param mask Mask to retrieve
* @return Session flags
*/
inline int flag(int mask) const
{ return m_flags & mask; }
/**
* Replace session flags
* @param value The new session flags
*/
inline void setFlags(int value)
{ m_flags = value; }
/**
* Get the arbitrary user data of this session
* @return The arbitrary user data of this session
*/
inline void* userData()
{ return m_private; }
/**
* Set the arbitrary user data of this session
* @param userdata The new arbitrary user data's value
*/
inline void userData(void* userdata)
{ m_private = userdata; }
/**
* Retrieve the client account used by this session
* @return The client account used by this session
*/
inline const String& line() const
{ return m_line; }
/**
* Set the client account used by this session
* @param acc The client account used by this session
*/
inline void line(const String& acc)
{ m_line = acc; }
/**
* Get an action (jingle element type) from a jingle element
* @param xml Element to check
* @return The found action, ActCount if not found or unknown
*/
Action getAction(XmlElement* xml);
/**
* Ask this session to accept an incoming xml 'iq' element
* @param type Iq type as enumeration
* @param from The sender
* @param to The recipient
* @param id The session id of this is a request (set/get) or the stanza id
* @param xml The received element
* @return True if accepted (the element was enqueued), false if not
*/
bool acceptIq(XMPPUtils::IqType type, const JabberID& from, const JabberID& to,
const String& id, XmlElement* xml);
/**
* Confirm (send result) a received element
* @param xml The element to confirm
* @return False if send failed or element is 0
*/
bool confirmResult(XmlElement* xml);
/**
* Confirm (send error) a received element
* @param xml The element to confirm (will be consumed and zeroed)
* @param error The error condition
* @param text Optional text to add to the error element
* @param type Error type
* @return False if send failed or element is 0
*/
bool confirmError(XmlElement*& xml, XMPPError::Type error,
const char* text = 0, XMPPError::ErrorType type = XMPPError::TypeModify);
/**
* Accept a Pending incoming session.
* This method is thread safe
* @param contents The list of accepted contents
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @return False if send failed
*/
virtual bool accept(const ObjList& contents, String* stanzaId = 0)
{ return false; }
/**
* Close a Pending or Active session
* This method is thread safe
* @param reason Optional termination reason
* @return False if send failed
*/
virtual bool hangup(XmlElement* reason = 0);
/**
* Create a RTP info child to be added to a session-info element
* @param info The informational tag as enumeration
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createRtpInfoXml(RtpInfo info)
{ return 0; }
/**
* Create a termination reason element
* @param reason The reason code
* @param text Optional reason text child
* @param child Optional additional reason child
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createReason(int reason, const char* text = 0,
XmlElement* child = 0)
{ return 0; }
/**
* Create a transfer reason element
* @param reason The reason code
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createTransferReason(int reason)
{ return 0; }
/**
* Create a RTP session reason element
* @param reason The reason code
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createRtpSessionReason(int reason)
{ return 0; }
/**
* Send a stanza with session content(s)
* This method is thread safe
* @param action Must be a transport- or content- action
* @param contents Non empty list with content(s) to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
virtual bool sendContent(Action action, const ObjList& contents, String* stanzaId = 0)
{ return false; }
/**
* Send a stanza with a session content
* This method is thread safe
* @param action Must be a transport- or content- action
* @param content The content to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
inline bool sendContent(Action action, const JGSessionContent* content,
String* stanzaId = 0) {
if (!content)
return false;
ObjList tmp;
tmp.append(content)->setDelete(false);
return sendContent(action,tmp,stanzaId);
}
/**
* Send a stanza with stream hosts
* This method is thread safe
* @param hosts The list of hosts to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
virtual bool sendStreamHosts(const ObjList& hosts, String* stanzaId = 0)
{ return false; }
/**
* Send a stanza with a stream host used. If the jid is empty, send an
* item-not-found error response
* This method is thread safe
* @param jid The stream host to send
* @param stanzaId The id of the stanza to confirm
* @return False if send failed
*/
virtual bool sendStreamHostUsed(const char* jid, const char* stanzaId)
{ return false; }
/**
* Build SOCKS SHA1 dst.addr used by file transfer
* @param buf Destination string
*/
void buildSocksDstAddr(String& buf);
/**
* Send a session info element to the remote peer.
* This method is thread safe
* @param xml The XmlElement carried by the session info element
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @param extra Optional extra child for jingle element
* @return False on failure
*/
bool sendInfo(XmlElement* xml, String* stanzaId = 0, XmlElement* extra = 0);
/**
* Send a dtmf string to remote peer. If the string's length is greater then 1, each
* character is added as a 'dtmf' child of the jingle element
* @param dtmf The dtmf string
* @param msDuration The tone duration in miliseconds. Ignored if 0
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @return False if send failed
*/
bool sendDtmf(const char* dtmf, unsigned int msDuration = 0, String* stanzaId = 0);
/**
* Check if the remote party supports a given feature
* @param feature The requested feature
* @return True if the remote party supports the given feature
*/
bool hasFeature(XMPPNamespace::Type feature);
/**
* Build a transfer element
* @param transferTo The JID to transfer to
* @param transferFrom The transferror's JID
* @param sid Optional session id used for attended transfer (empty for unattended transfer)
* @return Valid XmlElement pointer
*/
static XmlElement* buildTransfer(const String& transferTo, const String& transferFrom,
const String& sid = String::empty());
/**
* Get the session version associated with a text
* @param value The version text
* @param def Default value to return if not found
* @return Session Version value
*/
static inline Version lookupVersion(const char* value, Version def = VersionUnknown)
{ return (Version)lookup(value,s_versions,def); }
/**
* Get the session version name
* @param value The version value
* @param def Default value to return if not found
* @return Session version name or the default value if not found
*/
static inline const char* lookupVersion(int value, const char* def = "unknown")
{ return lookup(value,s_versions,def); }
/**
* Get the termination code associated with a text
* @param value The termination text
* @param def Default value to return if not found
* @return Termination code
*/
static inline int lookupReason(const char* value, int def = ReasonOk)
{ return lookup(value,s_reasons,def); }
/**
* Get the termination code associated with a text
* @param value The termination code
* @param def Default value to return if not found
* @return Termination text
*/
static inline const char* lookupReason(int value, const char* def = 0)
{ return lookup(value,s_reasons,def); }
/**
* Get the name of a session state
* @param state The state to find
* @return The name of a session state
*/
static const char* lookupState(int state)
{ return lookup(state,s_states); }
/**
* Get the name of an action
* @param act The action to find
* @param ver Session version to use
* @return The name of an action
*/
static const char* lookupAction(int act, Version ver);
/**
* Get the action associated with a given string
* @param str The action name
* @param ver Session version to use
* @return The name of an action
*/
static Action lookupAction(const char* str, Version ver);
/**
* Session version names
*/
static const TokenDict s_versions[];
/**
* Termination reasons and errors
*/
static const TokenDict s_reasons[];
/**
* RTP session info (XEP 0167)
*/
static const TokenDict s_rtpInfo[];
/**
* Session state names
*/
static const TokenDict s_states[];
/**
* Action names for version Version0
*/
static const TokenDict s_actions0[];
/**
* Action names for version Version1
*/
static const TokenDict s_actions1[];
/**
* Session flag names
*/
static const TokenDict s_flagName[];
protected:
/**
* Constructor. Create an outgoing session
* @param ver The session version
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
*/
JGSession(Version ver, JGEngine* engine,
const JabberID& caller, const JabberID& called);
/**
* Constructor. Create an incoming session.
* @param ver The session version
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
* @param xml A valid Jabber Jingle xml with action session initiate
* @param id Session id
*/
JGSession(Version ver, JGEngine* engine, const JabberID& caller,
const JabberID& called, XmlElement* xml, const String& id);
/**
* Build and send the initial message on an outgoing session
* @param contents The session contents to be sent with session initiate element
* @param extra Optional extra child to be added to the session initiate element
* @param subject Optional session subject
* @return True on success
*/
virtual bool initiate(const ObjList& contents, XmlElement* extra,
const char* subject = 0) = 0;
/**
* Get a Jingle event from the queue.
* This method is thread safe
* @param time Current time in miliseconds
* @return JGEvent pointer or 0
*/
virtual JGEvent* getEvent(u_int64_t time);
/**
* Release this session and its memory
*/
virtual void destroyed();
/**
* Send a stanza to the remote peer
* @param stanza The stanza to send
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @param confirmation True if the stanza needs confirmation (add 'id' attribute)
* @param ping True if the stanza is a ping one
* @param toutMs Optional stanza timeout interval in milliseconds
* @return True on success
*/
bool sendStanza(XmlElement* stanza, String* stanzaId = 0, bool confirmation = true,
bool ping = false, unsigned int toutMs = 0);
/**
* Send a ping (empty session info) stanza to the remote peer if it's time to do it
* @param msecNow The current time
* @return True if a ping was succesfully sent
*/
bool sendPing(u_int64_t msecNow);
/**
* Decode a jingle element
* @param xml The element to decode
* @param child The element's first child
* @return JGEvent pointer or 0
*/
virtual JGEvent* decodeJingle(XmlElement*& xml, XmlElement* child) = 0;
/**
* Create an 'iq' of type 'set' with a 'jingle' child
* @param action The action of the Jingle stanza
* @param element1 Optional child element
* @param element2 Optional child element
* @param element3 Optional child element
* @return Valid XmlElement pointer
*/
virtual XmlElement* createJingle(Action action, XmlElement* element1 = 0,
XmlElement* element2 = 0, XmlElement* element3 = 0) = 0;
/**
* Create a dtmf XML element
* @param dtmf The dtmf string
* @param msDuration The tone duration in miliseconds. Ignored if 0
* @return Valid XmlElement pointer or 0
*/
virtual XmlElement* createDtmf(const char* dtmf, unsigned int msDuration = 0) = 0;
/**
* Method called in getEvent() to process a last event decoded from a
* received jingle element
* @param ev The event to process (will be consumed and zeroed)
* @return JGEvent pointer or 0
*/
virtual JGEvent* processJingleSetEvent(JGEvent*& ev);
/**
* Method called in getEvent() to process a jabber event carrying a response
* @param result True if the element is a result, false if it's an error response
* @param xml Xml element to process
* @return JGEvent pointer or 0
*/
virtual JGEvent* processJabberIqResponse(bool result, XmlElement*& xml);
/**
* Decode a file transfer element
* @param set True if the xml is an iq 'set', false if type is 'get'
* @param xml The element to decode
* @param child The element's first child
* @return JGEvent pointer or 0
*/
virtual JGEvent* processFileTransfer(bool set, XmlElement*& xml, XmlElement* child);
/**
* Terminate notification from an event. Reset the last generated event
* @param event Terminated (processed) event
*/
void eventTerminated(JGEvent* event);
/**
* Changed session state
* @param newState Session new state
*/
void changeState(State newState);
Version m_version; // Session version
State m_state; // Session state
int m_flags; // Session flags
u_int64_t m_timeToPing; // Time to send ping (empty session-info)
JGEngine* m_engine; // The engine that owns this session
bool m_outgoing; // Session direction
String m_sid; // Session id
JabberID m_local; // Local peer's JID
JabberID m_remote; // Remote peer's JID
XmlFragment m_queue; // Incoming, unprocessed, xml elements
JGEvent* m_lastEvent; // Last generated event
bool m_recvTerminate; // Flag indicating whether session-terminate was received
void* m_private; // Arbitrary user data
String m_localSid; // Local session id (used to generate element's id)
u_int32_t m_stanzaId; // Sent stanza id counter
ObjList m_sentStanza; // Sent stanzas' id
String m_line; // Session account
private:
JGSession() {} // Don't use it
};
/**
* A session implementing the old jingle protocol
* @short The version 0 of a jingle session
*/
class YJABBER_API JGSession0 : public JGSession
{
friend class JGEvent;
friend class JGEngine;
public:
/**
* Destructor
*/
virtual ~JGSession0();
/**
* Accept a Pending incoming session.
* This method is thread safe
* @param contents The list of accepted contents
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @return False if send failed
*/
virtual bool accept(const ObjList& contents, String* stanzaId = 0);
protected:
/**
* Constructor. Create an outgoing session
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
*/
JGSession0(JGEngine* engine, const JabberID& caller, const JabberID& called);
/**
* Constructor. Create an incoming session.
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
* @param xml A valid Jabber Jingle xml with action session initiate
* @param id Session id
*/
JGSession0(JGEngine* engine, const JabberID& caller, const JabberID& called,
XmlElement* xml, const String& id);
/**
* Build and send the initial message on an outgoing session
* @param contents The session contents to be sent with session initiate element
* @param extra Optional extra child to be added to the session initiate element
* @param subject Optional session subject
* @return True on success
*/
virtual bool initiate(const ObjList& contents, XmlElement* extra,
const char* subject = 0);
/**
* Send a stanza with session content(s)
* This method is thread safe
* @param action Must be a transport- action
* @param contents Non empty list with content(s) to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
virtual bool sendContent(Action action, const ObjList& contents, String* stanzaId = 0);
/**
* Decode a jingle element
* @param xml The element to decode
* @param child The element's first child
* @return JGEvent pointer or 0
*/
virtual JGEvent* decodeJingle(XmlElement*& xml, XmlElement* child);
/**
* Create an 'iq' of type 'set' with a 'jingle' child
* @param action The action of the Jingle stanza
* @param element1 Optional child element
* @param element2 Optional child element
* @param element3 Optional child element
* @return Valid XmlElement pointer
*/
virtual XmlElement* createJingle(Action action, XmlElement* element1 = 0,
XmlElement* element2 = 0, XmlElement* element3 = 0);
/**
* Create a dtmf XML element
* @param dtmf The dtmf string
* @param msDuration The tone duration in miliseconds. Ignored if 0
* @return Valid XmlElement pointer or 0
*/
virtual XmlElement* createDtmf(const char* dtmf, unsigned int msDuration = 0);
protected:
String m_sessContentName; // Content name advertised to upper layer
Action m_candidatesAction; // Use candidates/transport-info for candidates
};
/**
* A session implementing the Jingle protocol including session transfer and file transfer
* @short The version 1 of a jingle session
*/
class YJABBER_API JGSession1 : public JGSession
{
friend class JGEvent;
friend class JGEngine;
public:
/**
* Destructor
*/
virtual ~JGSession1();
/**
* Accept a Pending incoming session.
* This method is thread safe
* @param contents The list of accepted contents
* @param stanzaId Optional string to be filled with sent stanza id (used to track the response)
* @return False if send failed
*/
virtual bool accept(const ObjList& contents, String* stanzaId = 0);
/**
* Create a RTP info child to be added to a session-info element
* @param info The informational tag as enumeration
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createRtpInfoXml(RtpInfo info);
/**
* Create a termination reason element
* @param reason The reason code
* @param text Optional reason text child
* @param child Optional additional reason child
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createReason(int reason, const char* text = 0,
XmlElement* child = 0);
/**
* Create a transfer reason element
* @param reason The reason code
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createTransferReason(int reason);
/**
* Create a RTP session reason element
* @param reason The reason code
* @return Valid XmlElement pointer or 0 if not supported
*/
virtual XmlElement* createRtpSessionReason(int reason);
/**
* Send a stanza with session content(s)
* This method is thread safe
* @param action Must be a transport- or content- action
* @param contents Non empty list with content(s) to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
virtual bool sendContent(Action action, const ObjList& contents, String* stanzaId = 0);
/**
* Send a stanza with stream hosts
* This method is thread safe
* @param hosts The list of hosts to send
* @param stanzaId Optional string to be filled with sent
* stanza id (used to track the response)
* @return False if send failed
*/
virtual bool sendStreamHosts(const ObjList& hosts, String* stanzaId = 0);
/**
* Send a stanza with a stream host used. If the jid is empty, send an
* item-not-found error response
* This method is thread safe
* @param jid The stream host to send
* @param stanzaId The id of the stanza to confirm
* @return False if send failed
*/
virtual bool sendStreamHostUsed(const char* jid, const char* stanzaId);
protected:
/**
* Constructor. Create an outgoing session
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
*/
JGSession1(JGEngine* engine, const JabberID& caller, const JabberID& called);
/**
* Constructor. Create an incoming session.
* @param engine The engine owning this session
* @param caller The caller's full JID
* @param called The called party's full JID
* @param xml A valid Jabber Jingle xml with action session initiate
* @param id Session id
*/
JGSession1(JGEngine* engine, const JabberID& caller, const JabberID& called,
XmlElement* xml, const String& id);
/**
* Build and send the initial message on an outgoing session
* @param contents The session contents to be sent with session initiate element
* @param extra Optional extra child to be added to the session initiate element
* @param subject Optional session subject
* @return True on success
*/
virtual bool initiate(const ObjList& contents, XmlElement* extra,
const char* subject = 0);
/**
* Decode a jingle element
* @param xml The element to decode
* @param child The element's first child
* @return JGEvent pointer or 0
*/
virtual JGEvent* decodeJingle(XmlElement*& xml, XmlElement* child);
/**
* Create an 'iq' of type 'set' with a 'jingle' child
* @param action The action of the Jingle stanza
* @param element1 Optional child element
* @param element2 Optional child element
* @param element3 Optional child element
* @return Valid XmlElement pointer
*/
virtual XmlElement* createJingle(Action action, XmlElement* element1 = 0,
XmlElement* element2 = 0, XmlElement* element3 = 0);
/**
* Create a dtmf XML element
* @param dtmf The dtmf string
* @param msDuration The tone duration in miliseconds. Ignored if 0
* @return Valid XmlElement pointer or 0
*/
virtual XmlElement* createDtmf(const char* dtmf, unsigned int msDuration = 0);
/**
* Decode a file transfer element
* @param set True if the xml is an iq 'set', false if type is 'get'
* @param xml The element to decode
* @param child The element's first child
* @return JGEvent pointer or 0
*/
virtual JGEvent* processFileTransfer(bool set, XmlElement*& xml, XmlElement* child);
};
/**
* This class holds an event generated by a Jingle session
* @short A Jingle event
*/
class YJABBER_API JGEvent
{
friend class JGSession;
friend class JGSession0;
friend class JGSession1;
public:
/**
* Jingle events enumeration
*/
enum Type {
Jingle, //
ResultOk, // Response for a sent stanza (iq with type=result)
ResultError, // Response for a sent stanza (iq with type=error)
ResultTimeout, // Response for a sent stanza (stanza timeout)
// Final
Terminated, // m_element is the element that caused the termination
// m_reason contains the reason
Destroy, // The engine sould delete the event (causing session destruction)
};
/**
* Destructor. Deref the session. Delete the XML element
*/
virtual ~JGEvent();
/**
* Get the type of this event
* @return The type of this event as enumeration
*/
inline Type type() const
{ return m_type; }
/**
* Get the name of this
* @return The name of this event
*/
inline const char* name()
{ return lookupType(m_type); }
/**
* Get the session that generated this event
* @return The session that generated this event
*/
inline JGSession* session() const
{ return m_session; }
/**
* Get the XML element that generated this event
* @return The XML element that generated this event
*/
inline XmlElement* element() const
{ return m_element; }
/**
* Get the Jingle child of the XML element carried by the event
* Don't delete it after use: it is owned by the event
* @return The Jingle child of the XML element carried by the event
*/
inline XmlElement* jingle() const
{ return m_jingle; }
/**
* Get the jingle action as enumeration
* @return The jingle action as enumeration
*/
inline JGSession::Action action() const
{ return m_action; }
/**
* Get the name of an action
* @return The name of an action
*/
inline const char* actionName() const
{ return m_session ? JGSession::lookupAction(m_action,m_session->version()) : ""; }
/**
* Get the id
* @return The id
*/
inline const String& id() const
{ return m_id; }
/**
* Get the reason
* @return The reason
*/
inline const String& reason() const
{ return m_reason; }
/**
* Get the text
* @return The text
*/
inline const String& text() const
{ return m_text; }
/**
* Get the XML element that generated this event and set it to 0
* @return The XML element that generated this event
*/
inline XmlElement* releaseXml() {
XmlElement* tmp = m_element;
m_jingle = m_element = 0;
return tmp;
}
/**
* Check if this event is a final one (Terminated or Destroy)
* @return True if it is
*/
inline bool final() const
{ return m_type == Terminated || m_type == Destroy; }
/**
* Confirm the element carryied by this event. See JGSession::confirm() for details
* @param error The error condition
* @param text Optional text to add to the error element
* @param type Error type
* @return False if send failed or element is 0
*/
inline bool confirmElement(XMPPError::Type error = XMPPError::NoError,
const char* text = 0, XMPPError::ErrorType type = XMPPError::TypeModify) {
if (m_session && element() && !m_confirmed) {
m_confirmed = true;
if (error == XMPPError::NoError)
return m_session->confirmResult(element());
XmlElement* err = releaseXml();
return m_session->confirmError(err,error,text,type);
}
return false;
}
/**
* Set the confirmed flag. Use it for action with delayed response
*/
inline void setConfirmed()
{ m_confirmed = true; }
/**
* Set the jingle action as enumeration. Set confirmation flag if
* the element don't require it
* @param act The jingle action as enumeration
*/
void setAction(JGSession::Action act);
/**
* Get the name of an event type
* @return The name of an event type
*/
static inline const char* lookupType(int type)
{ return lookup(type,s_typeName); }
/**
* Dictionary with event type names
*/
static const TokenDict s_typeName[];
/**
* The list of session contents if used
*/
ObjList m_contents;
/**
* The list of stream hosts if used
*/
ObjList m_streamHosts;
protected:
/**
* Constructor. Set the id parameter if the element is valid
* @param type Event type
* @param session The session that generated this event
* @param element Optional XML element that generated this event
* @param reason Optional reason data
* @param text Optional text data
*/
inline JGEvent(Type type, JGSession* session, XmlElement* element = 0,
const char* reason = 0, const char* text = 0)
: m_type(type), m_confirmed(true), m_session(0), m_element(element),
m_jingle(0), m_action(JGSession::ActCount), m_reason(reason), m_text(text)
{ init(session); }
/**
* Constructor. Create a Jingle event. Set the id parameter if the element is valid
* @param act The jingle action
* @param session The session that generated this event
* @param element XML element that generated this event
* @param reason Optional reason data
* @param text Optional text data
*/
inline JGEvent(JGSession::Action act, JGSession* session, XmlElement* element,
const char* reason = 0, const char* text = 0)
: m_type(Jingle), m_confirmed(false), m_session(0), m_element(element), m_jingle(0),
m_action(act), m_reason(reason), m_text(text) {
init(session);
setAction(act);
}
private:
JGEvent() {} // Don't use it
void init(JGSession* session);
Type m_type; // The type of this event
bool m_confirmed; // Flag indicating that element was confirmed
JGSession* m_session; // Jingle session that generated this event
XmlElement* m_element; // XML element that generated this event
XmlElement* m_jingle; // The session child, if present
// Event specific
JGSession::Action m_action; // The action if type is Jingle
String m_id; // The element's id attribute
String m_reason; // The reason if type is Error or Terminated
String m_text; // Dtmf text
};
/**
* This class holds a Jingle service for the Jabber engine. Handle jingle stanzas,
* stanza write fail events and stream termination events
* @short A Jingle engine
*/
class YJABBER_API JGEngine : public DebugEnabler, public Mutex
{
friend class JGSession;
public:
/**
* Constructor
* @param name Debug name
*/
JGEngine(const char* name = "jgengine");
/**
* Destructor. Terminates all active sessions
*/
virtual ~JGEngine();
/**
* Retrieve the default session flags value
* @return The default session flags value
*/
inline int sessionFlags() const
{ return m_sessionFlags; }
/**
* Get the timeout interval of a sent stanza
* @return The timeout interval of a sent stanza
*/
inline u_int64_t stanzaTimeout() const
{ return m_stanzaTimeout; }
/**
* Get the timeout interval of a sent stream host stanza
* @return The timeout interval of a sent stream host stanza
*/
inline u_int64_t streamHostTimeout() const
{ return m_streamHostTimeout; }
/**
* Get the ping interval used by jingle sessions
* @return The interval to ping the remote party of a jingle session
*/
inline u_int64_t pingInterval() const
{ return m_pingInterval; }
/**
* Initialize this service
* @param params Service's parameters
*/
virtual void initialize(const NamedList& params);
/**
* Send a session's stanza.
* This method should be re-implemented
* @param session The session requesting the operation
* @param stanza The stanza to send. Will be consumed and zeroed
* @return True on success
*/
virtual bool sendStanza(JGSession* session, XmlElement*& stanza);
/**
* Send a chat message on behalf of a session
* @param session The session requesting the operation
* @param body Message body
* @return True on success
*/
virtual bool sendMessage(JGSession* session, const char* body);
/**
* Call getEvent() for each session list until an event is generated or the end is reached
* This method is thread safe
* @param time Current time in miliseconds
* @return The first generated event
*/
JGEvent* getEvent(u_int64_t time);
/**
* Make an outgoing call.
* 'media' and 'transport' will be invalid on exit. Don't delete them
* @param ver The session version to use
* @param caller The caller
* @param called The called
* @param contents The list of session content(s)
* @param extra Optional extra child for session initiate element
* @param msg Optional message to send before call
* @param subject Optional session subject
* @param line Optional session account
* @param flags Optional session flags to set
* @return Valid JGSession pointer (referenced) on success
*/
JGSession* call(JGSession::Version ver, const JabberID& caller, const JabberID& called,
const ObjList& contents, XmlElement* extra = 0, const char* msg = 0,
const char* subject = 0, const char* line = 0, int* flags = 0);
/**
* Ask this engine to accept an incoming xml 'iq' element
* @param type Iq type as enumeration
* @param from The sender
* @param to The recipient
* @param id Element id attribute
* @param xml The received element
* @param line Account receiving the stanza (may be empty)
* @param error XMPPError result. This value should be check if false is returned.
* Any value different from NoError indicate an invalid element
* @param text Error text
* @return True if accepted (don't use the given pointer if accepted)
*/
bool acceptIq(XMPPUtils::IqType type, const JabberID& from, const JabberID& to,
const String& id, XmlElement* xml, const char* line,
XMPPError::Type& error, String& text);
/**
* Default event processor. Delete event.
* @param event The event to process
*/
void defProcessEvent(JGEvent* event);
/**
* Process events from the sessions. Default action: Delete event.
* Descendants must override this method to process generated events
* @param event The event to process
*/
virtual void processEvent(JGEvent* event);
/**
* Decode a comma separated list of flags
* @param list The list of flags
* @param dict Dictionary to use
* @return Found flags
*/
static int decodeFlags(const String& list, const TokenDict* dict);
/**
* Encode (append) flags to a comma separated list
* @param buf Destination buffer
* @param flags Flags to encode
* @param dict Dictionary to use
*/
static void encodeFlags(String& buf, int flags, const TokenDict* dict);
private:
// Create a local session id
void createSessionId(String& id);
ObjList m_sessions; // List of sessions
u_int32_t m_sessionId; // Session id counter
u_int64_t m_stanzaTimeout; // The timeout of a sent stanza
u_int64_t m_streamHostTimeout; // The timeout of a sent stream host stanza
u_int64_t m_pingInterval; // Interval to send ping (empty session-info)
int m_sessionFlags; // Default session flags
};
/**
* This class holds sent stanzas info used for timeout checking
* @short Send stanza timeout info
*/
class YJABBER_API JGSentStanza : public String
{
public:
/**
* Constructor
* @param id The sent stanza's id
* @param time The sent time
* @param notif True to notify stanza timeout or response
* @param ping True if the sent stanza is a ping one
* @param action Optional sent stanza action
*/
JGSentStanza(const char* id, u_int64_t time, bool notif = false, bool ping = false,
JGSession::Action action = JGSession::ActCount)
: String(id), m_time(time), m_notify(notif), m_ping(ping), m_action(action)
{}
/**
* Retrieve stanza timeout
* @return Stanza timeout
*/
inline u_int64_t timeout() const
{ return m_time; }
/**
* Check if this element timed out
* @return True if timeout
*/
inline bool timeout(u_int64_t time) const
{ return time > m_time; }
/**
* Check if timeout should be notified to sender
* @return True to notify
*/
inline bool notify() const
{ return m_notify; }
/**
* Check if the stanza is a ping one
* @return True if the stanza is a ping one
*/
inline bool ping() const
{ return m_ping; }
/**
* Get the jingle action as enumeration
* @return The jingle action as enumeration
*/
inline JGSession::Action action() const
{ return m_action; }
private:
u_int64_t m_time; // Timeout
bool m_notify; // Notify timeout to sender
bool m_ping; // Sent stanza is a ping one
JGSession::Action m_action; // Sent stanza action
};
};
#endif /* __YATEJINGLE_H */
/* vi: set ts=8 sw=4 sts=4 noet: */