/* Kopete Yahoo Protocol Copyright (c) 2004 Duncan Mac-Vicar P. Based on code Copyright (c) 2004 SuSE Linux AG Copyright (C) 2003 Justin Karneges Kopete (c) 2002-2004 by the Kopete developers ************************************************************************* * * * 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 #include #include #include #include #include #include #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(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"