2 gwclientstream.cpp - Kopete Groupwise Protocol
4 Copyright (c) 2006 Novell, Inc http://www.opensuse.org
5 Copyright (c) 2004 SUSE Linux AG http://www.suse.com
7 Based on Iris, Copyright (C) 2003 Justin Karneges <justin@affinix.com>
8 encode_method from Gaim src/protocols/novell/nmconn.c
9 Copyright (c) 2004 Novell, Inc. All Rights Reserved
11 Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
13 *************************************************************************
15 * This library is free software; you can redistribute it and/or *
16 * modify it under the terms of the GNU Lesser General Public *
17 * License as published by the Free Software Foundation; either *
18 * version 2 of the License, or (at your option) any later version. *
20 *************************************************************************
23 //#include<qtextstream.h>
24 //#include<qguardedptr.h>
27 // #include"bytestream.h"
30 // #include"simplesasl.h"
31 // #include"securestream.h"
32 // #include"protocol.h"
34 #include <qapplication.h> // for qdebug
42 #include "bytestream.h"
43 #include "connector.h"
44 #include "coreprotocol.h"
46 #include "securestream.h"
47 #include "tlshandler.h"
49 //#include "iostream.h"
51 #include "gwclientstream.h"
53 //#define LIBGW_DEBUG 1
55 void cs_dump( const QByteArray
&bytes
);
72 class ClientStream::Private
86 haveLocalAddr
= false;
108 bool allowPlain
, mutualAuth
;
110 QHostAddress localAddr
;
112 // int minimumSSF, maximumSSF;
113 // QString sasl_mech;
120 TLSHandler
*tlsHandler
;
134 bool tls_warned
, using_tls
;
137 // QStringList sasl_mechlist;
142 QQueue
<Transfer
*> in
;
144 QTimer noopTimer
; // probably not needed
148 ClientStream::ClientStream(Connector
*conn
, TLSHandler
*tlsHandler
, QObject
*parent
)
149 :Stream(parent
), d(new Private())
153 connect( d
->conn
, SIGNAL(connected()), SLOT(cr_connected()) );
154 connect( d
->conn
, SIGNAL(error()), SLOT(cr_error()) );
155 connect( &d
->client
, SIGNAL( outgoingData( const QByteArray
& ) ), SLOT ( cp_outgoingData( const QByteArray
& ) ) );
156 connect( &d
->client
, SIGNAL( incomingData() ), SLOT ( cp_incomingData() ) );
159 connect(&d
->noopTimer
, SIGNAL(timeout()), SLOT(doNoop()));
161 d
->tlsHandler
= tlsHandler
; // all the extra stuff happening in the larger ctor happens at connect time :)
164 ClientStream::~ClientStream()
170 void ClientStream::reset(bool all
)
175 // delete securestream
184 if(d
->mode
== Client
) {
187 d
->tlsHandler
->reset();
196 // reset state machine
200 while (!d
->in
.isEmpty())
201 delete d
->in
.dequeue();
204 // Jid ClientStream::jid() const
209 void ClientStream::connectToServer(const NovellDN
&id
, bool auth
)
212 d
->state
= Connecting
;
215 d
->server
= d
->id
.server
;
217 d
->conn
->connectToServer( d
->server
);
220 void ClientStream::continueAfterWarning()
222 if(d
->state
== WaitVersion
) {
223 // if we don't have TLS yet, then we're never going to get it
224 if(!d
->tls_warned
&& !d
->using_tls
) {
225 d
->tls_warned
= true;
227 emit
warning(WarnNoTLS
);
230 d
->state
= Connecting
;
233 else if(d
->state
== WaitTLS
) {
234 d
->state
= Connecting
;
239 void ClientStream::accept()
241 /* d->srv.host = d->server;
245 bool ClientStream::isActive() const
247 return (d
->state
!= Idle
);
250 bool ClientStream::isAuthenticated() const
252 return (d
->state
== Active
);
255 // void ClientStream::setPassword(const QString &s)
257 // if(d->client.old) {
258 // d->client.setPassword(s);
262 // d->sasl->setPassword(s);
266 // void ClientStream::setRealm(const QString &s)
269 // d->sasl->setRealm(s);
272 void ClientStream::continueAfterParams()
274 /* if(d->state == NeedParams) {
275 d->state = Connecting;
281 d->sasl->continueAfterParams();
286 void ClientStream::setNoopTime(int mills
)
288 d
->noop_time
= mills
;
290 if(d
->state
!= Active
)
293 if(d
->noop_time
== 0) {
297 d
->noopTimer
.start(d
->noop_time
);
300 void ClientStream::setLocalAddr(const QHostAddress
&addr
, quint16 port
)
302 d
->haveLocalAddr
= true;
307 int ClientStream::errorCondition() const
312 QString
ClientStream::errorText() const
317 // QDomElement ClientStream::errorAppSpec() const
319 // return d->errAppSpec;cr_error
322 // bool ClientStream::old() const
324 // return d->client.old;
327 void ClientStream::close()
329 if(d
->state
== Active
) {
331 // d->client.shutdown();
334 else if(d
->state
!= Idle
&& d
->state
!= Closing
) {
339 void ClientStream::setAllowPlain(bool b
)
344 void ClientStream::setRequireMutualAuth(bool b
)
349 // void ClientStream::setSSFRange(int low, int high)
351 // d->minimumSSF = low;
352 // d->maximumSSF = high;
355 // void ClientStream::setOldOnly(bool b)
360 bool ClientStream::transfersAvailable() const
362 return ( !d
->in
.isEmpty() );
365 Transfer
* ClientStream::read()
368 return 0; //first from queue...
370 return d
->in
.dequeue();
373 void ClientStream::write( Request
*request
)
375 // pass to CoreProtocol for transformation into wire format
376 d
->client
.outgoingTransfer( request
);
379 void cs_dump( const QByteArray
&bytes
)
381 //#define GW_CLIENTSTREAM_DEBUG 1
382 #ifdef GW_CLIENTSTREAM_DEBUG
383 CoreProtocol::debug( QString( "contains: %1 bytes " ).arg( bytes
.count() ) );
385 while ( count
< bytes
.count() )
388 for ( int i
= 0; i
< 8; ++i
)
390 if ( count
+ i
< bytes
.count() )
391 printf( "%02x ", bytes
[ count
+ i
] );
399 for ( int i
= 0; i
< 8; ++i
)
401 if ( count
+ i
< bytes
.count() )
403 int j
= bytes
[ count
+ i
];
404 if ( j
>= 0x20 && j
<= 0x7e )
407 printf( "%2c ", '.' );
423 void ClientStream::cp_outgoingData( const QByteArray
& outgoingBytes
)
425 // take formatted bytes from CoreProtocol and put them on the wire
427 CoreProtocol::debug( "ClientStream::cp_outgoingData:" );
428 cs_dump( outgoingBytes
);
430 d
->ss
->write( outgoingBytes
);
433 void ClientStream::cp_incomingData()
435 CoreProtocol::debug( "ClientStream::cp_incomingData:" );
436 Transfer
* incoming
= d
->client
.incomingTransfer();
439 CoreProtocol::debug( " - got a new transfer" );
440 d
->in
.enqueue( incoming
);
441 d
->newTransfers
= true;
445 CoreProtocol::debug( QString( " - client signalled incomingData but none was available, state is: %1" ).arg( d
->client
.state() ) );
448 void ClientStream::cr_connected()
450 d
->bs
= d
->conn
->stream();
451 connect(d
->bs
, SIGNAL(connectionClosed()), SLOT(bs_connectionClosed()));
452 connect(d
->bs
, SIGNAL(delayedCloseFinished()), SLOT(bs_delayedCloseFinished()));
454 QByteArray spare
= d
->bs
->read();
456 d
->ss
= new SecureStream(d
->bs
);
457 connect(d
->ss
, SIGNAL(readyRead()), SLOT(ss_readyRead()));
458 connect(d
->ss
, SIGNAL(bytesWritten(int)), SLOT(ss_bytesWritten(int)));
459 connect(d
->ss
, SIGNAL(tlsHandshaken()), SLOT(ss_tlsHandshaken()));
460 connect(d
->ss
, SIGNAL(tlsClosed()), SLOT(ss_tlsClosed()));
461 connect(d
->ss
, SIGNAL(error(int)), SLOT(ss_error(int)));
463 //d->client.startDialbackOut("andbit.net", "im.pyxa.org");
464 //d->client.startServerOut(d->server);
466 // d->client.startClientOut(d->jid, d->oldOnly, d->conn->useSSL(), d->doAuth);
467 // d->client.setAllowTLS(d->tlsHandler ? true: false);
468 // d->client.setAllowBind(d->doBinding);
469 // d->client.setAllowPlain(d->allowPlain);
471 /*d->client.jid = d->jid;
472 d->client.server = d->server;
473 d->client.allowPlain = d->allowPlain;
474 d->client.oldOnly = d->oldOnly;
475 d->client.sasl_mech = d->sasl_mech;
476 d->client.doTLS = d->tlsHandler ? true: false;
477 d->client.doBinding = d->doBinding;*/
479 QPointer
<QObject
> self
= this;
485 if(d
->conn
->useSSL()) {
486 CoreProtocol::debug( "CLIENTSTREAM: cr_connected(), starting TLS" );
488 d
->ss
->startTLSClient(d
->tlsHandler
, d
->server
, spare
);
491 /* d->client.addIncomingData(spare);
496 void ClientStream::cr_error()
499 emit
error(ErrConnection
);
502 void ClientStream::bs_connectionClosed()
505 emit
connectionClosed();
508 void ClientStream::bs_delayedCloseFinished()
510 // we don't care about this (we track all important data ourself)
513 void ClientStream::bs_error(int)
518 void ClientStream::ss_readyRead()
524 QByteArray
cs(a
.data(), a
.size()+1);
525 CoreProtocol::debug( QString( "ClientStream: ss_readyRead() recv: %1 bytes" ).arg( a
.size() ) );
529 d
->client
.addIncomingData(a
);
530 /* if(d->notify & CoreProtocol::NRecv) { */
534 void ClientStream::ss_bytesWritten(int bytes
)
537 CoreProtocol::debug( QString( "ClientStream::ss_bytesWritten: %1 bytes written" ).arg( bytes
) );
543 void ClientStream::ss_tlsHandshaken()
545 QPointer
<QObject
> self
= this;
546 emit
securityLayerActivated(LayerTLS
);
552 void ClientStream::ss_tlsClosed()
554 CoreProtocol::debug( "ClientStream::ss_tlsClosed()" );
556 emit
connectionClosed();
559 void ClientStream::ss_error(int x
)
561 CoreProtocol::debug( QString( "ClientStream::ss_error() x=%1 ").arg( x
) );
562 if(x
== SecureStream::ErrTLS
) {
564 d
->errCond
= TLSFail
;
569 emit
error(ErrSecurityLayer
);
573 void ClientStream::srvProcessNext()
577 void ClientStream::doReadyRead()
579 //QPointer<QObject> self = this;
583 //d->in_rrsig = false;
586 void ClientStream::processNext()
588 if( !d
->in
.isEmpty() ) {
589 //d->in_rrsig = true;
590 QTimer::singleShot(0, this, SLOT(doReadyRead()));
594 bool ClientStream::handleNeed()
600 void ClientStream::doNoop()
604 void ClientStream::handleError()
608 #include "gwclientstream.moc"