kopete/protocols/messenger/libpapillon
messengercoreprotocol.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "Papillon/MessengerCoreProtocol"
00019
00020
00021 #include <QtDebug>
00022 #include <QtCore/QDataStream>
00023 #include <QtCore/QTextStream>
00024 #include <QtCore/QLatin1String>
00025 #include <QtCore/QStringList>
00026
00027
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
00046 QByteArray in;
00047
00048 NetworkMessage *inNetworkMessage;
00049
00050 int state;
00051
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
00072 d->in += incomingBytes;
00073
00074
00075 int parsedBytes = 0;
00076 int transferCount = 0;
00077
00078 while ( d->in.size() && ( parsedBytes = rawToNetworkMessage( d->in ) ) )
00079 {
00080 transferCount++;
00081 int size = d->in.size();
00082 if ( parsedBytes < size )
00083 {
00084
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
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
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
00148 if(isPayloadCommand(command))
00149 {
00150 transferType |= NetworkMessage::PayloadMessage;
00151
00152
00153 payloadLength = commandList.takeLast().toUInt(&dummy);
00154 qDebug() << Q_FUNC_INFO << "Begin Payload transfer, length:" << payloadLength;
00155 }
00156
00157
00158
00159 if( commandList.size() >= 2 )
00160 {
00161 trId = commandList[1].toUInt(&isNumber);
00162 if(isNumber)
00163 transferType |= NetworkMessage::TransactionMessage;
00164 }
00165
00166
00167 int beginAt = isNumber ? 2 : 1;
00168
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
00191 qDebug() << Q_FUNC_INFO << parsedLine;
00192 d->state = Available;
00193 emit incomingData();
00194 }
00195
00196 bytesParsed = parsedLine.size() + 2;
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
00208 QByteArray payloadData = raw.left(d->payloadLength);
00209
00210 d->inNetworkMessage->setPayloadData(payloadData);
00211 qDebug() << Q_FUNC_INFO << "Byte data length:" << payloadData.size();
00212
00213
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