/* -*- c++ -*- * * donkeymessage.cpp * * Copyright (C) 2003 Petter E. Stokke * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include "donkeymessage.h" QTextCodec* DonkeyMessage::codec = 0; void DonkeyMessage::initCodec() { if (!codec) { codec = QTextCodec::codecForName("ISO-8859-1"); if (!codec) codec = QTextCodec::codecForLocale(); } } void DonkeyMessage::setStringCodec(QTextCodec* newCodec) { codec = newCodec; } DonkeyMessage::DonkeyMessage( int opcode ) : QMemArray() { initCodec(); op = opcode; pos = 0; } DonkeyMessage::DonkeyMessage( const char* data, int len ) : QMemArray() { initCodec(); resize(len - 2); op = data[0] | (data[1] << 8); char *p = (char*)data + 2; int i; for (i=0; i<(len-2); i++) (*this)[i] = p[i]; pos = 0; } DonkeyMessage::DonkeyMessage(int opcode, int len) : QMemArray(len) { initCodec(); op = opcode; pos = 0; } int DonkeyMessage::opcode() const { return op; } void DonkeyMessage::setOpcode(int opcode) { op = opcode; } inline void DonkeyMessage::writeInt(int64 v, int sz) { int j; pos = size(); resize(pos + sz); for(j = 0; j < sz; j++) (*this)[pos + j] = (v & (-1)) >> (8 * j); pos += sz; } void DonkeyMessage::writeInt8(int8 v) { writeInt((int64)v, 1); } void DonkeyMessage::writeInt16(int16 v) { writeInt((int64)v, 2); } void DonkeyMessage::writeInt32(int32 v) { writeInt((int64)v, 4); } void DonkeyMessage::writeInt64(int64 v) { writeInt((int64)v, 8); } void DonkeyMessage::writeBool(bool v) { writeInt8(v ? 1 : 0); } void DonkeyMessage::writeString(const QString& v) { QCString s = codec->fromUnicode(v); if (s.isNull()) { kdDebug() << "Unable to convert string into charset " << codec->name() << "." << endl; writeString(""); } else writeString((const char*)s); } void DonkeyMessage::writeString(const char* v) { int i,l = strlen(v); pos = size(); if (l >= 0xffff) { writeInt16(0xffff); writeInt32(l); } else writeInt16(l); resize(pos + l); for (i=0; i= 0xffff) { writeInt16(0xffff); writeInt32(l); } else writeInt16(l); resize(pos + l); for (i=0; i count()) { QString foo(kdBacktrace()); QString msg(dumpArray()); kdDebug() << "Position " << pos + sz << " exceeds buffer size " << count() << "\nMessage: " << msg << "\nBT: " << foo << endl; kdFatal() << "Invalid index access."; } int i; int64 res = 0; for(i = 0; i < sz; i++) { int64 quux = (*this)[pos + i] & 0xff; int64 flarp = quux << (8 * i); res |= flarp; } pos += sz; return res; } int8 DonkeyMessage::readInt8() { return (int8)readInt(1); } int16 DonkeyMessage::readInt16() { return (int16)readInt(2); } int32 DonkeyMessage::readInt32() { return (int32)readInt(4); } int64 DonkeyMessage::readInt64() { return (int64)readInt(8); } bool DonkeyMessage::readBool() { return (bool)readInt(1); } QString DonkeyMessage::readString(bool* ok) { return codec->toUnicode( readByteArray(ok) ); } QByteArray DonkeyMessage::readByteArray(bool* ok) { int sz = (int)readInt16(); if (sz == 0xffff) sz = (int)readInt32(); if ((uint)pos + sz > count()) { QString foo(kdBacktrace()); QString msg(dumpArray()); kdDebug() << "Position " << pos + sz << " exceeds buffer size " << count() << "\nMessage: " << msg << "\nBT: " << foo << endl; if(ok) { *ok = false; return QByteArray(); } kdFatal() << "Invalid index access."; } QByteArray buf(sz); memcpy(buf.data(), *this + pos, sz); pos += sz; return buf; } int DonkeyMessage::readDate() { return QDateTime::currentDateTime().toTime_t() - readInt32(); } double DonkeyMessage::readFloat() { return readString().toDouble(); } QString DonkeyMessage::readIPAddress() { /* QString address = QString::number(readInt8()) + "." + QString::number(readInt8()) + "." + QString::number(readInt8()) + "." + QString::number(readInt8()); */ struct in_addr in; in.s_addr = readInt32(); return QString(inet_ntoa(in)); } QString DonkeyMessage::readAddress() { if (readInt8()) return readString(); else return readIPAddress(); } bool DonkeyMessage::readTag(QMap& dict) { QString name = readString(); QVariant value; switch (readInt8()) { case 0: case 1: value = QVariant(readInt32()); break; case 2: { bool is_ok = true; value = QVariant(readString(&is_ok)); if(! is_ok) return false; } break; case 3: value = QVariant(readIPAddress()); break; case 4: value = QVariant(readInt16()); break; case 5: value = QVariant(readInt8()); break; default: kdWarning() << "DonkeyMessage::readTag() returned unknown value!" << endl; return false; } dict.replace(name, value); return true; } QString DonkeyMessage::dumpArray() const { QString out = "Opcode " + QString::number(op) + ", size " + QString::number(size()) + "\n"; int i; QString hex = "", asc = "", tmp; for (i=0; i<(int)size(); i++) { if (at(i) >= 32 && at(i) <= 127) asc += QChar(at(i)); else asc += "."; tmp.sprintf("%02x", at(i)); hex += tmp + " "; if (i % 16 == 15) { tmp.sprintf("%8d: ", i - 15); out += tmp + hex + " " + asc + "\n"; hex = ""; asc = ""; } } tmp.sprintf("%8d: ", i - (i % 16)); for (i %= 16; i < 16; i++) hex += " "; out += tmp + hex + " " + asc + "\n"; return out; }