simanager.cpp
/*
Copyright (c) 2007-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "simanager.h"
#include "siprofilehandler.h"
#include "sihandler.h"
#include "clientbase.h"
#include "disco.h"
#include "error.h"
namespace gloox
{
// ---- SIManager::SI ----
SIManager::SI::SI( const Tag* tag )
: StanzaExtension( ExtSI ), m_tag1( 0 ), m_tag2( 0 )
{
if( !tag || tag->name() != "si" || tag->xmlns() != XMLNS_SI )
return;
m_valid = true;
m_id = tag->findAttribute( "id" );
m_mimetype = tag->findAttribute( "mime-type" );
m_profile = tag->findAttribute( "profile" );
Tag* c = tag->findChild( "file", "xmlns", XMLNS_SI_FT );
if ( c )
m_tag1 = c->clone();
c = tag->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
if( c )
m_tag2 = c->clone();
}
SIManager::SI::SI( Tag* tag1, Tag* tag2, const std::string& id,
const std::string& mimetype, const std::string& profile )
: StanzaExtension( ExtSI ), m_tag1( tag1 ), m_tag2( tag2 ),
m_id( id ), m_mimetype( mimetype ), m_profile( profile )
{
m_valid = true;
}
SIManager::SI::~SI()
{
delete m_tag1;
delete m_tag2;
}
const std::string& SIManager::SI::filterString() const
{
static const std::string filter = "/iq/si[@xmlns='" + XMLNS_SI + "']";
return filter;
}
Tag* SIManager::SI::tag() const
{
if( !m_valid )
return 0;
Tag* t = new Tag( "si" );
t->setXmlns( XMLNS_SI );
if( !m_id.empty() )
t->addAttribute( "id", m_id );
if( !m_mimetype.empty() )
t->addAttribute( "mime-type", m_mimetype.empty() ? "binary/octet-stream" : m_mimetype );
if( !m_profile.empty() )
t->addAttribute( "profile", m_profile );
if( m_tag1 )
t->addChildCopy( m_tag1 );
if( m_tag2 )
t->addChildCopy( m_tag2 );
return t;
}
// ---- ~SIManager::SI ----
// ---- SIManager ----
SIManager::SIManager( ClientBase* parent, bool advertise )
: m_parent( parent ), m_advertise( advertise )
{
if( m_parent )
{
m_parent->registerStanzaExtension( new SI() );
m_parent->registerIqHandler( this, ExtSI );
if( m_parent->disco() && m_advertise )
m_parent->disco()->addFeature( XMLNS_SI );
}
}
SIManager::~SIManager()
{
if( m_parent )
{
m_parent->removeIqHandler( this, ExtSI );
m_parent->removeIDHandler( this );
if( m_parent->disco() && m_advertise )
m_parent->disco()->removeFeature( XMLNS_SI );
}
}
const std::string SIManager::requestSI( SIHandler* sih, const JID& to, const std::string& profile,
Tag* child1, Tag* child2, const std::string& mimetype,
const JID& from, const std::string& sid )
{
if( !m_parent || !sih )
return EmptyString;
const std::string& id = m_parent->getID();
const std::string& sidToUse = sid.empty() ? m_parent->getID() : sid;
IQ iq( IQ::Set, to, id );
iq.addExtension( new SI( child1, child2, sidToUse, mimetype, profile ) );
if( from )
iq.setFrom( from );
TrackStruct t;
t.sid = sidToUse;
t.profile = profile;
t.sih = sih;
m_track[id] = t;
m_parent->send( iq, this, OfferSI );
return sidToUse;
}
void SIManager::acceptSI( const JID& to, const std::string& id, Tag* child1, Tag* child2, const JID& from )
{
IQ iq( IQ::Result, to, id );
iq.addExtension( new SI( child1, child2 ) );
if( from )
iq.setFrom( from );
m_parent->send( iq );
}
void SIManager::declineSI( const JID& to, const std::string& id, SIError reason, const std::string& text )
{
IQ iq( IQ::Error, to, id );
Error* error;
if( reason == NoValidStreams || reason == BadProfile )
{
Tag* appError = 0;
if( reason == NoValidStreams )
appError = new Tag( "no-valid-streams", XMLNS, XMLNS_SI );
else if( reason == BadProfile )
appError = new Tag( "bad-profile", XMLNS, XMLNS_SI );
error = new Error( StanzaErrorTypeCancel, StanzaErrorBadRequest, appError );
}
else
{
error = new Error( StanzaErrorTypeCancel, StanzaErrorForbidden );
if( !text.empty() )
error->text( text );
}
iq.addExtension( error );
m_parent->send( iq );
}
void SIManager::registerProfile( const std::string& profile, SIProfileHandler* sih )
{
if( !sih || profile.empty() )
return;
m_handlers[profile] = sih;
if( m_parent && m_advertise && m_parent->disco() )
m_parent->disco()->addFeature( profile );
}
void SIManager::removeProfile( const std::string& profile )
{
if( profile.empty() )
return;
m_handlers.erase( profile );
if( m_parent && m_advertise && m_parent->disco() )
m_parent->disco()->removeFeature( profile );
}
bool SIManager::handleIq( const IQ& iq )
{
TrackMap::iterator itt = m_track.find( iq.id() );
if( itt != m_track.end() )
return false;
const SI* si = iq.findExtension<SI>( ExtSI );
if( !si || si->profile().empty() )
return false;
HandlerMap::const_iterator it = m_handlers.find( si->profile() );
if( it != m_handlers.end() && (*it).second )
{
(*it).second->handleSIRequest( iq.from(), iq.to(), iq.id(), *si );
return true;
}
return false;
}
void SIManager::handleIqID( const IQ& iq, int context )
{
switch( iq.subtype() )
{
case IQ::Result:
if( context == OfferSI )
{
TrackMap::iterator it = m_track.find( iq.id() );
if( it != m_track.end() )
{
const SI* si = iq.findExtension<SI>( ExtSI );
if( !si /*|| si->profile().empty()*/ )
return;
// Tag* si = iq.query();
// Tag* ptag = 0;
// Tag* fneg = 0;
// if( si && si->name() == "si" && si->xmlns() == XMLNS_SI )
// {
// ptag = si->findChildWithAttrib( XMLNS, (*it).second.profile );
// fneg = si->findChild( "feature", XMLNS, XMLNS_FEATURE_NEG );
// }
// FIXME: remove above commented code and
// check corectness of last 3 params!
(*it).second.sih->handleSIRequestResult( iq.from(), iq.to(), (*it).second.sid, *si );
m_track.erase( it );
}
}
break;
case IQ::Error:
if( context == OfferSI )
{
TrackMap::iterator it = m_track.find( iq.id() );
if( it != m_track.end() )
{
(*it).second.sih->handleSIRequestError( iq, (*it).second.sid );
m_track.erase( it );
}
}
break;
default:
break;
}
}
}
gloox::ClientBase
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition clientbase.h:79
gloox::Error
A stanza error abstraction implemented as a StanzaExtension.
Definition error.h:35
gloox::Error::text
const std::string & text(const std::string &lang=EmptyString) const
Definition error.cpp:132
gloox::IQ
An abstraction of an IQ stanza.
Definition iq.h:34
gloox::IQ::subtype
IqType subtype() const
Definition iq.h:74
gloox::IQ::Set
@ Set
Definition iq.h:46
gloox::IQ::Error
@ Error
Definition iq.h:49
gloox::IQ::Result
@ Result
Definition iq.h:48
gloox::JID
An abstraction of a JID.
Definition jid.h:31
gloox::SIHandler
An abstract base class to handle results of outgoing SI requests, i.e. you requested a stream (using ...
Definition sihandler.h:40
gloox::SIManager::SIManager
SIManager(ClientBase *parent, bool advertise=true)
Definition simanager.cpp:89
gloox::SIManager::~SIManager
virtual ~SIManager()
Definition simanager.cpp:101
gloox::SIManager::handleIqID
virtual void handleIqID(const IQ &iq, int context)
Definition simanager.cpp:213
gloox::SIManager::handleIq
virtual bool handleIq(const IQ &iq)
Definition simanager.cpp:193
gloox::SIManager::acceptSI
void acceptSI(const JID &to, const std::string &id, Tag *child1, Tag *child2=0, const JID &from=JID())
Definition simanager.cpp:137
gloox::SIManager::registerProfile
void registerProfile(const std::string &profile, SIProfileHandler *sih)
Definition simanager.cpp:171
gloox::SIManager::declineSI
void declineSI(const JID &to, const std::string &id, SIError reason, const std::string &text=EmptyString)
Definition simanager.cpp:147
gloox::SIManager::removeProfile
void removeProfile(const std::string &profile)
Definition simanager.cpp:182
gloox::SIManager::requestSI
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
gloox::SIManager::SIError
SIError
Definition simanager.h:42
gloox::SIManager::NoValidStreams
@ NoValidStreams
Definition simanager.h:43
gloox::SIManager::BadProfile
@ BadProfile
Definition simanager.h:44
gloox::SIProfileHandler
An abstract base class to handle SI requests for a specific profile, e.g. file transfer.
Definition siprofilehandler.h:38
gloox::StanzaExtension
This class abstracts a stanza extension, which is usually an XML child element in a specific namespac...
Definition stanzaextension.h:204
gloox::StanzaExtension::clone
virtual StanzaExtension * clone() const =0
gloox::Stanza::addExtension
void addExtension(const StanzaExtension *se)
Definition stanza.cpp:52
gloox::Stanza::setFrom
void setFrom(const JID &from)
Definition stanza.h:45
gloox::Stanza::id
const std::string & id() const
Definition stanza.h:63
gloox::Stanza::from
const JID & from() const
Definition stanza.h:51
gloox::Stanza::to
const JID & to() const
Definition stanza.h:57
gloox::Stanza::findExtension
const StanzaExtension * findExtension(int type) const
Definition stanza.cpp:57
gloox::Tag
This is an abstraction of an XML element.
Definition tag.h:47
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::EmptyString
const std::string EmptyString
Definition gloox.cpp:124
gloox::XMLNS
const std::string XMLNS
Definition gloox.cpp:122
gloox::StanzaErrorForbidden
@ StanzaErrorForbidden
Definition gloox.h:884
gloox::StanzaErrorBadRequest
@ StanzaErrorBadRequest
Definition gloox.h:874
gloox::XMLNS_SI
const std::string XMLNS_SI
Definition gloox.cpp:63
gloox::StanzaErrorTypeCancel
@ StanzaErrorTypeCancel
Definition gloox.h:859
gloox::ExtSI
@ ExtSI
Definition stanzaextension.h:82