gloox 1.0.27
jinglesession.cpp
1/*
2 Copyright (c) 2007-2023 by Jakob Schröter <js@camaya.net>
3 This file is part of the gloox library. http://camaya.net/gloox
4
5 This software is distributed under a license. The full license
6 agreement can be found in the file LICENSE in this distribution.
7 This software may not be copied, modified, sold or distributed
8 other than expressed in the named license agreement.
9
10 This software is distributed without any warranty.
11*/
12
13
14#include "jinglesession.h"
15
16#include "clientbase.h"
17#include "error.h"
18#include "jinglecontent.h"
19#include "jinglesessionhandler.h"
20#include "tag.h"
21#include "util.h"
22
23namespace gloox
24{
25
26 namespace Jingle
27 {
28
29 static const char* actionValues [] = {
30 "content-accept",
31 "content-add",
32 "content-modify",
33 "content-reject",
34 "content-remove",
35 "description-info",
36 "security-info",
37 "session-accept",
38 "session-info",
39 "session-initiate",
40 "session-terminate",
41 "transport-accept",
42 "transport-info",
43 "transport-reject",
44 "transport-replace"
45 };
46
47 static inline Action actionType( const std::string& type )
48 {
49 return static_cast<Action>( util::lookup( type, actionValues ) );
50 }
51
52 // ---- Session::Reason ----
53 static const char* reasonValues [] = {
54 "alternative-session",
55 "busy",
56 "cancel",
57 "connectivity-error",
58 "decline",
59 "expired",
60 "failed-application",
61 "failed-transport",
62 "general-error",
63 "gone",
64 "incompatible-parameters",
65 "media-error",
66 "security-error",
67 "success",
68 "timeout",
69 "unsupported-applications",
70 "unsupported-transports"
71 };
72
73 static inline Session::Reason::Reasons reasonType( const std::string& type )
74 {
75 return static_cast<Session::Reason::Reasons>( util::lookup( type, reasonValues ) );
76 }
77
79 const std::string& sid,
80 const std::string& text)
81 : Plugin( PluginReason ), m_reason( reason ), m_sid( sid ), m_text( text )
82 {
83 }
84
87 {
88 if( !tag || tag->name() != "reason" )
89 return;
90
91 const TagList& l = tag->children();
92 TagList::const_iterator it = l.begin();
93 for( ; it != l.end(); ++it )
94 {
95 if( (*it)->name() == "text" )
96 m_text = (*it)->cdata();
97 else if( (*it)->xmlns() == XMLNS_JINGLE )
98 m_reason = reasonType( (*it)->name() );
99 }
100 }
101
105
106 const std::string& Session::Reason::filterString() const
107 {
108 static const std::string filter = "jingle/reason";
109 return filter;
110 }
111
113 {
114 if( m_reason == InvalidReason )
115 return 0;
116
117 Tag* t = new Tag( "reason" );
118 Tag* r = new Tag( t, util::lookup( m_reason, reasonValues ) );
119 if( m_reason == AlternativeSession && !m_sid.empty() )
120 new Tag( r, "sid", m_sid );
121
122 if( !m_text.empty() )
123 new Tag( t, "text", m_text );
124
125 return t;
126 }
127
129 {
130 return new Reason( *this );
131 }
132 // ---- ~Session::Reason ----
133
134 // ---- Session::Jingle ----
136 const PluginList& plugins, const std::string& sid )
137 : StanzaExtension( ExtJingle ), m_action( action ), m_sid( sid ),
138 m_initiator( initiator ), m_responder( responder ), m_plugins( plugins ), m_tag( 0 )
139 {
140 }
141
142#ifdef JINGLE_TEST
144 const Plugin* plugin, const std::string& sid )
145 : StanzaExtension( ExtJingle ), m_action( action ), m_sid( sid ),
146 m_initiator( initiator ), m_responder( responder ), m_tag( 0 )
147 {
148 if( plugin )
149 m_plugins.push_back( plugin );
150 }
151#endif
152
154 : StanzaExtension( ExtJingle ), m_action( InvalidAction ), m_tag( 0 )
155 {
156 if( !tag || tag->name() != "jingle" )
157 return;
158
159 m_action = actionType( tag->findAttribute( "action" ) );
160 m_initiator.setJID( tag->findAttribute( "initiator" ) );
161 m_responder.setJID( tag->findAttribute( "responder" ) );
162 m_sid = tag->findAttribute( "sid" );
163
164 m_tag = tag->clone();
165 }
166
167// Session::Jingle::Jingle( const Jingle& right )
168// : StanzaExtension( ExtJingle ), m_action( right.m_action ),
169// m_sid( right.m_sid ), m_initiator( right.m_initiator ),
170// m_responder( right.m_responder )
171// {
172// PluginList::const_iterator it = right.m_plugins.begin();
173// for( ; it != right.m_plugins.end(); ++it )
174// m_plugins.push_back( (*it)->clone() );
175// }
176
178 {
179 util::clearList( m_plugins );
180 }
181
182 const std::string& Session::Jingle::filterString() const
183 {
184 static const std::string filter = "/iq/jingle[@xmlns='" + XMLNS_JINGLE + "']";
185 return filter;
186 }
187
189 {
190 if( m_action == InvalidAction || m_sid.empty() )
191 return 0;
192
193 Tag* t = new Tag( "jingle" );
195 t->addAttribute( "action", util::lookup( m_action, actionValues ) );
196
197 if( m_initiator && m_action == SessionInitiate )
198 t->addAttribute( "initiator", m_initiator.full() );
199
200 if( m_responder && m_action == SessionAccept )
201 t->addAttribute( "responder", m_responder.full() );
202
203 t->addAttribute( "sid", m_sid );
204
205 PluginList::const_iterator it = m_plugins.begin();
206 for( ; it != m_plugins.end(); ++it )
207 t->addChild( (*it)->tag() );
208
209 return t;
210 }
211
213 {
214 return new Jingle( *this );
215 }
216 // ---- ~Session::Jingle ----
217
218 // ---- Session ----
219 Session::Session( ClientBase* parent, const JID& callee, SessionHandler* jsh )
220 : m_parent( parent ), m_state( Ended ), m_remote( callee ),
221 m_handler( jsh ), m_valid( false )
222 {
223 if( !m_parent || !m_handler || !m_remote )
224 return;
225
226 m_initiator = m_parent->jid();
227 m_sid = m_parent->getID();
228
229 m_valid = true;
230 }
231
232 Session::Session( ClientBase* parent, const JID& callee, const Session::Jingle* jingle, SessionHandler* jsh )
233 : m_parent( parent ), m_state( Ended ), m_handler( jsh ), m_valid( false )
234 {
235 if( !m_parent || !m_handler || !callee /*|| jingle->action() != SessionInitiate*/ )
236 return;
237
238 m_remote = callee;
239 m_sid = jingle->sid();
240
241 m_valid = true;
242 }
243
245 {
246 if( m_parent )
247 m_parent->removeIDHandler( this );
248 }
249
250 bool Session::contentAccept( const Content* content )
251 {
252 if( m_state < Pending )
253 return false;
254
255 return doAction( ContentAccept, content );
256 }
257
258 bool Session::contentAdd( const Content* content )
259 {
260 if( m_state < Pending )
261 return false;
262
263 return doAction( ContentAdd, content );
264 }
265
266 bool Session::contentAdd( const PluginList& contents )
267 {
268 if( m_state < Pending )
269 return false;
270
271 return doAction( ContentAdd, contents );
272 }
273
274 bool Session::contentModify( const Content* content )
275 {
276 if( m_state < Pending )
277 return false;
278
279 return doAction( ContentModify, content );
280 }
281
282 bool Session::contentReject( const Content* content )
283 {
284 if( m_state < Pending )
285 return false;
286
287 return doAction( ContentReject, content );
288 }
289
290 bool Session::contentRemove( const Content* content )
291 {
292 if( m_state < Pending )
293 return false;
294
295 return doAction( ContentRemove, content );
296 }
297
299 {
300 if( m_state < Pending )
301 return false;
302
303 return doAction( DescriptionInfo, info );
304 }
305
306 bool Session::securityInfo( const Plugin* info )
307 {
308 if( m_state < Pending )
309 return false;
310
311 return doAction( SecurityInfo, info );
312 }
313
314 bool Session::sessionAccept( const Content* content )
315 {
316 if( !content || m_state > Pending )
317 return false;
318
319 m_state = Active;
320 return doAction( SessionAccept, content );
321 }
322
323 bool Session::sessionAccept( const PluginList& plugins )
324 {
325 if( plugins.empty() || m_state != Pending )
326 return false;
327
328 m_state = Active;
329 return doAction( SessionAccept, plugins );
330 }
331
332 bool Session::sessionInfo( const Plugin* info )
333 {
334 if( m_state < Pending )
335 return false;
336
337 return doAction( SessionInfo, info );
338 }
339
340 bool Session::sessionInitiate( const Content* content )
341 {
342 if( !content || !m_initiator || m_state >= Pending )
343 return false;
344
345 m_state = Pending;
346 return doAction( SessionInitiate, content );
347 }
348
350 {
351 if( plugins.empty() || !m_initiator || m_state >= Pending )
352 return false;
353
354 m_state = Pending;
355 return doAction( SessionInitiate, plugins );
356 }
357
359 {
360 if( m_state < Pending /*|| !m_initiator*/ )
361 return false;
362
363 m_state = Ended;
364
365 return doAction( SessionTerminate, reason );
366 }
367
368 bool Session::transportAccept( const Content* content )
369 {
370 if( m_state < Pending )
371 return false;
372
373 return doAction( TransportAccept, content );
374 }
375
376 bool Session::transportInfo( const Plugin* info )
377 {
378 if( m_state < Pending )
379 return false;
380
381 return doAction( TransportInfo, info );
382 }
383
384 bool Session::transportReject( const Content* content )
385 {
386 if( m_state < Pending )
387 return false;
388
389 return doAction( TransportReject, content );
390 }
391
392 bool Session::transportReplace( const Content* content )
393 {
394 if( m_state < Pending )
395 return false;
396
397 return doAction( TransportReplace, content );
398 }
399
400 bool Session::doAction( Action action, const Plugin* plugin )
401 {
402 PluginList pl;
403 pl.push_back( plugin );
404 return doAction( action, pl );
405 }
406
407 bool Session::doAction( Action action, const PluginList& plugins )
408 {
409 if( !m_valid || !m_parent )
410 return false;
411
412 IQ init( IQ::Set, m_remote, m_parent->getID() );
413 init.addExtension( new Jingle( action, m_initiator, m_responder, plugins, m_sid ) );
414 m_parent->send( init, this, action );
415
416 return true;
417 }
418
419 bool Session::handleIq( const IQ& iq )
420 {
421 const Jingle* j = iq.findExtension<Jingle>( ExtJingle );
422 if( !j || j->sid() != m_sid || !m_handler || !m_parent )
423 return false;
424
425 switch( j->action() )
426 {
427 case SessionAccept:
428 m_state = Active;
429 m_responder = j->responder();
430 break;
431 case SessionInitiate:
432 m_state = Pending;
433 m_initiator = j->initiator();
434 if( !m_responder )
435 m_responder = m_parent->jid();
436 break;
437 case SessionTerminate:
438 m_state = Ended;
439 break;
440 default:
441 break;
442 }
443
444 IQ re( IQ::Result, iq.from(), iq.id() );
445 m_parent->send( re );
446
447 m_handler->handleSessionAction( j->action(), this, j );
448
449 return true;
450 }
451
452 void Session::handleIqID( const IQ& iq, int context )
453 {
454 if( iq.subtype() == IQ::Error )
455 {
456
457 const Error* e = iq.findExtension<Error>( ExtError );
458 m_handler->handleSessionActionError( static_cast<Action>( context ), this, e );
459
460 switch( context )
461 {
462 case ContentAccept:
463 break;
464 case ContentAdd:
465 break;
466 case ContentModify:
467 break;
468 case ContentReject:
469 break;
470 case ContentRemove:
471 break;
472 case DescriptionInfo:
473 break;
474 case SessionAccept:
475 break;
476 case SessionInfo:
477 break;
478 case SessionInitiate:
479 m_state = Ended;
480 break;
481 case SessionTerminate:
482 break;
483 case TransportAccept:
484 break;
485 case TransportInfo:
486 break;
487 case TransportReject:
488 break;
489 case TransportReplace:
490 break;
491 case InvalidAction:
492 break;
493 default:
494 break;
495 }
496 }
497 }
498
499 }
500
501}
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition clientbase.h:79
const std::string getID()
void removeIDHandler(IqHandler *ih)
void send(Tag *tag)
const JID & jid()
Definition clientbase.h:147
A stanza error abstraction implemented as a StanzaExtension.
Definition error.h:35
An abstraction of an IQ stanza.
Definition iq.h:34
IqType subtype() const
Definition iq.h:74
@ Set
Definition iq.h:46
@ Error
Definition iq.h:49
@ Result
Definition iq.h:48
An abstraction of a JID.
Definition jid.h:31
bool setJID(const std::string &jid)
Definition jid.cpp:21
const std::string & full() const
Definition jid.h:61
An abstraction of a Jingle Content Type. This is part of Jingle (XEP-0166).
An abstraction of a Jingle plugin. This is part of Jingle (XEP-0166 et al.)
A Jingle session handler.
virtual void handleSessionActionError(Action action, Session *session, const Error *error)=0
virtual void handleSessionAction(Action action, Session *session, const Session::Jingle *jingle)=0
This is an abstraction of Jingle's (XEP-0166) <jingle> element as a StanzaExtension.
virtual StanzaExtension * clone() const
virtual const std::string & filterString() const
const std::string & sid() const
An abstraction of a Jingle (XEP-0166) session terminate reason.
Reason(Reasons reason, const std::string &sid=EmptyString, const std::string &text=EmptyString)
virtual Plugin * clone() const
virtual const std::string & filterString() const
bool contentReject(const Content *content)
bool transportReplace(const Content *content)
bool sessionAccept(const Content *content)
bool contentRemove(const Content *content)
bool sessionInfo(const Plugin *info)
bool transportReject(const Content *content)
bool transportInfo(const Plugin *info)
bool contentAdd(const Content *content)
bool sessionInitiate(const Content *content)
bool transportAccept(const Content *content)
virtual void handleIqID(const IQ &iq, int context)
virtual bool handleIq(const IQ &iq)
bool contentModify(const Content *content)
const JID & responder() const
const std::string & sid() const
bool securityInfo(const Plugin *info)
bool descriptionInfo(const Plugin *info)
const JID & initiator() const
bool contentAccept(const Content *content)
bool sessionTerminate(Session::Reason *reason)
This class abstracts a stanza extension, which is usually an XML child element in a specific namespac...
const std::string & id() const
Definition stanza.h:63
const JID & from() const
Definition stanza.h:51
const StanzaExtension * findExtension(int type) const
Definition stanza.cpp:57
This is an abstraction of an XML element.
Definition tag.h:47
const std::string & name() const
Definition tag.h:394
bool addAttribute(Attribute *attr)
Definition tag.cpp:354
void addChild(Tag *child)
Definition tag.cpp:424
const std::string & findAttribute(const std::string &name) const
Definition tag.cpp:589
Tag * clone() const
Definition tag.cpp:670
const TagList & children() const
Definition tag.cpp:510
bool setXmlns(const std::string &xmlns, const std::string &prefix=EmptyString)
Definition tag.cpp:522
std::list< const Plugin * > PluginList
void clearList(std::list< T * > &L)
Definition util.h:152
The namespace for the gloox library.
Definition adhoc.cpp:28
std::list< Tag * > TagList
Definition tag.h:31
const std::string XMLNS_JINGLE
Definition gloox.cpp:101