• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdenetwork
  • Sitemap
  • Contact Us
 

kopete/protocols/messenger/libpapillon

messengercoreprotocol.cpp

Go to the documentation of this file.
00001 /*
00002    messengercoreprotocol.cpp - Messenger core protocol for Papillon 
00003 
00004    Copyright (c) 2006 by Michaƫl Larouche <larouche@kde.org>
00005 
00006    Based on code copyright (c) 2004 SuSE Linux AG <http://www.suse.com>
00007    Based on Iris, Copyright (C) 2003  Justin Karneges
00008 
00009    *************************************************************************
00010    *                                                                       *
00011    * This library is free software; you can redistribute it and/or         *
00012    * modify it under the terms of the GNU Lesser General Public            *
00013    * License as published by the Free Software Foundation; either          *
00014    * version 2 of the License, or (at your option) any later version.      *
00015    *                                                                       *
00016    *************************************************************************
00017 */
00018 #include "Papillon/MessengerCoreProtocol"
00019 
00020 // Qt includes
00021 #include <QtDebug>
00022 #include <QtCore/QDataStream>
00023 #include <QtCore/QTextStream>
00024 #include <QtCore/QLatin1String>
00025 #include <QtCore/QStringList>
00026 
00027 // Papillon includes
00028 #include "Papillon/NetworkMessage"
00029 
00030 namespace Papillon
00031 {
00032 
00033 class MessengerCoreProtocol::Private
00034 {
00035 public:
00036     Private()
00037         : inNetworkMessage(0), state(MessengerCoreProtocol::NoData)
00038     {}
00039     
00040     ~Private()
00041     {
00042         delete inNetworkMessage;
00043     }
00044     
00045     // buffer containing unprocessed bytes we received
00046     QByteArray in;
00047     // the transfer that is being received
00048     NetworkMessage *inNetworkMessage;
00049     // represents the protocol's overall state
00050     int state;
00051     // Represend the length of payload data to read.
00052     int payloadLength;
00053 };
00054 
00055 MessengerCoreProtocol::MessengerCoreProtocol() : QObject(), d(new Private)
00056 {}
00057 
00058 MessengerCoreProtocol::~MessengerCoreProtocol()
00059 {
00060     qDebug() << Q_FUNC_INFO;
00061     delete d;
00062 }
00063 
00064 int MessengerCoreProtocol::state()
00065 {
00066     return d->state;
00067 }
00068 
00069 void MessengerCoreProtocol::addIncomingData(const QByteArray &incomingBytes )
00070 {
00071     // Append incoming bytes to incoming buffer
00072     d->in += incomingBytes;
00073     
00074     // convert every event in the chunk to a NetworkMessage, signalling it back to the ClientStream
00075     int parsedBytes = 0;
00076     int transferCount = 0;
00077     // while there is data left in the input buffer, and we are able to parse something out of it
00078     while ( d->in.size() && ( parsedBytes = rawToNetworkMessage( d->in ) ) )
00079     {
00080         transferCount++;
00081         int size =  d->in.size();
00082         if ( parsedBytes < size )
00083         {
00084             // Remove the parsed bytes and keep the old ones.
00085             d->in = d->in.right( size - parsedBytes );
00086         }
00087         else
00088         {
00089             d->in.clear();
00090         }
00091     }
00092 }
00093 
00094 NetworkMessage *MessengerCoreProtocol::incomingNetworkMessage()
00095 {
00096     if ( d->state == Available )
00097     {
00098         d->state = NoData;
00099         return d->inNetworkMessage;
00100     }
00101     else
00102     {
00103         return 0;
00104     }
00105 }
00106 
00107 void MessengerCoreProtocol::outgoingNetworkMessage(NetworkMessage *outgoing)
00108 {
00109     emit outgoingData( outgoing->toRawCommand() );
00110     // Clear the transfer.
00111     delete outgoing;
00112 }
00113 
00114 int MessengerCoreProtocol::rawToNetworkMessage(const QByteArray &raw)
00115 {
00116     uint bytesParsed = 0;
00117 
00118     if ( raw.size() < 4 )
00119     {
00120         d->state = NeedMore;
00121         return bytesParsed;
00122     }   
00123     
00124     QByteArray tempRaw = raw;
00125     QDataStream din( &tempRaw, QIODevice::ReadOnly );
00126     
00127     // look at first four bytes and decide what to do with the chunk
00128     if ( okToProceed( din ) )
00129     {
00130         if(d->state != WaitForPayload && d->state != NeedMore)
00131         {
00132             QTextStream lineStream(tempRaw);
00133             
00134             QString parsedLine = lineStream.readLine();
00135             
00136             QStringList commandList = parsedLine.split(" ");
00137             
00138             QString command;
00139             QStringList arguments;
00140             
00141             NetworkMessage::NetworkMessageType transferType;
00142             bool dummy, isNumber = false;
00143             int trId = 0, payloadLength = 0;
00144             
00145             command = commandList.at(0);
00146             
00147             // Determine the transfer type.
00148             if(isPayloadCommand(command))
00149             {
00150                 transferType |= NetworkMessage::PayloadMessage;
00151                 // Remove the last parameter from the command list and set the payload length.
00152                 // So it will not be in the arguments.
00153                 payloadLength = commandList.takeLast().toUInt(&dummy);
00154                 qDebug() << Q_FUNC_INFO << "Begin Payload transfer, length:" << payloadLength;
00155             }
00156             
00157             // Check for a transaction ID.
00158             // Do not check for a transaction if the commandList size is lower than 2.
00159             if( commandList.size() >= 2 )
00160             {
00161                 trId = commandList[1].toUInt(&isNumber);
00162                 if(isNumber)
00163                     transferType |= NetworkMessage::TransactionMessage;
00164             }
00165             
00166             // Begin at the third command arguments if we have a transaction ID.
00167             int beginAt = isNumber ? 2 : 1;
00168             // Fill the arguments.
00169             for(int i = beginAt; i < commandList.size(); ++i)
00170             {
00171                 arguments << commandList[i];
00172             }
00173             
00174             NetworkMessage *receivedNetworkMessage = new NetworkMessage(transferType);
00175             receivedNetworkMessage->setCommand(command);
00176             receivedNetworkMessage->setArguments(arguments);
00177             
00178             if(isNumber)
00179                 receivedNetworkMessage->setTransactionId( QString::number(trId) );
00180             
00181             d->inNetworkMessage = receivedNetworkMessage;
00182             
00183             if(payloadLength > 0)
00184             {
00185                 d->payloadLength = payloadLength;
00186                 d->state = WaitForPayload;
00187             }
00188             else
00189             {
00190                 // Show parsed line here for non-payload messages.
00191                 qDebug() << Q_FUNC_INFO << parsedLine;
00192                 d->state = Available;
00193                 emit incomingData();
00194             }
00195             
00196             bytesParsed = parsedLine.size() + 2; // 2 is to add \r\n to the size which was trimmed.
00197         }
00198         else if(d->state == WaitForPayload || d->state == NeedMore)
00199         {
00200             if(raw.size() < d->payloadLength)
00201             {
00202                 qDebug() << Q_FUNC_INFO << "Raw size:" << raw.size() << "Payload length:" << d->payloadLength;
00203                 d->state = NeedMore;
00204                 return bytesParsed;
00205             }
00206             
00207             // Retrieve the full payload data from raw data (do a shared copy)
00208             QByteArray payloadData = raw.left(d->payloadLength);
00209             
00210             d->inNetworkMessage->setPayloadData(payloadData);
00211             qDebug() << Q_FUNC_INFO << "Byte data length:" << payloadData.size();
00212 //          qDebug() << Q_FUNC_INFO << "Payload data read(from CoreProtocol):" << raw;
00213             // Show full payload command to output
00214             qDebug() << Q_FUNC_INFO << d->inNetworkMessage->toRawCommand();
00215             d->state = Available;
00216             
00217             bytesParsed = payloadData.size();
00218             
00219             emit incomingData();
00220         }
00221     }
00222     return bytesParsed;
00223 }
00224 
00225 void MessengerCoreProtocol::reset()
00226 {
00227     d->in.clear();
00228 }
00229 
00230 bool MessengerCoreProtocol::okToProceed(const QDataStream &din)
00231 {
00232     if( din.atEnd() )
00233     {
00234         d->state = NeedMore;
00235         return false;
00236     }
00237     else
00238         return true;
00239 }
00240 
00241 bool MessengerCoreProtocol::isPayloadCommand(const QString &command)
00242 {
00243     if( command == QLatin1String("ADL") ||
00244         command == QLatin1String("GCF") ||
00245         command == QLatin1String("MSG") ||
00246         command == QLatin1String("QRY") ||
00247         command == QLatin1String("RML") ||
00248         command == QLatin1String("UBX") ||
00249         command == QLatin1String("UBN") ||
00250         command == QLatin1String("UUN") ||
00251         command == QLatin1String("UUX")
00252       )
00253         return true;
00254     else
00255         return false;
00256 }
00257 
00258 }
00259 
00260 #include "messengercoreprotocol.moc"
00261 //kate: indent-mode csands; tab-width 4;

kopete/protocols/messenger/libpapillon

Skip menu "kopete/protocols/messenger/libpapillon"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdenetwork

Skip menu "kdenetwork"
  • kget
  • kopete
  •   kopete
  •   libkopete
  •       libpapillon
  • krfb
Generated for kdenetwork by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal