You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/kopete/protocols/yahoo/libkyahoo/yahooclientstream.cpp

421 lines
8.1 KiB

/*
oscarclientstream.cpp - Kopete Oscar Protocol
Copyright (c) 2004 Matt Rogers <matt.rogers@kdemail.net>
Based on code Copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
Based on Iris, Copyright (C) 2003 Justin Karneges <justin@affinix.com>
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 <tqapplication.h> // for qdebug
#include <tqguardedptr.h>
#include <tqobject.h>
#include <tqptrqueue.h>
#include <tqtimer.h>
#include <kdebug.h>
#include "bytestream.h"
#include "connector.h"
#include "coreprotocol.h"
#include "transfer.h"
#include "yahooclientstream.h"
#include "yahootypes.h"
void cs_dump( const TQByteArray &bytes );
enum {
Idle,
Connecting,
Active,
Closing
};
enum {
Client,
Server
};
class ClientStream::Private
{
public:
Private()
{
conn = 0;
bs = 0;
username = TQString();
password = TQString();
server = TQString();
haveLocalAddr = false;
doBinding = true;
reset();
}
void reset()
{
state = Idle;
notify = 0;
newTransfers = false;
}
TQString username;
TQString password;
TQString server;
bool doAuth; //send the initial login sequences to get the cookie
bool haveLocalAddr;
TQHostAddress localAddr;
TQ_UINT16 localPort;
bool doBinding;
Connector *conn;
ByteStream *bs;
CoreProtocol client;
TQString defRealm;
int mode;
int state;
int notify;
bool newTransfers;
int errCond;
TQString errText;
TQPtrQueue<Transfer> in;
TQTimer noopTimer; // used to send icq keepalive
int noop_time;
};
ClientStream::ClientStream(Connector *conn, TQObject *tqparent)
:Stream(tqparent), d(new Private())
{
kdDebug(YAHOO_RAW_DEBUG) ;
d->mode = Client;
d->conn = conn;
connect( d->conn, TQT_SIGNAL(connected()), TQT_SLOT(cr_connected()) );
connect( d->conn, TQT_SIGNAL(error()), TQT_SLOT(cr_error()) );
connect( &d->client, TQT_SIGNAL( outgoingData( const TQByteArray& ) ), TQT_SLOT ( cp_outgoingData( const TQByteArray & ) ) );
connect( &d->client, TQT_SIGNAL( incomingData() ), TQT_SLOT ( cp_incomingData() ) );
d->noop_time = 0;
connect(&d->noopTimer, TQT_SIGNAL(timeout()), TQT_SLOT(doNoop()));
}
ClientStream::~ClientStream()
{
reset();
delete d;
}
void ClientStream::reset(bool all)
{
kdDebug(YAHOO_RAW_DEBUG) ;
d->reset();
d->noopTimer.stop();
// client
if(d->mode == Client) {
// reset connector
if(d->bs) {
disconnect(d->bs, 0, this, 0);
d->bs->close();
d->bs = 0;
}
d->conn->done();
// reset state machine
d->client.reset();
}
if(all)
d->in.clear();
}
void ClientStream::connectToServer(const TQString& server, bool auth)
{
kdDebug(YAHOO_RAW_DEBUG) ;
reset(true);
d->state = Connecting;
d->doAuth = auth;
d->server = server;
d->conn->connectToServer( d->server );
}
void ClientStream::continueAfterWarning()
{
kdDebug(YAHOO_RAW_DEBUG) ;
/* unneeded?
if(d->state == WaitVersion) {
d->state = Connecting;
processNext();
}
else if(d->state == WaitTLS) {
d->state = Connecting;
processNext();
}
*/
}
void ClientStream::accept()
{
}
bool ClientStream::isActive() const
{
return (d->state != Idle);
}
bool ClientStream::isAuthenticated() const
{
return (d->state == Active);
}
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 TQHostAddress &addr, TQ_UINT16 port)
{
d->haveLocalAddr = true;
d->localAddr = addr;
d->localPort = port;
}
int ClientStream::errorCondition() const
{
return d->errCond;
}
TQString ClientStream::errorText() const
{
return d->errText;
}
void ClientStream::close()
{
if(d->state == Active) {
d->state = Closing;
// d->client.shutdown();
processNext();
}
else if(d->state != Idle && d->state != Closing) {
reset();
}
}
bool ClientStream::transfersAvailable() const
{
kdDebug(YAHOO_RAW_DEBUG) ;
return ( !d->in.isEmpty() );
}
Transfer* ClientStream::read()
{
if(d->in.isEmpty())
return 0; //first from queue...
else
return d->in.dequeue();
}
void ClientStream::write( Transfer *request )
{
kdDebug(YAHOO_RAW_DEBUG) ;
// pass to CoreProtocol for transformation into wire format
d->client.outgoingTransfer( request );
}
void cs_dump( const TQByteArray &bytes )
{
#if 0
qDebug( "tqcontains: %i bytes ", 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" );
#endif
Q_UNUSED( bytes );
}
void ClientStream::cp_outgoingData( const TQByteArray& outgoingBytes )
{
if ( !d->bs )
return;
// take formatted bytes from CoreProtocol and put them on the wire
kdDebug(YAHOO_RAW_DEBUG) << "[data size: " << outgoingBytes.size() << "]" << endl;
//cs_dump( outgoingBytes );
d->bs->write( outgoingBytes );
}
void ClientStream::cp_incomingData()
{
// kdDebug(YAHOO_RAW_DEBUG) ;
Transfer * incoming = d->client.incomingTransfer();
if ( incoming )
{
// kdDebug(YAHOO_RAW_DEBUG) << " - got a new transfer";
d->in.enqueue( incoming );
d->newTransfers = true;
emit doReadyRead();
}
else
kdDebug(YAHOO_RAW_DEBUG) << " - client signalled incomingData but none was available, state is: "<< d->client.state() << endl;
}
/* Connector connected */
void ClientStream::cr_connected()
{
kdDebug(YAHOO_RAW_DEBUG) ;
d->bs = d->conn->stream();
connect(d->bs, TQT_SIGNAL(connectionClosed()), TQT_SLOT(bs_connectionClosed()));
connect(d->bs, TQT_SIGNAL(delayedCloseFinished()), TQT_SLOT(bs_delayedCloseFinished()));
connect(d->bs, TQT_SIGNAL(readyRead()), TQT_SLOT(bs_readyRead()));
connect(d->bs, TQT_SIGNAL(bytesWritten(int)), TQT_SLOT(bs_bytesWritten(int)));
connect(d->bs, TQT_SIGNAL(error(int)), TQT_SLOT(bs_error(int)));
TQByteArray spare = d->bs->read();
TQGuardedPtr<TQObject> self = this;
emit connected();
if(!self)
return;
}
void ClientStream::cr_error()
{
kdDebug(YAHOO_RAW_DEBUG) ;
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)
{
kdDebug(YAHOO_RAW_DEBUG) ;
// TODO
}
void ClientStream::bs_readyRead()
{
// kdDebug(YAHOO_RAW_DEBUG) ;
TQByteArray a;
//qDebug( "size of storage for incoming data is %i bytes.", a.size() );
a = d->bs->read();
//TQCString cs(a.data(), a.size()+1);
//qDebug("ClientStream: recv: %d [%s]\n", a.size(), cs.data());
//kdDebug(YAHOO_RAW_DEBUG) << " recv: " << a.size() <<" bytes";
//cs_dump( a );
d->client.addIncomingData(a);
}
void ClientStream::bs_bytesWritten(int bytes)
{
kdDebug(YAHOO_RAW_DEBUG) << " written: " << bytes <<" bytes" << endl;
}
void ClientStream::srvProcessNext()
{
}
void ClientStream::doReadyRead()
{
// kdDebug(YAHOO_RAW_DEBUG) ;
emit readyRead();
}
void ClientStream::processNext()
{
if( !d->in.isEmpty() )
{
TQTimer::singleShot(0, this, TQT_SLOT(doReadyRead()));
}
}
bool ClientStream::handleNeed()
{
return false;
}
void ClientStream::doNoop()
{
}
void ClientStream::handleError()
{
}
#include "yahooclientstream.moc"