69e0103bc0
git-svn-id: http://yate.null.ro/svn/yate/trunk@2898 acf43c95-373e-0410-b603-e72c3f656dc1
2003 lines
62 KiB
C++
2003 lines
62 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-2006 Null Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#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)
|
|
*/
|
|
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)
|
|
: m_params("")
|
|
{ set(id,name,clockrate,synonym,channels); }
|
|
|
|
/**
|
|
* 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)
|
|
: GenObject(),
|
|
m_params(src.m_params)
|
|
{ set(src.m_id,src.m_name,src.m_clockrate,src.m_synonym,src.m_channels); }
|
|
|
|
/**
|
|
* 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)
|
|
*/
|
|
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) {
|
|
m_id = id;
|
|
m_name = name;
|
|
m_clockrate = clockrate;
|
|
m_synonym = synonym;
|
|
m_channels = channels;
|
|
m_pTime = pTime;
|
|
m_maxPTime = maxPTime;
|
|
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);
|
|
|
|
/**
|
|
* Build a telephone-event media
|
|
* @return JGRtpMedia pointer
|
|
*/
|
|
static inline JGRtpMedia* telEvent()
|
|
{ return new JGRtpMedia("106","telephone-event","8000",""); }
|
|
|
|
/**
|
|
* 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;
|
|
|
|
/**
|
|
* 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)
|
|
{}
|
|
|
|
/**
|
|
* 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)
|
|
*/
|
|
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)
|
|
{ append(new JGRtpMedia(id,name,clockrate,synonym,channels,pTime,maxPTime)); }
|
|
|
|
/**
|
|
* Reset the list and data
|
|
*/
|
|
void reset();
|
|
|
|
/**
|
|
* 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
|
|
* @param telEvent True to append a telephone event data payload
|
|
* @return Valid XmlElement pointer
|
|
*/
|
|
XmlElement* toXml(bool telEvent = true) 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 = ",");
|
|
|
|
/**
|
|
* 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;
|
|
};
|
|
|
|
|
|
/**
|
|
* This class holds a RTP transport candidate
|
|
* @short A RTP transport candidate
|
|
*/
|
|
class 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
|
|
*/
|
|
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 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 = 2,
|
|
};
|
|
|
|
/**
|
|
* 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 = 2, // Audio: RTP RAW-UDP transport
|
|
FileBSBOffer = 3, // File offer: byte stream (SOCKS) transport
|
|
FileBSBRequest = 4, // 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 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(const char* jid, const char* addr, int port, const char* zeroConf = 0)
|
|
: String(jid),
|
|
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_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);
|
|
|
|
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,
|
|
};
|
|
|
|
/**
|
|
* 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; }
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
inline Action getAction(XmlElement* xml)
|
|
{ return xml ? lookupAction(xml->attribute("type"),m_version) : ActCount; }
|
|
|
|
/**
|
|
* 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)
|
|
* @return False on failure
|
|
*/
|
|
bool sendInfo(XmlElement* xml, String* stanzaId = 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[];
|
|
|
|
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
|
|
* @return True on success
|
|
*/
|
|
bool sendStanza(XmlElement* stanza, String* stanzaId = 0, bool confirmation = true,
|
|
bool ping = false);
|
|
|
|
/**
|
|
* 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
|
|
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();
|
|
|
|
/**
|
|
* 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 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
|
|
* @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);
|
|
|
|
/**
|
|
* 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);
|
|
|
|
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_pingInterval; // Interval to send ping (empty session-info)
|
|
};
|
|
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
JGSentStanza(const char* id, u_int64_t time, bool notif = false, bool ping = false)
|
|
: String(id), m_time(time), m_notify(notif), m_ping(ping)
|
|
{}
|
|
|
|
/**
|
|
* 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; }
|
|
|
|
private:
|
|
u_int64_t m_time; // Timeout
|
|
bool m_notify; // Notify timeout to sender
|
|
bool m_ping; // Sent stanza is a ping one
|
|
};
|
|
|
|
};
|
|
|
|
#endif /* __YATEJINGLE_H */
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|