gloox  0.9.9.12
inbandbytestreammanager.cpp
1 /*
2  Copyright (c) 2006-2008 by Jakob Schroeter <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 "inbandbytestreammanager.h"
15 #include "inbandbytestreamhandler.h"
16 #include "inbandbytestream.h"
17 #include "clientbase.h"
18 #include "disco.h"
19 
20 namespace gloox
21 {
22 
24  : m_parent( parent ), m_inbandBytestreamHandler( 0 ), m_syncInbandBytestreams( true ),
25  m_blockSize( 4096 )
26  {
27  if( m_parent )
28  {
29  m_parent->registerIqHandler( this, XMLNS_IBB );
30  m_parent->disco()->addFeature( XMLNS_IBB );
31  }
32  }
33 
35  {
36  if( m_parent )
37  {
38  m_parent->disco()->removeFeature( XMLNS_IBB );
39  m_parent->removeIqHandler( XMLNS_IBB );
40  m_parent->removeIDHandler( this );
41  }
42 
43  IBBMap::iterator it = m_ibbMap.begin();
44  for( ; it != m_ibbMap.end(); ++it )
45  {
46  delete (*it).second;
47  }
48  }
49 
51  const std::string& sid )
52  {
53  if( !m_parent || !ibbh )
54  return false;
55 
56  const std::string& msid = sid.empty() ? m_parent->getID() : sid;
57  const std::string& id = m_parent->getID();
58  Tag *iq = new Tag( "iq" );
59  iq->addAttribute( "type", "set" );
60  iq->addAttribute( "to", to.full() );
61  iq->addAttribute( "id", id );
62  Tag *o = new Tag( iq, "open" );
63  o->addAttribute( "sid", msid );
64  o->addAttribute( "block-size", m_blockSize );
65  o->addAttribute( "xmlns", XMLNS_IBB );
66 
67  TrackItem item;
68  item.sid = msid;
69  item.ibbh = ibbh;
70  m_trackMap[id] = item;
71  m_parent->trackID( this, id, IBBOpenStream );
72  m_parent->send( iq );
73 
74  return true;
75  }
76 
78  {
79  Tag *o = 0;
80  if( ( stanza->subtype() == StanzaIqSet ) &&
81  ( ( o = stanza->findChild( "open", "xmlns", XMLNS_IBB ) ) != 0 ) )
82  {
83  InBandBytestream *ibb = new InBandBytestream( 0, m_parent );
84  const std::string& sid = o->findAttribute( "sid" );
85  ibb->setSid( sid );
86 
87  if( !m_inbandBytestreamHandler )
88  rejectInBandBytestream( ibb, stanza->from(), stanza->id() );
89 
90  if( !m_syncInbandBytestreams )
91  {
92  AsyncIBBItem item;
93  item.ibb = ibb;
94  item.from = stanza->from();
95  item.id = stanza->id();
96  m_asyncTrackMap[sid] = item;
97  }
98 
99  bool t = m_inbandBytestreamHandler->handleIncomingInBandBytestream( stanza->from(), ibb );
100  if( m_syncInbandBytestreams && t )
101  {
102  acceptInBandBytestream( ibb, stanza->from(), stanza->id() );
103  }
104  else if( m_syncInbandBytestreams && !t )
105  {
106  rejectInBandBytestream( ibb, stanza->from(), stanza->id() );
107  }
108  }
109  else if( ( stanza->subtype() == StanzaIqSet ) &&
110  ( ( o = stanza->findChild( "close", "xmlns", XMLNS_IBB ) ) != 0 ) &&
111  o->hasAttribute( "sid" ) )
112  {
113  IBBMap::iterator it = m_ibbMap.find( o->findAttribute( "sid" ) );
114  if( it != m_ibbMap.end() )
115  {
116  (*it).second->closed();
117 
118  Tag *iq = new Tag( "iq" );
119  iq->addAttribute( "type", "result" );
120  iq->addAttribute( "to", stanza->from().full() );
121  iq->addAttribute( "id", stanza->id() );
122 
123  m_parent->send( iq );
124  }
125  }
126  else
127  {
128  return false;
129  }
130 
131  return true;
132  }
133 
135  {
136  if( m_syncInbandBytestreams )
137  return;
138 
139  AsyncTrackMap::iterator it = m_asyncTrackMap.find( ibb->sid() );
140  if( it != m_asyncTrackMap.end() )
141  {
142  acceptInBandBytestream( ibb, (*it).second.from, (*it).second.id );
143  m_asyncTrackMap.erase( it );
144  }
145  }
146 
148  {
149  if( m_syncInbandBytestreams )
150  return;
151 
152  AsyncTrackMap::iterator it = m_asyncTrackMap.find( ibb->sid() );
153  if( it != m_asyncTrackMap.end() )
154  {
155  rejectInBandBytestream( ibb, (*it).second.from, (*it).second.id );
156  m_asyncTrackMap.erase( it );
157  }
158  }
159 
161  const JID& from, const std::string& id )
162  {
163  m_ibbMap[ibb->sid()] = ibb;
164  Tag *iq = new Tag( "iq" );
165  iq->addAttribute( "type", "result" );
166  iq->addAttribute( "to", from.full() );
167  iq->addAttribute( "id", id );
168  m_parent->send( iq );
169  }
170 
171  void InBandBytestreamManager::rejectInBandBytestream( InBandBytestream *ibb,
172  const JID& from, const std::string& id )
173  {
174  delete ibb;
175  Tag *iq = new Tag( "iq" );
176  iq->addAttribute( "type", "error" );
177  iq->addAttribute( "to", from.full() );
178  iq->addAttribute( "id", id );
179  Tag *e = new Tag( iq, "error" );
180  e->addAttribute( "code", "501" );
181  e->addAttribute( "type", "cancel" );
182  Tag *f = new Tag( e, "feature-not-implemented" );
183  f->addAttribute( "xmlns", XMLNS_XMPP_STANZAS );
184  m_parent->send( iq );
185  }
186 
187  bool InBandBytestreamManager::handleIqID( Stanza *stanza, int context )
188  {
189  switch( context )
190  {
191  case IBBOpenStream:
192  {
193  TrackMap::iterator it = m_trackMap.find( stanza->id() );
194  if( it != m_trackMap.end() )
195  {
196  switch( stanza->subtype() )
197  {
198  case StanzaIqResult:
199  {
200  InBandBytestream *ibb = new InBandBytestream( 0, m_parent );
201  ibb->setSid( (*it).second.sid );
202  ibb->setBlockSize( m_blockSize );
203  m_ibbMap[(*it).second.sid] = ibb;
204  InBandBytestreamHandler *t = (*it).second.ibbh;
205  t->handleOutgoingInBandBytestream( stanza->from(), ibb );
206  break;
207  }
208  case StanzaIqError:
209  (*it).second.ibbh->handleInBandBytestreamError( stanza->from(), stanza->error() );
210  break;
211  default:
212  break;
213  }
214  m_trackMap.erase( it );
215  }
216  break;
217  }
218  default:
219  break;
220  }
221 
222  return false;
223  }
224 
226  {
227  IBBMap::iterator it = m_ibbMap.find( ibb->sid() );
228  if( it != m_ibbMap.end() )
229  {
230  delete ibb;
231  m_ibbMap.erase( it );
232  return true;
233  }
234 
235  return false;
236  }
237 
239  bool sync )
240  {
241  m_inbandBytestreamHandler = ibbh;
242  m_syncInbandBytestreams = sync;
243  }
244 
246  {
247  m_inbandBytestreamHandler = 0;
248  }
249 
250 }