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/coreprotocol.cpp

238 lines
6.3 KiB

/*
Kopete Yahoo Protocol
Copyright (c) 2004 Duncan Mac-Vicar P. <duncan@kde.org>
Based on code
Copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
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 <string.h>
#include <iostream>
#include <tqdatastream.h>
#include <tqdatetime.h>
#include <tqtextstream.h>
#include <kdebug.h>
#include <kurl.h>
#include "coreprotocol.h"
#include "ymsgprotocol.h"
#include "ymsgtransfer.h"
CoreProtocol::CoreProtocol() : TQObject()
{
m_YMSGProtocol = new YMSGProtocol( this, "ymsgprotocol" );
}
CoreProtocol::~CoreProtocol()
{
}
int CoreProtocol::state()
{
return m_state;
}
void CoreProtocol::addIncomingData( const TQByteArray & incomingBytes )
{
// store locally
int oldsize = m_in.size();
kdDebug(YAHOO_RAW_DEBUG) << incomingBytes.size() << " bytes. already had " << oldsize << " bytes" << endl;
m_in.resize( oldsize + incomingBytes.size() );
memcpy( m_in.data() + oldsize, incomingBytes.data(), incomingBytes.size() );
m_state = Available;
// convert every event in the chunk to a Transfer, signalling it back to the clientstream
int parsedBytes = 0;
int transferCount = 0;
// while there is data left in the input buffer, and we are able to parse something out of it
while ( m_in.size() && ( parsedBytes = wireToTransfer(m_in) ) )
{
transferCount++;
kdDebug(YAHOO_RAW_DEBUG) << " parsed transfer " << transferCount << " in chunk of "<< parsedBytes << " bytes" << endl;
int size = m_in.size();
if ( parsedBytes < size )
{
kdDebug(YAHOO_RAW_DEBUG) << " more data in chunk! ( I have parsed " << parsedBytes << " and total data of " << size << ")" << endl;
// remove parsed bytes from the buffer
//m_in.remove( 0, parsedBytes );
// copy the unparsed bytes into a new qbytearray and replace m_in with that
TQByteArray remainder( size - parsedBytes );
memcpy( remainder.data(), m_in.data() + parsedBytes, remainder.size() );
m_in = remainder;
}
else
m_in.truncate( 0 );
}
if ( m_state == NeedMore )
kdDebug(YAHOO_RAW_DEBUG) << " message was incomplete, waiting for more..." << endl;
/*
if ( m_eventProtocol->state() == EventProtocol::OutOfSync )
{
tqDebug( " - protocol thinks it's out of sync, discarding the rest of the buffer and hoping the server regains sync soon..." );
m_in.truncate( 0 );
}
*/
kdDebug(YAHOO_RAW_DEBUG) << " done processing chunk" << endl;
}
Transfer* CoreProtocol::incomingTransfer()
{
kdDebug(YAHOO_GEN_DEBUG) << k_funcinfo << endl;
if ( m_state == Available )
{
// kdDebug(YAHOO_RAW_DEBUG) << " - got a transfer";
m_state = NoData;
return m_inTransfer;
m_inTransfer = 0;
}
else
{
kdDebug(YAHOO_RAW_DEBUG) << " no milk today" << endl;
return 0;
}
}
void cp_dump( const TQByteArray &bytes )
{
#ifdef YAHOO_COREPROTOCOL_DEBUG
kdDebug(YAHOO_RAW_DEBUG) << " contains " << bytes.count() << " bytes" << endl;
for ( uint i = 0; i < bytes.count(); ++i )
{
printf( "%02x ", bytes[ i ] );
}
printf( "\n" );
#else
Q_UNUSED( bytes );
#endif
}
void CoreProtocol::outgoingTransfer( Transfer* outgoing )
{
kdDebug(YAHOO_GEN_DEBUG) << k_funcinfo << endl;
if ( outgoing->type() == Transfer::YMSGTransfer )
{
kdDebug(YAHOO_RAW_DEBUG) << " got YMSGTransfer" << endl;
YMSGTransfer *yt = (YMSGTransfer *) outgoing;
TQByteArray bytesOut = yt->serialize();
//TQTextStream dout( bytesOut, TQIODevice::WriteOnly );
//dout.setEncoding( TQTextStream::Latin1 );
//dout.setByteOrder( TQDataStream::LittleEndian );
//dout << bytesOut;
//kdDebug(YAHOO_RAW_DEBUG) << " " << bytesOut;
emit outgoingData( bytesOut );
// now convert
//fieldsToWire( fields );
}
delete outgoing;
}
int CoreProtocol::wireToTransfer( const TQByteArray& wire )
{
kdDebug(YAHOO_GEN_DEBUG) << k_funcinfo << endl;
// processing incoming data and reassembling it into transfers
// may be an event or a response
uint bytesParsed = 0;
if ( wire.size() < 20 ) // minimal value of a YMSG header
{
m_state = NeedMore;
return bytesParsed;
}
TQByteArray tempWire = wire;
TQDataStream din( tempWire, IO_ReadOnly );
// look at first four bytes and decide what to do with the chunk
if ( okToProceed( din ) )
{
if ( (wire[0] == 'Y') && (wire[1] == 'M') && (wire[2] == 'S') && (wire[3] == 'G'))
{
// kdDebug(YAHOO_RAW_DEBUG) << " - looks like a valid YMSG packet";
YMSGTransfer *t = static_cast<YMSGTransfer *>(m_YMSGProtocol->parse( wire, bytesParsed ));
// kdDebug(YAHOO_RAW_DEBUG) << " - YMSG Protocol parsed " << bytesParsed << " bytes";
if ( t )
{
if( wire.size() < t->packetLength() )
{
m_state = NeedMore;
delete t;
return 0;
}
m_inTransfer = t;
// kdDebug(YAHOO_RAW_DEBUG) << " - got a valid packet ";
m_state = Available;
emit incomingData();
}
else
bytesParsed = 0;
}
else
{
kdDebug(YAHOO_RAW_DEBUG) << " - not a valid YMSG packet. Trying to recover." << endl;
TQTextStream s( wire, IO_ReadOnly );
TQString remaining = s.read();
int pos = remaining.find( "YMSG", bytesParsed );
if( pos >= 0 )
{
kdDebug(YAHOO_RAW_DEBUG) << "Recover successful." << endl;
bytesParsed += pos;
}
else
{
kdDebug(YAHOO_RAW_DEBUG) << "Recover failed. Dump it!" << endl;
bytesParsed = wire.size();
}
}
}
return bytesParsed;
}
void CoreProtocol::reset()
{
m_in.resize( 0 );
}
void CoreProtocol::slotOutgoingData( const TQByteArray &out )
{
tqDebug( "%s", out.data() );
}
bool CoreProtocol::okToProceed( TQDataStream &din)
{
if ( din.atEnd() )
{
m_state = NeedMore;
kdDebug(YAHOO_RAW_DEBUG) << " saved message prematurely" << endl;
return false;
}
else
return true;
}
#include "coreprotocol.moc"