gloox 1.0.27
simanager.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 "simanager.h"
15
16#include "siprofilehandler.h"
17#include "sihandler.h"
18#include "clientbase.h"
19#include "disco.h"
20#include "error.h"
21
22namespace gloox
23{
24
25 // ---- SIManager::SI ----
26 SIManager::SI::SI( const Tag* tag )
27 : StanzaExtension( ExtSI ), m_tag1( 0 ), m_tag2( 0 )
28 {
29 if( !tag || tag->name() != "si" || tag->xmlns() != XMLNS_SI )
30 return;
31
32 m_valid = true;
33
34 m_id = tag->findAttribute( "id" );
35 m_mimetype = tag->findAttribute( "mime-type" );
36 m_profile = tag->findAttribute( "profile" );
37
38 Tag* c = tag->findChild( "file", "xmlns", XMLNS_SI_FT );
39 if ( c )
40 m_tag1 = c->clone();
41 c = tag->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
42 if( c )
43 m_tag2 = c->clone();
44 }
45
46 SIManager::SI::SI( Tag* tag1, Tag* tag2, const std::string& id,
47 const std::string& mimetype, const std::string& profile )
48 : StanzaExtension( ExtSI ), m_tag1( tag1 ), m_tag2( tag2 ),
49 m_id( id ), m_mimetype( mimetype ), m_profile( profile )
50 {
51 m_valid = true;
52 }
53
54 SIManager::SI::~SI()
55 {
56 delete m_tag1;
57 delete m_tag2;
58 }
59
60 const std::string& SIManager::SI::filterString() const
61 {
62 static const std::string filter = "/iq/si[@xmlns='" + XMLNS_SI + "']";
63 return filter;
64 }
65
66 Tag* SIManager::SI::tag() const
67 {
68 if( !m_valid )
69 return 0;
70
71 Tag* t = new Tag( "si" );
72 t->setXmlns( XMLNS_SI );
73 if( !m_id.empty() )
74 t->addAttribute( "id", m_id );
75 if( !m_mimetype.empty() )
76 t->addAttribute( "mime-type", m_mimetype.empty() ? "binary/octet-stream" : m_mimetype );
77 if( !m_profile.empty() )
78 t->addAttribute( "profile", m_profile );
79 if( m_tag1 )
80 t->addChildCopy( m_tag1 );
81 if( m_tag2 )
82 t->addChildCopy( m_tag2 );
83
84 return t;
85 }
86 // ---- ~SIManager::SI ----
87
88 // ---- SIManager ----
89 SIManager::SIManager( ClientBase* parent, bool advertise )
90 : m_parent( parent ), m_advertise( advertise )
91 {
92 if( m_parent )
93 {
94 m_parent->registerStanzaExtension( new SI() );
95 m_parent->registerIqHandler( this, ExtSI );
96 if( m_parent->disco() && m_advertise )
97 m_parent->disco()->addFeature( XMLNS_SI );
98 }
99 }
100
102 {
103 if( m_parent )
104 {
105 m_parent->removeIqHandler( this, ExtSI );
106 m_parent->removeIDHandler( this );
107 if( m_parent->disco() && m_advertise )
108 m_parent->disco()->removeFeature( XMLNS_SI );
109 }
110 }
111
112 const std::string SIManager::requestSI( SIHandler* sih, const JID& to, const std::string& profile,
113 Tag* child1, Tag* child2, const std::string& mimetype,
114 const JID& from, const std::string& sid )
115 {
116 if( !m_parent || !sih )
117 return EmptyString;
118
119 const std::string& id = m_parent->getID();
120 const std::string& sidToUse = sid.empty() ? m_parent->getID() : sid;
121
122 IQ iq( IQ::Set, to, id );
123 iq.addExtension( new SI( child1, child2, sidToUse, mimetype, profile ) );
124 if( from )
125 iq.setFrom( from );
126
127 TrackStruct t;
128 t.sid = sidToUse;
129 t.profile = profile;
130 t.sih = sih;
131 m_track[id] = t;
132 m_parent->send( iq, this, OfferSI );
133
134 return sidToUse;
135 }
136
137 void SIManager::acceptSI( const JID& to, const std::string& id, Tag* child1, Tag* child2, const JID& from )
138 {
139 IQ iq( IQ::Result, to, id );
140 iq.addExtension( new SI( child1, child2 ) );
141 if( from )
142 iq.setFrom( from );
143
144 m_parent->send( iq );
145 }
146
147 void SIManager::declineSI( const JID& to, const std::string& id, SIError reason, const std::string& text )
148 {
149 IQ iq( IQ::Error, to, id );
150 Error* error;
151 if( reason == NoValidStreams || reason == BadProfile )
152 {
153 Tag* appError = 0;
154 if( reason == NoValidStreams )
155 appError = new Tag( "no-valid-streams", XMLNS, XMLNS_SI );
156 else if( reason == BadProfile )
157 appError = new Tag( "bad-profile", XMLNS, XMLNS_SI );
158 error = new Error( StanzaErrorTypeCancel, StanzaErrorBadRequest, appError );
159 }
160 else
161 {
163 if( !text.empty() )
164 error->text( text );
165 }
166
167 iq.addExtension( error );
168 m_parent->send( iq );
169 }
170
171 void SIManager::registerProfile( const std::string& profile, SIProfileHandler* sih )
172 {
173 if( !sih || profile.empty() )
174 return;
175
176 m_handlers[profile] = sih;
177
178 if( m_parent && m_advertise && m_parent->disco() )
179 m_parent->disco()->addFeature( profile );
180 }
181
182 void SIManager::removeProfile( const std::string& profile )
183 {
184 if( profile.empty() )
185 return;
186
187 m_handlers.erase( profile );
188
189 if( m_parent && m_advertise && m_parent->disco() )
190 m_parent->disco()->removeFeature( profile );
191 }
192
193 bool SIManager::handleIq( const IQ& iq )
194 {
195 TrackMap::iterator itt = m_track.find( iq.id() );
196 if( itt != m_track.end() )
197 return false;
198
199 const SI* si = iq.findExtension<SI>( ExtSI );
200 if( !si || si->profile().empty() )
201 return false;
202
203 HandlerMap::const_iterator it = m_handlers.find( si->profile() );
204 if( it != m_handlers.end() && (*it).second )
205 {
206 (*it).second->handleSIRequest( iq.from(), iq.to(), iq.id(), *si );
207 return true;
208 }
209
210 return false;
211 }
212
213 void SIManager::handleIqID( const IQ& iq, int context )
214 {
215 switch( iq.subtype() )
216 {
217 case IQ::Result:
218 if( context == OfferSI )
219 {
220 TrackMap::iterator it = m_track.find( iq.id() );
221 if( it != m_track.end() )
222 {
223 const SI* si = iq.findExtension<SI>( ExtSI );
224 if( !si /*|| si->profile().empty()*/ )
225 return;
226
227// Tag* si = iq.query();
228// Tag* ptag = 0;
229// Tag* fneg = 0;
230// if( si && si->name() == "si" && si->xmlns() == XMLNS_SI )
231// {
232// ptag = si->findChildWithAttrib( XMLNS, (*it).second.profile );
233// fneg = si->findChild( "feature", XMLNS, XMLNS_FEATURE_NEG );
234// }
235
236 // FIXME: remove above commented code and
237 // check corectness of last 3 params!
238 (*it).second.sih->handleSIRequestResult( iq.from(), iq.to(), (*it).second.sid, *si );
239 m_track.erase( it );
240 }
241 }
242 break;
243 case IQ::Error:
244 if( context == OfferSI )
245 {
246 TrackMap::iterator it = m_track.find( iq.id() );
247 if( it != m_track.end() )
248 {
249 (*it).second.sih->handleSIRequestError( iq, (*it).second.sid );
250 m_track.erase( it );
251 }
252 }
253 break;
254 default:
255 break;
256 }
257 }
258
259}
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition: clientbase.h:79
const std::string getID()
void removeIqHandler(IqHandler *ih, int exttype)
void removeIDHandler(IqHandler *ih)
void send(Tag *tag)
void registerIqHandler(IqHandler *ih, int exttype)
virtual Disco * disco() const
Definition: clientbase.h:233
void registerStanzaExtension(StanzaExtension *ext)
void removeFeature(const std::string &feature)
Definition: disco.h:430
void addFeature(const std::string &feature)
Definition: disco.h:422
A stanza error abstraction implemented as a StanzaExtension.
Definition: error.h:35
const std::string & text(const std::string &lang=EmptyString) const
Definition: error.cpp:132
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
An abstract base class to handle results of outgoing SI requests, i.e. you requested a stream (using ...
Definition: sihandler.h:40
virtual ~SIManager()
Definition: simanager.cpp:101
virtual void handleIqID(const IQ &iq, int context)
Definition: simanager.cpp:213
virtual bool handleIq(const IQ &iq)
Definition: simanager.cpp:193
void acceptSI(const JID &to, const std::string &id, Tag *child1, Tag *child2=0, const JID &from=JID())
Definition: simanager.cpp:137
void registerProfile(const std::string &profile, SIProfileHandler *sih)
Definition: simanager.cpp:171
void declineSI(const JID &to, const std::string &id, SIError reason, const std::string &text=EmptyString)
Definition: simanager.cpp:147
void removeProfile(const std::string &profile)
Definition: simanager.cpp:182
const std::string requestSI(SIHandler *sih, const JID &to, const std::string &profile, Tag *child1, Tag *child2=0, const std::string &mimetype="binary/octet-stream", const JID &from=JID(), const std::string &sid=EmptyString)
Definition: simanager.cpp:112
An abstract base class to handle SI requests for a specific profile, e.g. file transfer.
void addExtension(const StanzaExtension *se)
Definition: stanza.cpp:52
void setFrom(const JID &from)
Definition: stanza.h:45
const std::string & id() const
Definition: stanza.h:63
const JID & from() const
Definition: stanza.h:51
const JID & to() const
Definition: stanza.h:57
const StanzaExtension * findExtension(int type) const
Definition: stanza.cpp:57
This is an abstraction of an XML element.
Definition: tag.h:47
The namespace for the gloox library.
Definition: adhoc.cpp:28
const std::string EmptyString
Definition: gloox.cpp:124
const std::string XMLNS
Definition: gloox.cpp:122
@ StanzaErrorForbidden
Definition: gloox.h:884
@ StanzaErrorBadRequest
Definition: gloox.h:874
const std::string XMLNS_SI
Definition: gloox.cpp:63
@ StanzaErrorTypeCancel
Definition: gloox.h:859