gloox  0.9.9.12
inbandbytestream.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 "inbandbytestream.h"
15 #include "inbandbytestreamdatahandler.h"
16 #include "messagesession.h"
17 #include "disco.h"
18 #include "clientbase.h"
19 #include "base64.h"
20 
21 #include <sstream>
22 
23 namespace gloox
24 {
25 
26  InBandBytestream::InBandBytestream( MessageSession *session, ClientBase *clientbase )
27  : MessageFilter( session ), m_clientbase( clientbase ),
28  m_inbandBytestreamDataHandler( 0 ), m_blockSize( 4096 ), m_sequence( -1 ),
29  m_lastChunkReceived( -1 ), m_open( true )
30  {
31  }
32 
34  {
35  if( m_open )
36  close();
37 
38  if( m_parent )
39  m_parent->removeMessageFilter( this );
40  }
41 
42  void InBandBytestream::decorate( Tag * /*tag*/ )
43  {
44  }
45 
47  {
48  if( !m_inbandBytestreamDataHandler || !m_open )
49  return;
50 
51  if( stanza->subtype() == StanzaMessageError )
52  {
53  m_inbandBytestreamDataHandler->handleInBandError( m_sid, stanza->from(), stanza->error() );
54  m_open = false;
55  }
56 
57  Tag *data = 0;
58  if( ( data = stanza->findChild( "data", "xmlns", XMLNS_IBB ) ) == 0 )
59  return;
60 
61  const std::string& sid = data->findAttribute( "sid" );
62  if( sid.empty() || sid != m_sid )
63  return;
64 
65  const std::string& seq = data->findAttribute( "seq" );
66  if( seq.empty() )
67  {
68  m_open = false;
69  return;
70  }
71 
72  std::stringstream str;
73  int sequence = 0;
74  str << seq;
75  str >> sequence;
76 
77  if( m_lastChunkReceived + 1 != sequence )
78  {
79  m_open = false;
80  return;
81  }
82  m_lastChunkReceived = sequence;
83 
84  if( !data->cdata().length() )
85  {
86  m_open = false;
87  return;
88  }
89 
90  m_inbandBytestreamDataHandler->handleInBandData( Base64::decode64( data->cdata() ), sid );
91  }
92 
93  bool InBandBytestream::sendBlock( const std::string& data )
94  {
95  if( !m_open || !m_parent || !m_clientbase || data.length() > m_blockSize )
96  return false;
97 
98  Tag *m = new Tag( "message" );
99  m->addAttribute( "to", m_parent->target().full() );
100  m->addAttribute( "id", m_clientbase->getID() );
101  Tag *d = new Tag( m, "data", Base64::encode64( data ) );
102  d->addAttribute( "sid", m_sid );
103  d->addAttribute( "seq", ++m_sequence );
104  d->addAttribute( "xmlns", XMLNS_IBB );
105 
106  // FIXME: hard-coded AMP
107  Tag *a = new Tag( m, "amp" );
108  a->addAttribute( "xmlns", XMLNS_AMP );
109  Tag *r = new Tag( a, "rule" );
110  r->addAttribute( "condition", "deliver-at" );
111  r->addAttribute( "value", "stored" );
112  r->addAttribute( "action", "error" );
113  r = new Tag( a, "rule" );
114  r->addAttribute( "condition", "match-resource" );
115  r->addAttribute( "value", "exact" );
116  r->addAttribute( "action", "error" );
117 
118  m_clientbase->send( m );
119  return true;
120  }
121 
122  void InBandBytestream::closed()
123  {
124  m_open = false;
125 
126  if( m_inbandBytestreamDataHandler )
127  m_inbandBytestreamDataHandler->handleInBandClose( m_sid, m_parent->target() );
128  }
129 
130  void InBandBytestream::close()
131  {
132  m_open = false;
133 
134  if( !m_parent )
135  return;
136 
137  const std::string& id = m_clientbase->getID();
138  Tag *iq = new Tag( "iq" );
139  iq->addAttribute( "type", "set" );
140  iq->addAttribute( "to", m_parent->target().full() );
141  iq->addAttribute( "id", id );
142  Tag *c = new Tag( iq, "close" );
143  c->addAttribute( "sid", m_sid );
144  c->addAttribute( "xmlns", XMLNS_IBB );
145 
146  m_clientbase->send( iq );
147  }
148 
150  {
151  m_inbandBytestreamDataHandler = ibbdh;
152  }
153 
155  {
156  m_inbandBytestreamDataHandler = 0;
157  }
158 
159 }