summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp')
-rw-r--r--kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp606
1 files changed, 606 insertions, 0 deletions
diff --git a/kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp b/kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp
new file mode 100644
index 00000000..7d58de93
--- /dev/null
+++ b/kopete/protocols/groupwise/libgroupwise/gwclientstream.cpp
@@ -0,0 +1,606 @@
+/*
+ gwclientstream.cpp - Kopete Groupwise Protocol
+
+ Copyright (c) 2004 SUSE Linux AG http://www.suse.com
+
+ Based on Iris, Copyright (C) 2003 Justin Karneges
+ encode_method from Gaim src/protocols/novell/nmconn.c
+ Copyright (c) 2004 Novell, Inc. All Rights Reserved
+
+ Kopete (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
+
+ *************************************************************************
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ *************************************************************************
+*/
+
+//#include<qtextstream.h>
+//#include<qguardedptr.h>
+// #include<qca.h>
+// #include<stdlib.h>
+// #include"bytestream.h"
+// #include"base64.h"
+// #include"hash.h"
+// #include"simplesasl.h"
+// #include"securestream.h"
+// #include"protocol.h"
+
+#include <qapplication.h> // for qdebug
+#include <qguardedptr.h>
+#include <qobject.h>
+#include <qptrqueue.h>
+#include <qtimer.h>
+
+#include "bytestream.h"
+#include "connector.h"
+#include "coreprotocol.h"
+#include "request.h"
+#include "securestream.h"
+#include "tlshandler.h"
+
+//#include "iostream.h"
+
+#include "gwclientstream.h"
+
+//#define LIBGW_DEBUG 1
+
+void cs_dump( const QByteArray &bytes );
+
+enum {
+ Idle,
+ Connecting,
+ WaitVersion,
+ WaitTLS,
+ NeedParams,
+ Active,
+ Closing
+};
+
+enum {
+ Client,
+ Server
+};
+
+class ClientStream::Private
+{
+public:
+ Private()
+ {
+ conn = 0;
+ bs = 0;
+ ss = 0;
+ tlsHandler = 0;
+ tls = 0;
+// sasl = 0;
+ in.setAutoDelete(true);
+
+ allowPlain = false;
+ mutualAuth = false;
+ haveLocalAddr = false;
+/* minimumSSF = 0;
+ maximumSSF = 0;*/
+ doBinding = true;
+
+ in_rrsig = false;
+
+ reset();
+ }
+ void reset()
+ {
+ state = Idle;
+ notify = 0;
+ newTransfers = false;
+// sasl_ssf = 0;
+ tls_warned = false;
+ using_tls = false;
+ }
+
+ NovellDN id;
+ QString server;
+ bool oldOnly;
+ bool allowPlain, mutualAuth;
+ bool haveLocalAddr;
+ QHostAddress localAddr;
+ Q_UINT16 localPort;
+// int minimumSSF, maximumSSF;
+// QString sasl_mech;
+ bool doBinding;
+
+ bool in_rrsig;
+
+ Connector *conn;
+ ByteStream *bs;
+ TLSHandler *tlsHandler;
+ QCA::TLS *tls;
+// QCA::SASL *sasl;
+ SecureStream *ss;
+ CoreProtocol client;
+ //CoreProtocol srv;
+
+ QString defRealm;
+
+ int mode;
+ int state;
+ int notify;
+ bool newTransfers;
+// int sasl_ssf;
+ bool tls_warned, using_tls;
+ bool doAuth;
+
+// QStringList sasl_mechlist;
+
+ int errCond;
+ QString errText;
+
+ QPtrQueue<Transfer> in;
+
+ QTimer noopTimer; // probably not needed
+ int noop_time;
+};
+
+ClientStream::ClientStream(Connector *conn, TLSHandler *tlsHandler, QObject *parent)
+:Stream(parent)
+{
+ d = new Private;
+ d->mode = Client;
+ d->conn = conn;
+ connect( d->conn, SIGNAL(connected()), SLOT(cr_connected()) );
+ connect( d->conn, SIGNAL(error()), SLOT(cr_error()) );
+ connect( &d->client, SIGNAL( outgoingData( const QByteArray& ) ), SLOT ( cp_outgoingData( const QByteArray & ) ) );
+ connect( &d->client, SIGNAL( incomingData() ), SLOT ( cp_incomingData() ) );
+
+ d->noop_time = 0;
+ connect(&d->noopTimer, SIGNAL(timeout()), SLOT(doNoop()));
+
+ d->tlsHandler = tlsHandler; // all the extra stuff happening in the larger ctor happens at connect time :)
+}
+
+ClientStream::~ClientStream()
+{
+ reset();
+ delete d;
+}
+
+void ClientStream::reset(bool all)
+{
+ d->reset();
+ d->noopTimer.stop();
+
+ // delete securestream
+ delete d->ss;
+ d->ss = 0;
+
+ // reset sasl
+// delete d->sasl;
+// d->sasl = 0;
+
+ // client
+ if(d->mode == Client) {
+ // reset tls
+ if(d->tlsHandler)
+ d->tlsHandler->reset();
+
+ // reset connector
+ if(d->bs) {
+ d->bs->close();
+ d->bs = 0;
+ }
+ d->conn->done();
+
+ // reset state machine
+ d->client.reset();
+ }
+ if(all)
+ d->in.clear();
+}
+
+// Jid ClientStream::jid() const
+// {
+// return d->jid;
+// }
+
+void ClientStream::connectToServer(const NovellDN &id, bool auth)
+{
+ reset(true);
+ d->state = Connecting;
+ d->id = id;
+ d->doAuth = auth;
+ d->server = d->id.server;
+
+ d->conn->connectToServer( d->server );
+}
+
+void ClientStream::continueAfterWarning()
+{
+ if(d->state == WaitVersion) {
+ // if we don't have TLS yet, then we're never going to get it
+ if(!d->tls_warned && !d->using_tls) {
+ d->tls_warned = true;
+ d->state = WaitTLS;
+ emit warning(WarnNoTLS);
+ return;
+ }
+ d->state = Connecting;
+ processNext();
+ }
+ else if(d->state == WaitTLS) {
+ d->state = Connecting;
+ processNext();
+ }
+}
+
+void ClientStream::accept()
+{
+/* d->srv.host = d->server;
+ processNext();*/
+}
+
+bool ClientStream::isActive() const
+{
+ return (d->state != Idle);
+}
+
+bool ClientStream::isAuthenticated() const
+{
+ return (d->state == Active);
+}
+
+// void ClientStream::setPassword(const QString &s)
+// {
+// if(d->client.old) {
+// d->client.setPassword(s);
+// }
+// else {
+// if(d->sasl)
+// d->sasl->setPassword(s);
+// }
+// }
+
+// void ClientStream::setRealm(const QString &s)
+// {
+// if(d->sasl)
+// d->sasl->setRealm(s);
+// }
+
+void ClientStream::continueAfterParams()
+{
+/* if(d->state == NeedParams) {
+ d->state = Connecting;
+ if(d->client.old) {
+ processNext();
+ }
+ else {
+ if(d->sasl)
+ d->sasl->continueAfterParams();
+ }
+ }*/
+}
+
+void ClientStream::setNoopTime(int mills)
+{
+ d->noop_time = mills;
+
+ if(d->state != Active)
+ return;
+
+ if(d->noop_time == 0) {
+ d->noopTimer.stop();
+ return;
+ }
+ d->noopTimer.start(d->noop_time);
+}
+
+void ClientStream::setLocalAddr(const QHostAddress &addr, Q_UINT16 port)
+{
+ d->haveLocalAddr = true;
+ d->localAddr = addr;
+ d->localPort = port;
+}
+
+int ClientStream::errorCondition() const
+{
+ return d->errCond;
+}
+
+QString ClientStream::errorText() const
+{
+ return d->errText;
+}
+
+// QDomElement ClientStream::errorAppSpec() const
+// {
+// return d->errAppSpec;cr_error
+// }
+
+// bool ClientStream::old() const
+// {
+// return d->client.old;
+// }
+
+void ClientStream::close()
+{
+ if(d->state == Active) {
+ d->state = Closing;
+// d->client.shutdown();
+ processNext();
+ }
+ else if(d->state != Idle && d->state != Closing) {
+ reset();
+ }
+}
+
+void ClientStream::setAllowPlain(bool b)
+{
+ d->allowPlain = b;
+}
+
+void ClientStream::setRequireMutualAuth(bool b)
+{
+ d->mutualAuth = b;
+}
+
+// void ClientStream::setSSFRange(int low, int high)
+// {
+// d->minimumSSF = low;
+// d->maximumSSF = high;
+// }
+
+// void ClientStream::setOldOnly(bool b)
+// {
+// d->oldOnly = b;
+// }
+
+bool ClientStream::transfersAvailable() const
+{
+ return ( !d->in.isEmpty() );
+}
+
+Transfer * ClientStream::read()
+{
+ if(d->in.isEmpty())
+ return 0; //first from queue...
+ else
+ return d->in.dequeue();
+}
+
+void ClientStream::write( Request *request )
+{
+ // pass to CoreProtocol for transformation into wire format
+ d->client.outgoingTransfer( request );
+}
+
+void cs_dump( const QByteArray &bytes )
+{
+//#define GW_CLIENTSTREAM_DEBUG 1
+#ifdef GW_CLIENTSTREAM_DEBUG
+ CoreProtocol::debug( QString( "contains: %1 bytes " ).arg( bytes.count() ) );
+ uint count = 0;
+ while ( count < bytes.count() )
+ {
+ int dword = 0;
+ for ( int i = 0; i < 8; ++i )
+ {
+ if ( count + i < bytes.count() )
+ printf( "%02x ", bytes[ count + i ] );
+ else
+ printf( " " );
+ if ( i == 3 )
+ printf( " " );
+ }
+ printf(" | ");
+ dword = 0;
+ for ( int i = 0; i < 8; ++i )
+ {
+ if ( count + i < bytes.count() )
+ {
+ int j = bytes [ count + i ];
+ if ( j >= 0x20 && j <= 0x7e )
+ printf( "%2c ", j );
+ else
+ printf( "%2c ", '.' );
+ }
+ else
+ printf( " " );
+ if ( i == 3 )
+ printf( " " );
+ }
+ printf( "\n" );
+ count += 8;
+ }
+ printf( "\n" );
+#else
+ Q_UNUSED( bytes );
+#endif
+}
+
+void ClientStream::cp_outgoingData( const QByteArray& outgoingBytes )
+{
+ // take formatted bytes from CoreProtocol and put them on the wire
+#ifdef LIBGW_DEBUG
+ CoreProtocol::debug( "ClientStream::cp_outgoingData:" );
+ cs_dump( outgoingBytes );
+#endif
+ d->ss->write( outgoingBytes );
+}
+
+void ClientStream::cp_incomingData()
+{
+ CoreProtocol::debug( "ClientStream::cp_incomingData:" );
+ Transfer * incoming = d->client.incomingTransfer();
+ if ( incoming )
+ {
+ CoreProtocol::debug( " - got a new transfer" );
+ d->in.enqueue( incoming );
+ d->newTransfers = true;
+ emit doReadyRead();
+ }
+ else
+ CoreProtocol::debug( QString( " - client signalled incomingData but none was available, state is: %1" ).arg( d->client.state() ) );
+}
+
+void ClientStream::cr_connected()
+{
+ d->bs = d->conn->stream();
+ connect(d->bs, SIGNAL(connectionClosed()), SLOT(bs_connectionClosed()));
+ connect(d->bs, SIGNAL(delayedCloseFinished()), SLOT(bs_delayedCloseFinished()));
+
+ QByteArray spare = d->bs->read();
+
+ d->ss = new SecureStream(d->bs);
+ connect(d->ss, SIGNAL(readyRead()), SLOT(ss_readyRead()));
+ connect(d->ss, SIGNAL(bytesWritten(int)), SLOT(ss_bytesWritten(int)));
+ connect(d->ss, SIGNAL(tlsHandshaken()), SLOT(ss_tlsHandshaken()));
+ connect(d->ss, SIGNAL(tlsClosed()), SLOT(ss_tlsClosed()));
+ connect(d->ss, SIGNAL(error(int)), SLOT(ss_error(int)));
+
+ //d->client.startDialbackOut("andbit.net", "im.pyxa.org");
+ //d->client.startServerOut(d->server);
+
+// d->client.startClientOut(d->jid, d->oldOnly, d->conn->useSSL(), d->doAuth);
+// d->client.setAllowTLS(d->tlsHandler ? true: false);
+// d->client.setAllowBind(d->doBinding);
+// d->client.setAllowPlain(d->allowPlain);
+
+ /*d->client.jid = d->jid;
+ d->client.server = d->server;
+ d->client.allowPlain = d->allowPlain;
+ d->client.oldOnly = d->oldOnly;
+ d->client.sasl_mech = d->sasl_mech;
+ d->client.doTLS = d->tlsHandler ? true: false;
+ d->client.doBinding = d->doBinding;*/
+
+ QGuardedPtr<QObject> self = this;
+ emit connected();
+ if(!self)
+ return;
+
+ // immediate SSL?
+ if(d->conn->useSSL()) {
+ CoreProtocol::debug( "CLIENTSTREAM: cr_connected(), starting TLS" );
+ d->using_tls = true;
+ d->ss->startTLSClient(d->tlsHandler, d->server, spare);
+ }
+ else {
+/* d->client.addIncomingData(spare);
+ processNext();*/
+ }
+}
+
+void ClientStream::cr_error()
+{
+ reset();
+ emit error(ErrConnection);
+}
+
+void ClientStream::bs_connectionClosed()
+{
+ reset();
+ emit connectionClosed();
+}
+
+void ClientStream::bs_delayedCloseFinished()
+{
+ // we don't care about this (we track all important data ourself)
+}
+
+void ClientStream::bs_error(int)
+{
+ // TODO
+}
+
+void ClientStream::ss_readyRead()
+{
+ QByteArray a;
+ a = d->ss->read();
+
+#ifdef LIBGW_DEBUG
+ QCString cs(a.data(), a.size()+1);
+ CoreProtocol::debug( QString( "ClientStream: ss_readyRead() recv: %1 bytes" ).arg( a.size() ) );
+ cs_dump( a );
+#endif
+
+ d->client.addIncomingData(a);
+/* if(d->notify & CoreProtocol::NRecv) { */
+ //processNext();
+}
+
+void ClientStream::ss_bytesWritten(int bytes)
+{
+#ifdef LIBGW_DEBUG
+ CoreProtocol::debug( QString( "ClientStream::ss_bytesWritten: %1 bytes written" ).arg( bytes ) );
+#else
+ Q_UNUSED( bytes );
+#endif
+}
+
+void ClientStream::ss_tlsHandshaken()
+{
+ QGuardedPtr<QObject> self = this;
+ emit securityLayerActivated(LayerTLS);
+ if(!self)
+ return;
+ processNext();
+}
+
+void ClientStream::ss_tlsClosed()
+{
+ CoreProtocol::debug( "ClientStream::ss_tlsClosed()" );
+ reset();
+ emit connectionClosed();
+}
+
+void ClientStream::ss_error(int x)
+{
+ CoreProtocol::debug( QString( "ClientStream::ss_error() x=%1 ").arg( x ) );
+ if(x == SecureStream::ErrTLS) {
+ reset();
+ d->errCond = TLSFail;
+ emit error(ErrTLS);
+ }
+ else {
+ reset();
+ emit error(ErrSecurityLayer);
+ }
+}
+
+void ClientStream::srvProcessNext()
+{
+}
+
+void ClientStream::doReadyRead()
+{
+ //QGuardedPtr<QObject> self = this;
+ emit readyRead();
+ //if(!self)
+ // return;
+ //d->in_rrsig = false;
+}
+
+void ClientStream::processNext()
+{
+ if( !d->in.isEmpty() ) {
+ //d->in_rrsig = true;
+ QTimer::singleShot(0, this, SLOT(doReadyRead()));
+ }
+}
+
+bool ClientStream::handleNeed()
+{
+ return false;
+}
+
+
+void ClientStream::doNoop()
+{
+}
+
+void ClientStream::handleError()
+{
+}
+
+#include "gwclientstream.moc"