gloox 1.0

simanager.cpp

00001 /*
00002   Copyright (c) 2007-2009 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 #include "simanager.h"
00015 
00016 #include "siprofilehandler.h"
00017 #include "sihandler.h"
00018 #include "clientbase.h"
00019 #include "disco.h"
00020 #include "error.h"
00021 
00022 namespace gloox
00023 {
00024 
00025   // ---- SIManager::SI ----
00026   SIManager::SI::SI( const Tag* tag )
00027     : StanzaExtension( ExtSI ), m_tag1( 0 ), m_tag2( 0 )
00028   {
00029     if( !tag || tag->name() != "si" || tag->xmlns() != XMLNS_SI )
00030       return;
00031 
00032     m_valid = true;
00033 
00034     m_id = tag->findAttribute( "id" );
00035     m_mimetype = tag->findAttribute( "mime-type" );
00036     m_profile = tag->findAttribute( "profile" );
00037 
00038     Tag* c = tag->findChild( "file", "xmlns", XMLNS_SI_FT );
00039     if ( c )
00040       m_tag1 = c->clone();
00041     c = tag->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
00042     if( c )
00043       m_tag2 = c->clone();
00044   }
00045 
00046   SIManager::SI::SI( Tag* tag1, Tag* tag2, const std::string& id,
00047                      const std::string& mimetype, const std::string& profile )
00048     : StanzaExtension( ExtSI ), m_tag1( tag1 ), m_tag2( tag2 ),
00049       m_id( id ), m_mimetype( mimetype ), m_profile( profile )
00050   {
00051     m_valid = true;
00052   }
00053 
00054   SIManager::SI::~SI()
00055   {
00056     delete m_tag1;
00057     delete m_tag2;
00058   }
00059 
00060   const std::string& SIManager::SI::filterString() const
00061   {
00062     static const std::string filter = "/iq/si[@xmlns='" + XMLNS_SI + "']";
00063     return filter;
00064   }
00065 
00066   Tag* SIManager::SI::tag() const
00067   {
00068     if( !m_valid )
00069       return 0;
00070 
00071     Tag* t = new Tag( "si" );
00072     t->setXmlns( XMLNS_SI );
00073     if( !m_id.empty() )
00074       t->addAttribute( "id", m_id );
00075     if( !m_mimetype.empty() )
00076       t->addAttribute( "mime-type", m_mimetype.empty() ? "binary/octet-stream" : m_mimetype );
00077     if( !m_profile.empty() )
00078       t->addAttribute( "profile", m_profile );
00079     if( m_tag1 )
00080       t->addChildCopy( m_tag1 );
00081     if( m_tag2 )
00082       t->addChildCopy( m_tag2 );
00083 
00084     return t;
00085   }
00086   // ---- ~SIManager::SI ----
00087 
00088   // ---- SIManager ----
00089   SIManager::SIManager( ClientBase* parent, bool advertise )
00090     : m_parent( parent ), m_advertise( advertise )
00091   {
00092     if( m_parent )
00093     {
00094       m_parent->registerStanzaExtension( new SI() );
00095       m_parent->registerIqHandler( this, ExtSI );
00096       if( m_parent->disco() && m_advertise )
00097         m_parent->disco()->addFeature( XMLNS_SI );
00098     }
00099   }
00100 
00101   SIManager::~SIManager()
00102   {
00103     if( m_parent )
00104     {
00105       m_parent->removeIqHandler( this, ExtSI );
00106       m_parent->removeIDHandler( this );
00107       if( m_parent->disco() && m_advertise )
00108         m_parent->disco()->removeFeature( XMLNS_SI );
00109     }
00110   }
00111 
00112   const std::string SIManager::requestSI( SIHandler* sih, const JID& to, const std::string& profile,
00113                                           Tag* child1, Tag* child2, const std::string& mimetype,
00114                                           const JID& from, const std::string& sid )
00115   {
00116     if( !m_parent || !sih )
00117       return EmptyString;
00118 
00119     const std::string& id = m_parent->getID();
00120     const std::string& sidToUse = sid.empty() ? m_parent->getID() : sid;
00121 
00122     IQ iq( IQ::Set, to, id );
00123     iq.addExtension( new SI( child1, child2, sidToUse, mimetype, profile ) );
00124     if( from )
00125       iq.setFrom( from );
00126 
00127     TrackStruct t;
00128     t.sid = sidToUse;
00129     t.profile = profile;
00130     t.sih = sih;
00131     m_track[id] = t;
00132     m_parent->send( iq, this, OfferSI );
00133 
00134     return sidToUse;
00135   }
00136 
00137   void SIManager::acceptSI( const JID& to, const std::string& id, Tag* child1, Tag* child2, const JID& from )
00138   {
00139     IQ iq( IQ::Result, to, id );
00140     iq.addExtension( new SI( child1, child2 ) );
00141     if( from )
00142       iq.setFrom( from );
00143 
00144     m_parent->send( iq );
00145   }
00146 
00147   void SIManager::declineSI( const JID& to, const std::string& id, SIError reason, const std::string& text )
00148   {
00149     IQ iq( IQ::Error, to, id );
00150     Error* error;
00151     if( reason == NoValidStreams || reason == BadProfile )
00152     {
00153       Tag* appError = 0;
00154       if( reason == NoValidStreams )
00155         appError = new Tag( "no-valid-streams", XMLNS, XMLNS_SI );
00156       else if( reason == BadProfile )
00157         appError = new Tag( "bad-profile", XMLNS, XMLNS_SI );
00158       error = new Error( StanzaErrorTypeCancel, StanzaErrorBadRequest, appError );
00159     }
00160     else
00161     {
00162       error = new Error( StanzaErrorTypeCancel, StanzaErrorForbidden );
00163       if( !text.empty() )
00164         error->text( text );
00165     }
00166 
00167     iq.addExtension( error );
00168     m_parent->send( iq );
00169   }
00170 
00171   void SIManager::registerProfile( const std::string& profile, SIProfileHandler* sih )
00172   {
00173     if( !sih || profile.empty() )
00174       return;
00175 
00176     m_handlers[profile] = sih;
00177 
00178     if( m_parent && m_advertise && m_parent->disco() )
00179       m_parent->disco()->addFeature( profile );
00180   }
00181 
00182   void SIManager::removeProfile( const std::string& profile )
00183   {
00184     if( profile.empty() )
00185       return;
00186 
00187     m_handlers.erase( profile );
00188 
00189     if( m_parent && m_advertise && m_parent->disco() )
00190       m_parent->disco()->removeFeature( profile );
00191   }
00192 
00193   bool SIManager::handleIq( const IQ& iq )
00194   {
00195     TrackMap::iterator itt = m_track.find( iq.id() );
00196     if( itt != m_track.end() )
00197       return false;
00198 
00199     const SI* si = iq.findExtension<SI>( ExtSI );
00200     if( !si || si->profile().empty() )
00201       return false;
00202 
00203     HandlerMap::const_iterator it = m_handlers.find( si->profile() );
00204     if( it != m_handlers.end() && (*it).second )
00205     {
00206       (*it).second->handleSIRequest( iq.from(), iq.to(), iq.id(), *si );
00207       return true;
00208     }
00209 
00210     return false;
00211   }
00212 
00213   void SIManager::handleIqID( const IQ& iq, int context )
00214   {
00215     switch( iq.subtype() )
00216     {
00217       case IQ::Result:
00218         if( context == OfferSI )
00219         {
00220           TrackMap::iterator it = m_track.find( iq.id() );
00221           if( it != m_track.end() )
00222           {
00223             const SI* si = iq.findExtension<SI>( ExtSI );
00224             if( !si /*|| si->profile().empty()*/ )
00225               return;
00226 
00227 //             Tag* si = iq.query();
00228 //             Tag* ptag = 0;
00229 //             Tag* fneg = 0;
00230 //             if( si && si->name() == "si" && si->xmlns() == XMLNS_SI )
00231 //             {
00232 //               ptag = si->findChildWithAttrib( XMLNS, (*it).second.profile );
00233 //               fneg = si->findChild( "feature", XMLNS, XMLNS_FEATURE_NEG );
00234 //             }
00235 
00236             // FIXME: remove above commented code and
00237             // check corectness of last 3 params!
00238             (*it).second.sih->handleSIRequestResult( iq.from(), iq.to(), (*it).second.sid, *si );
00239             m_track.erase( it );
00240           }
00241         }
00242         break;
00243       case IQ::Error:
00244         if( context == OfferSI )
00245         {
00246           TrackMap::iterator it = m_track.find( iq.id() );
00247           if( it != m_track.end() )
00248           {
00249             (*it).second.sih->handleSIRequestError( iq, (*it).second.sid );
00250             m_track.erase( it );
00251           }
00252         }
00253         break;
00254       default:
00255         break;
00256     }
00257   }
00258 
00259 }