15 #include "authenticationhandler.h"
17 #include "configmanager.h"
18 #include "streambase.h"
19 #include "streamfeature.h"
21 #include <gloox/adhoc.h>
22 #include <gloox/base64.h>
23 #include <gloox/connectionbase.h>
24 #include <gloox/connectiontls.h>
25 #include <gloox/dataform.h>
26 #include <gloox/dataformfield.h>
28 #include <gloox/jid.h>
29 #include <gloox/logsink.h>
30 #include <gloox/sha.h>
31 #include <gloox/tlsbase.h>
32 #include <gloox/util.h>
41 static const char* streamErrorValues[] = {
43 "bad-namespace-prefix",
48 "improper-addressing",
49 "internal-server-error",
56 "remote-connection-failed",
57 "resource-constraint",
61 "undefined-condition",
62 "unsupported-encoding",
63 "unsupported-stanza-type",
64 "unsupported-version",
68 static inline const std::string streamErrorValue( gloox::StreamError se )
70 return gloox::util::lookup( se, streamErrorValues );
74 const gloox::LogSink& log )
75 : m_parent( parent ), m_cm( cm ),
76 m_connection( conn ), m_logInstance( log ),
77 m_parser( this, false ), m_exclusiveHandler( 0 ),
78 m_threading( false ), m_fakePresence( true ), m_strictXMPP( true )
83 sha.feed( m_connection->server() );
84 sha.feed( gloox::util::int2string( m_connection->port() ) );
85 sha.feed( gloox::util::int2string( time( 0 ) ) );
88 m_connection->registerConnectionDataHandler(
this );
90 "Assigning ID: " + m_id );
98 printf(
"in ~StreamBase\n" );
100 gloox::util::clearList( m_features );
101 gloox::util::clearList( m_incomingQueue );
102 gloox::util::clearList( m_outgoingQueue );
103 printf(
"leaving ~StreamBase\n" );
108 if( !m_threading && !m_incomingQueue.size()
109 && !m_outgoingQueue.size() )
114 m_queueSemaphore.
wait();
115 if( m_incomingQueue.size() )
117 gloox::Tag* t = m_incomingQueue.front();
118 m_incomingQueueMutex.lock();
119 m_incomingQueue.pop_front();
120 m_incomingQueueMutex.unlock();
123 else if( m_outgoingQueue.size() )
125 gloox::Tag* t = m_outgoingQueue.front();
126 m_outgoingQueueMutex.lock();
127 m_outgoingQueue.pop_front();
128 m_outgoingQueueMutex.unlock();
131 }
while( m_threading );
137 return m_connection->recv( timeout );
139 return gloox::ConnNotConnected;
143 gloox::StreamError se,
144 const std::string& text )
146 if( m_fakePresence && !m_self.resource().empty() )
148 gloox::Tag* b =
new gloox::Tag(
"presence" );
149 b->addAttribute(
"type",
"unavailable" );
153 if( se != gloox::StreamErrorUndefined )
158 st =
new gloox::Tag(
"stream" );
159 st->setPrefix(
"stream" );
160 st->setXmlns( gloox::XMLNS_STREAM,
"stream" );
161 st->addAttribute(
"version",
"1.0" );
163 gloox::Tag* s =
new gloox::Tag( st,
"error" );
164 s->setPrefix(
"stream" );
165 gloox::Tag* err =
new gloox::Tag( s, streamErrorValue( se ) );
166 err->setXmlns( gloox::XMLNS_XMPP_STREAM );
169 gloox::Tag* txt =
new gloox::Tag( err,
"text", text );
170 txt->setXmlns( gloox::XMLNS_XMPP_STREAM );
177 send(
"</stream:stream>" );
182 printf(
"disconnecting with reason %d\n", e );
184 int oldState = m_state;
189 m_connection->disconnect();
191 m_parent.disconnect(
this );
197 void StreamBase::handleReceivedData(
const gloox::ConnectionBase* ,
const std::string& data )
202 std::string copy = data;
204 if( ( i = m_parser.feed( copy ) ) >= 0 )
207 "parse error (at pos "
208 + gloox::util::int2string( i )
209 +
"): " + copy.c_str() );
210 disconnect( gloox::ConnParseError, gloox::StreamErrorXmlNotWellFormed,
"syntax error" );
233 m_logInstance.dbg( gloox::LogAreaXmlOutgoing, xml );
234 m_connection->send( xml );
238 gloox::ConnectionBase* conn )
242 m_exclusiveHandler = 0;
249 gloox::JID j = m_parent.
name().bare();
250 j.setResource( m_id );
254 void StreamBase::handleConnect(
const gloox::ConnectionBase* )
257 printf(
"should not happen\n" );
261 void StreamBase::handleDisconnect(
const gloox::ConnectionBase* , gloox::ConnectionError )
264 printf(
"detected disconnect\n" );
274 if( tag->name() ==
"disconnect" && tag->xmlns() ==
XMLNS_GLOOXD )
277 static_cast<gloox::StreamError>( strtol( tag->cdata().c_str(), 0, 10 ) ) );
281 m_incomingQueueMutex.lock();
282 m_incomingQueue.push_back( tag );
283 m_incomingQueueMutex.unlock();
284 m_queueSemaphore.
post();
292 m_outgoingQueueMutex.lock();
293 m_outgoingQueue.push_back( tag );
294 m_outgoingQueueMutex.unlock();
295 m_queueSemaphore.
post();
298 void StreamBase::handleTag( gloox::Tag* tag )
309 m_logInstance.dbg( gloox::LogAreaXmlIncoming, tag->xml() );
317 if( m_exclusiveHandler )
319 m_exclusiveHandler->handleTag( tag );
324 const std::string tname = tag->name();
326 if( tname ==
"stream" && tag->xmlns() == gloox::XMLNS_STREAM )
329 printf(
"greeting\n" );
331 handleStreamGreeting( tag );
335 else if( ( m_state & StateReallyDone ) != StateReallyDone )
337 FeatureList::const_iterator it = m_features.begin();
338 for( ; it != m_features.end(); ++it )
340 if( tag->findTag( (*it)->filterString() ) )
342 m_exclusiveHandler = (*it);
343 (*it)->handleTag( tag );
349 if( ( m_state &
StateDone ) == StateDone )
352 m_connection->server(), m_connection->port() );
354 gloox::util::clearList( m_features );
358 disconnect( gloox::ConnStreamError, gloox::StreamErrorNotAuthorized );
364 const std::string type = tag->findAttribute( gloox::TYPE );
368 if( tname ==
"presence" && type ==
"unavailable" )
370 m_fakePresence =
false;
375 void StreamBase::handleStreamGreeting(
const gloox::Tag* tag )
380 const std::string& to = tag->findAttribute(
"to" );
384 disconnect( gloox::ConnStreamError, gloox::StreamErrorPolicyViolation );
388 if ( !tag->hasAttribute(
"version",
"1.0" ) )
393 "StrictXMPP: Stream " + m_id +
" does not send 'version' attribute."
394 " Disconnecting. See C2S::setStrictXMPP()." );
395 disconnect( gloox::ConnStreamError, gloox::StreamErrorUnsupportedVersion,
396 "This server mandates XMPP version 1.0 which your client does not seem to support." );
402 "StrictXMPP: Stream " + m_id +
" does not send 'version' attribute."
403 " Ignoring. See C2S::setStrictXMPP()." );
409 if( !m_cm.
checkDomain( to, m_connection->localInterface(),
410 m_connection->localPort() ) )
412 disconnect( gloox::ConnStreamError, gloox::StreamErrorHostUnknown );
416 else if( m_self.server() != to )
418 disconnect( gloox::ConnStreamError, gloox::StreamErrorHostUnknown );
422 m_self.setServer( to );
424 m_state &= ~StateReset;
426 std::string reply =
"<stream:stream xmlns:stream='";
427 reply += gloox::XMLNS_STREAM;
428 reply +=
"' xmlns='";
429 reply += gloox::XMLNS_CLIENT;
432 reply +=
"' version='1.0' id='glooxd001'>";
435 gloox::Tag* f =
new gloox::Tag(
"features" );
436 f->setPrefix(
"stream" );
437 f->setXmlns( gloox::XMLNS_STREAM,
"stream" );
439 FeatureList::const_iterator it = m_features.begin();
440 for( ; it != m_features.end(); ++it )
441 f->addChild( (*it)->tag( m_state, to ) );
451 if( !tag->hasAttribute(
"from" )
452 || tag->findAttribute(
"from") != m_self.full() )
453 tag->addAttribute(
"from", m_self.full() );
463 m_parent.handleIncomingTag( tag );