Update of /cvsroot/seq/showeq/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10951/src Modified Files: Tag: pre_5_0_beta crctab.h everquest.h interface.cpp messageshell.cpp messageshell.h packet.cpp packet.h packetformat.cpp packetformat.h packetfragment.cpp packetfragment.h packetlog.cpp packetstream.cpp packetstream.h player.cpp spells_en2spellsh.pl staticspells.h util.cpp util.h Log Message: 5.0.0.17 New network protocol Index: crctab.h =================================================================== RCS file: /cvsroot/seq/showeq/src/crctab.h,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.1.16.1 diff -u -d -r1.1.1.1 -r1.1.1.1.16.1 --- crctab.h 19 Dec 2001 00:36:52 -0000 1.1.1.1 +++ crctab.h 9 Feb 2005 07:07:34 -0000 1.1.1.1.16.1 @@ -5,9 +5,6 @@ * http://seq.sf.net/ */ -#ifndef _CRCTAB_H_ -#define _CRCTAB_H_ - static uint32_t crctab[256] = { 0x0, @@ -64,4 +61,3 @@ 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5a05df1b, 0x2d02ef8d, }; -#endif // _CRCTAB_H_ Index: packet.h =================================================================== RCS file: /cvsroot/seq/showeq/src/packet.h,v retrieving revision 1.39.6.1 retrieving revision 1.39.6.2 diff -u -d -r1.39.6.1 -r1.39.6.2 --- packet.h 7 Dec 2003 06:30:43 -0000 1.39.6.1 +++ packet.h 9 Feb 2005 07:07:38 -0000 1.39.6.2 @@ -101,6 +101,8 @@ void session_tracking(bool enable); void setArqSeqGiveUp(uint16_t giveUp); void setRealtime(bool val); + void dispatchSessionKey(uint32_t sessionId, EQStreamID streamid, + uint32_t sessionKey); protected slots: void closeStream(); @@ -169,6 +171,7 @@ EQPacketOPCodeDB* m_zoneOPCodeDB; void dispatchPacket (int size, unsigned char *buffer); + void dispatchPacket(EQUDPIPPacketFormat& packet); protected slots: void resetEQPacket(); void dispatchWorldChatData (size_t len, uint8_t* data, uint8_t direction = 0); Index: staticspells.h =================================================================== RCS file: /cvsroot/seq/showeq/src/staticspells.h,v retrieving revision 1.1.14.1 retrieving revision 1.1.14.2 diff -u -d -r1.1.14.1 -r1.1.14.2 --- staticspells.h 7 Nov 2004 23:10:25 -0000 1.1.14.1 +++ staticspells.h 9 Feb 2005 07:07:39 -0000 1.1.14.2 @@ -5,7 +5,6 @@ * http://seq.sourceforge.net/ */ -#ifndef DOXYGEN_SHOULD_SKIP_THIS /* File autogenerated from spells_en.txt */ // Format: // /* Spell ID */ { Spell Name }, @@ -486,7 +485,7 @@ /* 0x01d9 - 473 */ { "Invoke Fear II" }, /* 0x01da - 474 */ { "Radius of Fear2" }, /* 0x01db - 475 */ { "Fear2" }, [...2987 lines suppressed...] +/* 0x19e6 - 6630 */ { "Stone Pummel" }, +/* 0x19e7 - 6631 */ { "Black Cyclone" }, +/* 0x19e8 - 6632 */ { "Lightning Cyclone" }, +/* 0x19e9 - 6633 */ { "Feral Roar" }, +/* 0x19ea - 6634 */ { "Kirin Hoof" }, +/* 0x19eb - 6635 */ { "Kirin Touch" }, +/* 0x19ec - 6636 */ { "Kirin Word" }, +/* 0x19ed - 6637 */ { "Summon Storm Dervish" }, +/* 0x19ee - 6638 */ { "Devouring Flames of Al'Kabor" }, +/* 0x19ef - 6639 */ { "Devouring Flames Recourse" }, +/* 0x19f0 - 6640 */ { "Vishimtar's Shadow" }, // -// Max SpellId: 0x1142 = 4418 -// Number of Spells: 4293 -// Empty Entries: 125 -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - +// Max SpellId: 0x19f1 = 6641 +// Number of Spells: 6433 +// Empty Entries: 208 Index: packetstream.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/packetstream.cpp,v retrieving revision 1.1.6.5 retrieving revision 1.1.6.6 diff -u -d -r1.1.6.5 -r1.1.6.6 --- packetstream.cpp 7 Nov 2004 23:10:24 -0000 1.1.6.5 +++ packetstream.cpp 9 Feb 2005 07:07:38 -0000 1.1.6.6 @@ -9,7 +9,6 @@ */ /* Implementation of EQPacketStream class */ -#include "decode.h" #include "packetstream.h" #include "packetformat.h" #include "packetinfo.h" @@ -23,17 +22,17 @@ // Macros // The following defines are used to diagnose packet handling behavior [...1053 lines suppressed...] + m_sessionKey = sessionKey; + +#ifdef PACKET_SESSION_DIAG + seqDebug("EQPacket: Received key %u for session %u on stream %s (%d) from stream %s (%d)", + m_sessionKey, m_sessionId, EQStreamStr[m_streamid], m_streamid, + EQStreamStr[streamid], streamid); +#endif + } +} + +/////////////////////////////////////////////////////////////// +// Calculate the CRC on the given packet using this stream's key +uint16_t EQPacketStream::calculateCRC(EQProtocolPacket& packet) +{ + // CRC is at the end of the raw payload, 2 bytes. + return ::calcCRC16(packet.rawPayload(), packet.rawPayloadLength()-2, + m_sessionKey); } #include "packetstream.moc" Index: interface.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/interface.cpp,v retrieving revision 1.67.6.10 retrieving revision 1.67.6.11 diff -u -d -r1.67.6.10 -r1.67.6.11 --- interface.cpp 7 Nov 2004 23:10:03 -0000 1.67.6.10 +++ interface.cpp 9 Feb 2005 07:07:36 -0000 1.67.6.11 @@ -1788,7 +1788,7 @@ m_messageShell, SLOT(formattedMessage(const uint8_t*, size_t, uint8_t))); m_packet->connect2("OP_SimpleMessage", SP_Zone, DIR_Server, - "simpleMessageStruct", SZC_None, + "simpleMessageStruct", SZC_Match, m_messageShell, SLOT(simpleMessage(const uint8_t*, size_t, uint8_t))); m_packet->connect2("OP_SpecialMesg", SP_Zone, DIR_Server, @@ -1805,6 +1805,12 @@ m_packet->connect2("OP_RandomReply", SP_Zone, DIR_Server, "randomStruct", SZC_Match, m_messageShell, SLOT(random(const uint8_t*))); + m_packet->connect2("OP_ConsentResponse", SP_Zone, DIR_Server, + "consentResponseStruct", SZC_Match, + m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_DenyResponse", SP_Zone, DIR_Server, + "consentResponseStruct", SZC_Match, + m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); m_packet->connect2("OP_Emote", SP_Zone, DIR_Server|DIR_Client, "emoteTextStruct", SZC_None, m_messageShell, SLOT(emoteText(const uint8_t*))); @@ -1993,6 +1999,9 @@ m_packet->connect2("OP_WearChange", SP_Zone, DIR_Server|DIR_Client, "SpawnUpdateStruct", SZC_Match, m_spawnShell, SLOT(updateSpawnInfo(const uint8_t*))); + m_packet->connect2("OP_InitialHPUpdate", SP_Zone, DIR_Server|DIR_Client, + "hpNpcUpdateStruct", SZC_Match, + m_spawnShell, SLOT(updateNpcHP(const uint8_t*))); m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server|DIR_Client, "hpNpcUpdateStruct", SZC_Match, m_spawnShell, SLOT(updateNpcHP(const uint8_t*))); @@ -2044,7 +2053,7 @@ "actionStruct", SZC_Match, m_spellShell, SLOT(action(const uint8_t*, size_t, uint8_t))); m_packet->connect2("OP_SimpleMessage", SP_Zone, DIR_Server, - "simpleMessageStruct", SZC_None, + "simpleMessageStruct", SZC_Match, m_spellShell, SLOT(simpleMessage(const uint8_t*, size_t, uint8_t))); @@ -2068,6 +2077,9 @@ m_packet->connect2("OP_LevelUpdate", SP_Zone, DIR_Server, "levelUpUpdateStruct", SZC_Match, m_player, SLOT(updateLevel(const uint8_t*))); + m_packet->connect2("OP_InitialHPUpdate", SP_Zone, DIR_Server|DIR_Client, + "hpNpcUpdateStruct", SZC_Match, + m_player, SLOT(updateNpcHP(const uint8_t*))); m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server|DIR_Client, "hpNpcUpdateStruct", SZC_Match, m_player, SLOT(updateNpcHP(const uint8_t*))); Index: packetformat.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/packetformat.cpp,v retrieving revision 1.1.6.2 retrieving revision 1.1.6.3 diff -u -d -r1.1.6.2 -r1.1.6.3 --- packetformat.cpp 12 Feb 2004 00:39:28 -0000 1.1.6.2 +++ packetformat.cpp 9 Feb 2005 07:07:38 -0000 1.1.6.3 @@ -11,116 +11,52 @@ /* Implementation of packet format classes class */ #include "packetformat.h" +#include "diagnosticmessages.h" //---------------------------------------------------------------------- -// EQPacketFormatRaw class methods -QString EQPacketFormatRaw::headerFlags(const QString& prefix, - bool brief) const -{ - QString tmp; - if (!prefix.isEmpty()) - { - if (brief) - tmp = prefix + ": "; - else - tmp = prefix + "[Hdr (" + QString::number(flagsHi(), 16) + ", " - + QString::number(flagsLo(), 16) + "): "; - } - else if (!brief) - tmp = "[Hdr (" + QString::number(flagsHi(), 16) + ", " - + QString::number(flagsLo(), 16) + "): "; - - if (isARQ()) - tmp += "ARQ, "; - if (isClosingLo()) - tmp += "closingLo, "; - if (isFragment()) - tmp += "Fragment, "; - if (isASQ()) - tmp += "ASQ, "; - if (isSEQStart()) - tmp += "SEQStart, "; - if (isClosingHi()) - tmp += "closingHi, "; - if (isSEQEnd()) - tmp += "SEQEnd, "; - if (isARSP()) - tmp += "ARSP, "; - if (isNAK()) - tmp += "NAK, "; - if (isSpecARQ()) - tmp += "SpecARQ, "; - if (m_flagsHi.m_unknown1) - tmp += "HiUnknown1, "; - - if (skip() != 0) - tmp += QString("Skip: ") + QString::number(skip(), 16) + ", "; - - tmp += QString("seq: ") + QString::number(seq(), 16); - - tmp += "] "; - - if (!brief) - { - if (isARQ()) - tmp += QString("[ARQ: ") + QString::number(arq(), 16) + "] "; - - if (isFragment()) - { - tmp += QString("[FragSeq: ") + QString::number(fragSeq(), 16) - + ", FragCur: " + QString::number(fragCur(), 16) - + ", FragTot: " + QString::number(fragTot(), 16) + "] "; - } - } - - return tmp; -} - -//---------------------------------------------------------------------- -// EQPacketFormat class methods -EQPacketFormat::EQPacketFormat(EQPacketFormat& packet, bool copy) - : m_ownCopy(copy), - m_isValid(packet.m_isValid) +// EQProtocolPacket class methods +EQProtocolPacket::EQProtocolPacket(EQProtocolPacket& packet, bool copy) + : m_ownCopy(copy) { if (!copy) { // just copy all their values m_packet = packet.m_packet; m_length = packet.m_length; - m_postSkipData = packet.m_postSkipData; - m_postSkipDataLength = packet.m_postSkipDataLength; m_payload = packet.m_payload; m_payloadLength = packet.m_payloadLength; - m_arq = packet.m_arq; + m_arqSeq = packet.m_arqSeq; + m_subpacket = packet.m_subpacket; } else { - init(packet.m_packet, packet.m_length, copy); + init(packet.m_packet, packet.m_length, copy, packet.m_subpacket); } } -EQPacketFormat::~EQPacketFormat() +EQProtocolPacket::~EQProtocolPacket() { if (m_ownCopy) delete [] (uint8_t*)m_packet; } -EQPacketFormat& EQPacketFormat::operator=(const EQPacketFormat& packet) +EQProtocolPacket& EQProtocolPacket::operator=(const EQProtocolPacket& packet) { // if this was a deep copy, delete the existing data if (m_ownCopy) delete [] (uint8_t*)m_packet; // initialize as deep as this object previously was - init(packet.m_packet, packet.m_length, m_ownCopy); + init(packet.m_packet, packet.m_length, m_ownCopy, packet.m_subpacket); return *this; } -void EQPacketFormat::init(EQPacketFormatRaw* packet, - uint16_t length, - bool copy) +void EQProtocolPacket::init(uint8_t* packet, uint16_t length, + bool copy, bool subpacket) { + m_subpacket = subpacket; + if (!copy) { // the data is someone elses memory @@ -138,8 +74,7 @@ m_ownCopy = true; // allocate memory for the copy - // NOTE: We should use an allocater for this instead of normal new - m_packet = (EQPacketFormatRaw*)new uint8_t[length]; + m_packet = new uint8_t[length]; // copy the data memcpy((void*)m_packet, (void*)packet, length); @@ -152,73 +87,38 @@ init(); } -void EQPacketFormat::init() +void EQProtocolPacket::init() { - // finish initialization iff the packet has a valid CRC32 - if (validate()) - { - m_postSkipData = ((uint8_t*)m_packet) + m_packet->skip() + 2; - - // calculate the length of the rest of the data - m_postSkipDataLength = m_length - (m_postSkipData - ((uint8_t*)m_packet)); - - // get the location of the payload - m_payload = m_packet->payload(); + // Get the net op code. Leave in network order. + m_netOp = *(uint16_t*)(m_packet); + + // get the location of the payload + m_payload = &m_packet[2]; - // calculate the lenght of the payload (length - diff - len(checkSum)) - m_payloadLength = m_length - (m_payload - ((uint8_t*)m_packet)) - 4; + // calculate the length of the payload (len - net op - crc) + m_payloadLength = m_length - 2 - (hasCRC() ? 2 : 0); - // make a local copy of the arq to speed up comparisons - m_arq = eqntohuint16(&m_postSkipData[2]); - } - else - { - m_postSkipData = 0; - m_postSkipDataLength = 0; - m_payload = 0; - m_payloadLength = 0; - m_arq = 0; - } -} - -bool EQPacketFormat::validate() -{ - m_isValid = ((m_packet != NULL) && - ((m_length >= 4) && (crc32() == calcCRC32()))); - return m_isValid; + // make a local copy of the arq to speed up comparisons + m_arqSeq = eqntohuint16(m_payload); } -QString EQPacketFormat::headerFlags(const QString& prefix, - bool brief) const +QString EQProtocolPacket::headerFlags(const QString& prefix, bool brief) const { QString tmp; - if (m_isValid) + if (brief) { - if (brief) - tmp = prefix + ": "; - else - tmp = prefix + " Hdr (" + QString::number(flagsHi(), 16) + ", " - + QString::number(flagsLo(), 16) + "): "; - - tmp += m_packet->headerFlags("", true); - - if (!brief) - { - if (isARQ()) - tmp += QString("arq: ") + QString::number(arq(), 16) + ", "; - - if (isFragment()) - tmp += QString("FragSeq: ") + QString::number(fragSeq(), 16) - + ", FragCur: " + QString::number(fragCur(), 16) - + ", FragTot: " + QString::number(fragTot(), 16) + ", "; + tmp = prefix + ": "; + } + else + { + tmp = prefix + " NetOpCode: " + QString::number(getNetOpCode(), 16); - tmp += QString("Opcode: ") - + QString::number(eqntohuint16(payload()), 16); + if (hasArqSeq()) + { + tmp += (", Seq: " + QString::number(arqSeq())); } } - else - tmp = prefix + ": INVALID CRC32! Possible non-EQ packet?!"; return tmp; } @@ -244,6 +144,9 @@ // note whether or not this object ownw the memory m_ownCopy = copy; + // No session yet + m_sessionKey = 0; + // initialize the object init(ipdata); } @@ -253,6 +156,7 @@ { // note whether or not this object ownw the memory m_ownCopy = copy; + m_sessionKey = packet.getSessionKey(); if (copy) { @@ -332,9 +236,10 @@ length -= sizeof (struct udphdr); data += (sizeof (struct udphdr)); m_rawpayload = data; + m_rawpayloadSize = length; - // initialize underlying EQPacketFormat with the UDP payload - EQPacketFormat::init((EQPacketFormatRaw*)data, length, false); + // initialize underlying EQProtocolPacket with the UDP payload + EQProtocolPacket::init(data, length, false); } QString EQUDPIPPacketFormat::headerFlags(bool brief) const @@ -344,5 +249,5 @@ (const char*)getIPv4SourceA(), getSourcePort(), (const char*)getIPv4DestA(), getDestPort()); - return EQPacketFormat::headerFlags(tmp, brief); + return EQProtocolPacket::headerFlags(tmp, brief); } Index: spells_en2spellsh.pl =================================================================== RCS file: /cvsroot/seq/showeq/src/spells_en2spellsh.pl,v retrieving revision 1.5 retrieving revision 1.5.12.1 diff -u -d -r1.5 -r1.5.12.1 --- spells_en2spellsh.pl 2 Oct 2003 04:02:23 -0000 1.5 +++ spells_en2spellsh.pl 9 Feb 2005 07:07:39 -0000 1.5.12.1 @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/usr/bin/perl # spells_en2spellsh.pl # ShowEQ Distributed under GPL Index: messageshell.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/Attic/messageshell.cpp,v retrieving revision 1.1.4.5 retrieving revision 1.1.4.6 diff -u -d -r1.1.4.5 -r1.1.4.6 --- messageshell.cpp 7 Nov 2004 23:10:22 -0000 1.1.4.5 +++ messageshell.cpp 9 Feb 2005 07:07:37 -0000 1.1.4.6 @@ -337,12 +337,18 @@ for (int inp = 0; inp < 21; inp ++) { - tempStr.sprintf("He has %s (icn:%i)", inspt->itemNames[inp], inspt->icons[inp]); - m_messages->addMessage(MT_Inspect, tempStr); + if (strnlen(inspt->itemNames[inp], 64) > 0) + { + tempStr.sprintf("He has %s (icn:%i)", inspt->itemNames[inp], inspt->icons[inp]); + m_messages->addMessage(MT_Inspect, tempStr); + } } - tempStr.sprintf("His info: %s", inspt->mytext); - m_messages->addMessage(MT_Inspect, tempStr); + if (strnlen(inspt->mytext, 200) > 0) + { + tempStr.sprintf("His info: %s", inspt->mytext); + m_messages->addMessage(MT_Inspect, tempStr); + } } void MessageShell::logOut(const uint8_t*, size_t, uint8_t) @@ -686,8 +692,16 @@ message = "ExpAA: " + Commanate(player->altexp); m_messages->addMessage(MT_Player, message); + message.sprintf("Group: %s %s %s %s %s %s", player->groupMembers[0], + player->groupMembers[1], + player->groupMembers[2], + player->groupMembers[3], + player->groupMembers[4], + player->groupMembers[5]); + m_messages->addMessage(MT_Player, message); + int buffnumber; - for (buffnumber=0;buffnumber<15;buffnumber++) + for (buffnumber=0;buffnumber<20;buffnumber++) { if (player->buffs[buffnumber].spellid && player->buffs[buffnumber].duration) { @@ -697,6 +711,19 @@ m_messages->addMessage(MT_Player, message); } } + + message = "LDoN Earned Guk Points: " + Commanate(player->ldon_guk_points); + m_messages->addMessage(MT_Player, message); + message = "LDoN Earned Mira Points: " + Commanate(player->ldon_mir_points); + m_messages->addMessage(MT_Player, message); + message = "LDoN Earned MMC Points: " + Commanate(player->ldon_mmc_points); + m_messages->addMessage(MT_Player, message); + message = "LDoN Earned Ruj Points: " + Commanate(player->ldon_ruj_points); + m_messages->addMessage(MT_Player, message); + message = "LDoN Earned Tak Points: " + Commanate(player->ldon_tak_points); + m_messages->addMessage(MT_Player, message); + message = "LDoN Unspent Points: " + Commanate(player->ldon_avail_points); + m_messages->addMessage(MT_Player, message); } void MessageShell::increaseSkill(const uint8_t* data) @@ -717,6 +744,17 @@ m_messages->addMessage(MT_Player, tempStr); } +void MessageShell::consent(const uint8_t* data, size_t, uint8_t dir) +{ + const consentResponseStruct* consent = (const consentResponseStruct*)data; + + m_messages->addMessage(MT_General, + QString("Consent: %1 %4 permission to drag %2's corpse in %3") + .arg(QString::fromUtf8(consent->consentee)) + .arg(QString::fromUtf8(consent->consenter)) + .arg(QString::fromUtf8(consent->corpseZoneName)) + .arg((consent->allow == 1 ? "granted" : "denied"))); +} void MessageShell::consMessage(const uint8_t* data, size_t, uint8_t dir) Index: util.h =================================================================== RCS file: /cvsroot/seq/showeq/src/util.h,v retrieving revision 1.13.6.2 retrieving revision 1.13.6.3 diff -u -d -r1.13.6.2 -r1.13.6.3 --- util.h 16 Jan 2004 20:22:11 -0000 1.13.6.2 +++ util.h 9 Feb 2005 07:07:40 -0000 1.13.6.3 @@ -64,8 +64,8 @@ void diagFileWriteFail(QString filename); void diagFileReadFail(QString filename); -uint32_t calcCRC32(const uint8_t* p, - uint32_t length); +uint32_t calcCRC32(const uint8_t* p, uint32_t length); +uint16_t calcCRC16(uint8_t* p, uint32_t length, uint32_t seed); // Templatized function to generate a string representing the bit pattern // of the passed in value. Index: packet.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/packet.cpp,v retrieving revision 1.62.6.4 retrieving revision 1.62.6.5 diff -u -d -r1.62.6.4 -r1.62.6.5 --- packet.cpp 7 Nov 2004 23:10:23 -0000 1.62.6.4 +++ packet.cpp 9 Feb 2005 07:07:37 -0000 1.62.6.5 @@ -38,10 +38,12 @@ // The following defines are used to diagnose packet handling behavior // this define is used to diagnose packet processing (in dispatchPacket mostly) -//#define PACKET_PROCESS_DIAG 3 // verbosity level 0-n +//#define PACKET_PROCESS_DIAG 3 +// verbosity level 0-n // this define is used to diagnose cache handling (in dispatchPacket mostly) -//#define PACKET_CACHE_DIAG 3 // verbosity level (0-n) +//#define PACKET_CACHE_DIAG 3 +// verbosity level (0-n) // diagnose opcode DB issues //#define PACKET_OPCODEDB_DIAG 1 @@ -52,7 +54,7 @@ // Packet version is a unique number that should be bumped every time packet // structure (ie. encryption) changes. It is checked by the VPacket feature // (currently the date of the last packet structure change) -#define PACKETVERSION 40100 +#define PACKETVERSION 40101 //---------------------------------------------------------------------- // constants @@ -81,7 +83,7 @@ QString ip, QString mac_address, bool realtime, - bool session_tracking, + bool sessionTrackingFlag, bool recordPackets, bool playbackPackets, int8_t playbackSpeed, @@ -96,7 +98,7 @@ m_ip(ip), m_mac(mac_address), m_realtime(realtime), - m_session_tracking(session_tracking), + m_session_tracking(sessionTrackingFlag), m_recordPackets(recordPackets), m_playbackPackets(playbackPackets), m_playbackSpeed(playbackSpeed) @@ -164,6 +166,10 @@ SIGNAL(numPacket(int, int)), this, SIGNAL(numPacket(int, int))); + connect(m_client2WorldStream, + SIGNAL(sessionKey(uint32_t, EQStreamID, uint32_t)), + this, + SLOT(dispatchSessionKey(uint32_t, EQStreamID, uint32_t))); // Setup world -> client stream m_world2ClientStream = new EQPacketStream(world2client, DIR_Server, @@ -194,6 +200,14 @@ SIGNAL(numPacket(int, int)), this, SIGNAL(numPacket(int, int))); + connect(m_world2ClientStream, + SIGNAL(sessionTrackingChanged(uint8_t)), + this, + SIGNAL(sessionTrackingChanged(uint8_t))); + connect(m_world2ClientStream, + SIGNAL(sessionKey(uint32_t, EQStreamID, uint32_t)), + this, + SLOT(dispatchSessionKey(uint32_t, EQStreamID, uint32_t))); // Setup client -> zone stream m_client2ZoneStream = new EQPacketStream(client2zone, DIR_Client, @@ -227,6 +241,18 @@ SIGNAL(numPacket(int, int)), this, SIGNAL(numPacket(int, int))); + connect(m_client2ZoneStream, + SIGNAL(sessionTrackingChanged(uint8_t)), + this, + SIGNAL(sessionTrackingChanged(uint8_t))); + connect(m_client2ZoneStream, + SIGNAL(closing()), + this, + SLOT(closeStream())); + connect(m_client2ZoneStream, + SIGNAL(sessionKey(uint32_t, EQStreamID, uint32_t)), + this, + SLOT(dispatchSessionKey(uint32_t, EQStreamID, uint32_t))); // Setup zone -> client stream m_zone2ClientStream = new EQPacketStream(zone2client, DIR_Server, @@ -273,6 +299,10 @@ SIGNAL(closing()), this, SLOT(closeStream())); + connect(m_zone2ClientStream, + SIGNAL(sessionKey(uint32_t, EQStreamID, uint32_t)), + this, + SLOT(dispatchSessionKey(uint32_t, EQStreamID, uint32_t))); // Initialize convenient streams array m_streams[client2world] = m_client2WorldStream; @@ -335,6 +365,9 @@ emit filterChanged(); } + // Flag session tracking properly on streams + session_tracking(sessionTrackingFlag); + // if running setuid root, then give up root access, since the PacketCapture // is the only thing that needed it. if ((geteuid() == 0) && (getuid() != geteuid())) @@ -555,59 +588,22 @@ void EQPacket::dispatchPacket(int size, unsigned char *buffer) { #ifdef DEBUG_PACKET - debug ("dispatchPacket()"); + debug ("EQPacket::dispatchPacket()"); #endif /* DEBUG_PACKET */ /* Setup variables */ // Create an object to parse the packet EQUDPIPPacketFormat packet(buffer, size, false); - // signal a new packet - emit newPacket(packet); - - /* Chat and Login Server Packets, Discard for now */ - if ((packet.getDestPort() == ChatServerPort) || - (packet.getSourcePort() == ChatServerPort)) - return; - - if ((packet.getDestPort() == WorldServerChatPort) || - (packet.getSourcePort() == WorldServerChatPort)) - return; - - if (((packet.getDestPort() >= LoginServerMinPort) && - (packet.getDestPort() <= LoginServerMaxPort)) || - (packet.getSourcePort() >= LoginServerMinPort) && - (packet.getSourcePort() <= LoginServerMaxPort)) - return; - -#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1) - seqDebug("%s", (const char*)packet.headerFlags((PACKET_PROCESS_DIAG < 3))); -#endif - - if (!packet.isValid()) - { - seqWarn("INVALID PACKET: Bad CRC32 [%s:%d -> %s:%d] seq %04x len %d crc32 (%08x != %08x)", - (const char*)packet.getIPv4SourceA(), packet.getSourcePort(), - (const char*)packet.getIPv4DestA(), packet.getDestPort(), - packet.seq(), - packet.getRawPacketLength(), - packet.crc32(), packet.calcCRC32()); - return; - } + dispatchPacket(packet); - /* discard pure ack/req packets and non valid flags*/ - if (packet.flagsHi() < 0x02 || packet.flagsHi() > 0x46 || size < 10) - { -#if defined(PACKET_PROCESS_DIAG) - seqDebug("discarding packet %s:%d ==>%s:%d flagsHi=%d size=%d", - (const char*)packet.getIPv4SourceA(), packet.getSourcePort(), - (const char*)packet.getIPv4DestA(), packet.getDestPort(), - packet.flagsHi(), size); - seqDebug("%s", (const char*)packet.headerFlags(false)); -#endif - return; - } + // signal a new packet. This has to be at the end so that the session is + // filled in if possible, so that it can report on crc errors properly + emit newPacket(packet); +} +void EQPacket::dispatchPacket(EQUDPIPPacketFormat& packet) +{ /* Client Detection */ if (m_detectingClient && packet.getSourcePort() == WorldServerGeneralPort) { @@ -625,39 +621,92 @@ emit clientChanged(m_client_addr); seqInfo("Client Detected: %s", (const char*)m_ip); } - /* end client detection */ + /* end client detection */ + /* Find the stream we are sending this to */ + EQPacketStream* stream; + /* Chat and Login Server Packets, Discard for now */ + if ((packet.getDestPort() == ChatServerPort) || + (packet.getSourcePort() == ChatServerPort)) + return; - if (packet.getSourcePort() == WorldServerChatPort) - { - dispatchWorldChatData(packet.payloadLength(), packet.payload(), DIR_Server); - + if ((packet.getDestPort() == WorldServerChatPort) || + (packet.getSourcePort() == WorldServerChatPort)) return; - } - else if (packet.getDestPort() == WorldServerChatPort) - { - dispatchWorldChatData(packet.payloadLength(), packet.payload(), DIR_Client); - + + if (((packet.getDestPort() >= LoginServerMinPort) && + (packet.getDestPort() <= LoginServerMaxPort)) || + (packet.getSourcePort() >= LoginServerMinPort) && + (packet.getSourcePort() <= LoginServerMaxPort)) return; - } - /* stream identification */ if (packet.getIPv4SourceN() == m_client_addr) { if (packet.getDestPort() == WorldServerGeneralPort) - m_client2WorldStream->handlePacket(packet); + stream = m_client2WorldStream; else - m_client2ZoneStream->handlePacket(packet); + stream = m_client2ZoneStream; } else if (packet.getIPv4DestN() == m_client_addr) { if (packet.getSourcePort() == WorldServerGeneralPort) - m_world2ClientStream->handlePacket(packet); + stream = m_world2ClientStream; else - m_zone2ClientStream->handlePacket(packet); + stream = m_zone2ClientStream; + } + else + { + return; } + // Fill in the session id of the packet in case people need it and only + // have the packet. This is crappy, but logging doesn't have access to + // the stream the packet came from. + packet.setSessionKey(stream->getSessionKey()); + +#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1) + seqDebug("%s", (const char*)packet.headerFlags((PACKET_PROCESS_DIAG < 3))); +#endif + + // Check CRC. Have to ask the stream to do it, since the packet doesn't know + // it's sessionKey yet. + if (packet.hasCRC()) + { + uint16_t calcedCRC = stream->calculateCRC(packet); + + if (calcedCRC != packet.crc() && packet.getSessionKey() != 0) + { + seqWarn("INVALID PACKET: Bad CRC [%s:%d -> %s:%d] netOp %04x seq %04x len %d crc (%04x != %04x)", + (const char*)packet.getIPv4SourceA(), packet.getSourcePort(), + (const char*)packet.getIPv4DestA(), packet.getDestPort(), + packet.getNetOpCode(), + packet.arqSeq(), + packet.getUDPPayloadLength(), + packet.crc(), calcedCRC); + return; + } + } + + /* discard pure ack/req packets */ + if (packet.getNetOpCode() == OP_KeepAlive || + packet.getNetOpCode() == OP_SessionStatRequest || + packet.getNetOpCode() == OP_SessionStatResponse || + packet.getNetOpCode() == OP_Resend || + packet.getNetOpCode() == OP_Ack) + { +#if defined(PACKET_PROCESS_DIAG) + seqDebug("discarding packet %s:%d ==>%s:%d netopcode=%04x size=%d", + (const char*)packet.getIPv4SourceA(), packet.getSourcePort(), + (const char*)packet.getIPv4DestA(), packet.getDestPort(), + packet.getNetOpCode(), size); +#endif + return; + } + + // Send it to the stream handler. + stream->handlePacket(packet); + return; } /* end dispatchPacket() */ @@ -721,6 +770,15 @@ emit clientPortLatched(m_clientPort); } +void EQPacket::dispatchSessionKey(uint32_t sessionId, EQStreamID streamid, + uint32_t sessionKey) +{ + m_client2WorldStream->receiveSessionKey(sessionId, streamid, sessionKey); + m_world2ClientStream->receiveSessionKey(sessionId, streamid, sessionKey); + m_client2ZoneStream->receiveSessionKey(sessionId, streamid, sessionKey); + m_zone2ClientStream->receiveSessionKey(sessionId, streamid, sessionKey); +} + /////////////////////////////////////////// //EQPacket::dispatchWorldChatData // note this dispatch gets just the payload Index: packetstream.h =================================================================== RCS file: /cvsroot/seq/showeq/src/packetstream.h,v retrieving revision 1.1.6.1 retrieving revision 1.1.6.2 diff -u -d -r1.1.6.1 -r1.1.6.2 --- packetstream.h 7 Dec 2003 06:30:44 -0000 1.1.6.1 +++ packetstream.h 9 Feb 2005 07:07:39 -0000 1.1.6.2 @@ -26,7 +26,7 @@ #include <netinet/in.h> class EQUDPIPPacketFormat; -class EQPacketFormat; +class EQProtocolPacket; class EQPacketOPCodeDB; class EQPacketOPCode; @@ -48,7 +48,7 @@ // is the expected arq. This results in the check for followers to only // taking amortized constant time (as opposed to the O(log N) of map::find() // or constant average time of the hash find methods. -typedef std::map<uint16_t, EQPacketFormat* > EQPacketMap; +typedef std::map<uint16_t, EQProtocolPacket* > EQPacketMap; //---------------------------------------------------------------------- // EQPacketStream @@ -74,6 +74,10 @@ bool connect2(const QString& opcodeName, const char* payload, EQSizeCheckType szt, const QObject* receiver, const char* member); + void receiveSessionKey(uint32_t sessionId, EQStreamID streamid, + uint32_t sessionKey); + uint16_t calculateCRC(EQProtocolPacket& packet); + uint32_t getSessionKey() const { return m_sessionKey; } public slots: void handlePacket(EQUDPIPPacketFormat& pf); @@ -92,8 +96,10 @@ // this signals a change in the session tracking state void sessionTrackingChanged(uint8_t); - void lockOnClient(in_port_t serverPort, in_port_t clientPort); + + // Signal a new session key being received + void sessionKey(uint32_t sessionId, EQStreamID streadid, uint32_t sessionKey); // used for net_stats display void cacheSize(int, int); @@ -104,14 +110,9 @@ protected: void resetCache(); - void setCache(uint16_t serverArqSeq, EQPacketFormat& packet); + void setCache(uint16_t serverArqSeq, EQProtocolPacket& packet); void processCache(); - void processFragment(EQPacketFormat& pf); - void initDecode(); - void stopDecode(); - uint8_t* decodeOpCode(uint8_t *data, size_t *len, uint16_t& opCode); - void decodePacket(uint8_t *data, size_t len, uint16_t opCode); - void processPayload(uint8_t* data, size_t len); + void processPacket(EQProtocolPacket& packet, bool subpacket); void dispatchPacket(const uint8_t* data, size_t len, uint16_t opCode, const EQPacketOPCode* opcodeEntry); @@ -133,6 +134,11 @@ // Fragment handling EQPacketFragmentSequence m_fragment; + // Session info + uint32_t m_sessionId; + uint32_t m_sessionKey; + uint32_t m_maxLength; + // encryption int64_t m_decodeKey; bool m_validKey; Index: util.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/util.cpp,v retrieving revision 1.20.6.2 retrieving revision 1.20.6.3 diff -u -d -r1.20.6.2 -r1.20.6.3 --- util.cpp 16 Jan 2004 20:22:11 -0000 1.20.6.2 +++ util.cpp 9 Feb 2005 07:07:40 -0000 1.20.6.3 @@ -963,4 +963,25 @@ return crc ^ 0xFFFFFFFF; } +////////////////////////////////////////////////////////////////// +// Seeded CRC16 needed by the packet layer. +uint16_t calcCRC16(uint8_t* p, uint32_t length, uint32_t seed) +{ +#include "crctab.h" + unsigned long crc = 0L ^ 0xffffffff; + + // CRC each byte of the seed + crc = crc >> 8 ^ crctab[(seed ^ crc) & 0xFF]; + crc = crc >> 8 ^ crctab[(seed >> 8 ^ crc) & 0xFF]; + crc = crc >> 8 ^ crctab[(seed >> 16 ^ crc) & 0xFF]; + crc = crc >> 8 ^ crctab[(seed >> 24 ^ crc) & 0xFF]; + + // Then crc the buffer + while(length--) + { + crc = crc >> 8 ^ crctab[(*(p++) ^ crc) & 0xFF]; + } + + return crc ^ 0xffffffffL; +} Index: messageshell.h =================================================================== RCS file: /cvsroot/seq/showeq/src/Attic/messageshell.h,v retrieving revision 1.1.4.2 retrieving revision 1.1.4.3 diff -u -d -r1.1.4.2 -r1.1.4.3 --- messageshell.h 13 Dec 2003 00:49:42 -0000 1.1.4.2 +++ messageshell.h 9 Feb 2005 07:07:37 -0000 1.1.4.3 @@ -50,6 +50,7 @@ void simpleMessage(const uint8_t* cmsg, size_t, uint8_t); void specialMessage(const uint8_t* smsg, size_t, uint8_t); void guildMOTD(const uint8_t* gmotd, size_t, uint8_t); + void consent(const uint8_t* consent, size_t, uint8_t); void moneyOnCorpse(const uint8_t* money); void moneyUpdate(const uint8_t* money); void moneyThing(const uint8_t* money); Index: player.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/player.cpp,v retrieving revision 1.42.6.7 retrieving revision 1.42.6.8 diff -u -d -r1.42.6.7 -r1.42.6.8 --- player.cpp 7 Nov 2004 23:10:24 -0000 1.42.6.7 +++ player.cpp 9 Feb 2005 07:07:39 -0000 1.42.6.8 @@ -374,7 +374,7 @@ //Added by Halcyon int buffnumber; const struct spellBuff *buff; - for (buffnumber=0;buffnumber<15;buffnumber++) + for (buffnumber=0;buffnumber<20;buffnumber++) { if (player->buffs[buffnumber].spellid && player->buffs[buffnumber].duration) { @@ -851,9 +851,9 @@ updateLastChanged(); emit changeItem(this, tSpawnChangedPosition); - emit newSpeed(hypot( hypot( (pupdate->deltaX*8), - (pupdate->deltaY*8)), - (pupdate->deltaZ*8))); + emit newSpeed((int)lrint(hypot( hypot( (pupdate->deltaX*80), + (pupdate->deltaY*80)), + (pupdate->deltaZ*80)))); static uint8_t count = 0; @@ -1063,8 +1063,8 @@ } else if (level() < 23) { // - greenRange = -7; - cyanRange = -5; + greenRange = -8; + cyanRange = -6; } else if (level() < 27) { // Index: packetformat.h =================================================================== RCS file: /cvsroot/seq/showeq/src/packetformat.h,v retrieving revision 1.1.6.2 retrieving revision 1.1.6.3 diff -u -d -r1.1.6.2 -r1.1.6.3 --- packetformat.h 24 Sep 2004 04:25:53 -0000 1.1.6.2 +++ packetformat.h 9 Feb 2005 07:07:38 -0000 1.1.6.3 @@ -42,269 +42,134 @@ // Forward declarations class QString; -//---------------------------------------------------------------------- -// enumerated types -enum EQPacketHeaderFlagsHi -{ - seqEnd = 0x80, - closingHi = 0x40, - seqStart = 0x20, - asq = 0x10, - fragment = 0x08, - closingLo = 0x04, - ackRequest = 0x02, -}; - -enum EQPacketHeaderFlagsLo -{ - ackResponse = 0x04, - specAckRequest = 0x01 -}; - -//---------------------------------------------------------------------- -// EQPacketFormatRaw - -// Why EQPacketFormatRaw, because the EQPacket name was taken... ;-) -// (/thank Xylor for the format of the packets) -// (/thank fee for helping me to understand the format) -// Some simplifying assumptions based on observed packet behavior -// that are used to optimize access -// 1) the arq bit is always set when the fragment bit is set -// 2) the arq is always after 2 bytes past the embedded ack/req data. -// 3) the fragment stuff is always 4 bytes after the embedded ack/req data -// based on 1). -// -#pragma pack(1) -class EQPacketFormatRaw -{ - public: - // accessors to check for individual flasg - bool isARQ() const { return m_flagsHi.m_arq; } - bool isClosingLo() const { return m_flagsHi.m_closingLo; } - bool isFragment() const { return m_flagsHi.m_fragment; } - bool isASQ() const { return m_flagsHi.m_asq; } - bool isSEQStart() const { return m_flagsHi.m_seqStart; } - bool isClosingHi() const { return m_flagsHi.m_closingHi; } - bool isSEQEnd() const { return m_flagsHi.m_seqEnd; } - bool isARSP() const { return m_flagsLo.m_arsp; } - bool isSpecARQ() const { return m_flagsLo.m_specARQ; } - bool isNAK() const { return m_flagsLo.m_nak; } - - // Check flag against the EQPacketHeaderFlag{Hi, Lo} values - bool checkFlagHi(uint8_t mask) const - { return ((m_flagsHiVal & mask) != 0); } - bool checkFlagLo(uint8_t mask) const - { return ((m_flagsLoVal & mask) != 0); } - - // accessors to return the flag values - uint8_t flagsHi() const { return m_flagsHiVal; } - uint8_t flagsLo() const { return m_flagsLoVal; } - - // number of uint8_t's to skip when examining packets - uint8_t skip() const - { - return ((uint8_t)m_flagsLo.m_skip + - (isARSP() ? 2 : 0) + - (isNAK() ? 2 : 0)); - } - - // The following accessors are only valid if the corresponding - // flag is set. - uint16_t seq() const { return eqntohuint16(&m_data[0]); } - uint16_t arsp() const { return eqntohuint16(&m_data[2]); } - uint16_t nak() const { return eqntohuint16(&m_data[4]); } - uint16_t arq() const - { return eqntohuint16(&m_data[2 + skip()]); } - uint16_t fragSeq() const - { return eqntohuint16(&m_data[4 + skip()]); } - uint16_t fragCur() const - { return eqntohuint16(&m_data[6 + skip()]); } - uint16_t fragTot() const - { return eqntohuint16(&m_data[8 + skip()]); } - uint8_t asqHigh() const { return m_data[10 + skip()]; } - uint8_t asqLow() const { return m_data[11 + skip()]; } - uint32_t crc32(uint16_t len) const - { return (len >= 6) ? eqntohuint32(&m_data[len - 2 - 4]) : 0xDEADBEEF; } - - uint8_t* payload() - { - return m_data + // m_data is already passed the flag bytes - (skip() // skip arsp, specARQ data - + (isASQ() ? 1 : 0) // skip asqHigh - + (isARQ() ? 2 : 0) // skip arq - + ((isASQ() && isARQ()) ? 1 : 0) // skip asqLow - + (isFragment() ? 6 : 0) // skip fragment data - + 2 // seq - ); - } - - QString headerFlags(const QString& prefix = "", - bool brief = false) const; +// Net Op Codes in net order. Underneath, there are actually channels +// 0-3, where 0x0900 is OP_Packet on channel 0, 0x0a00 is OP_Packet on +// channel 1, 0x0b00 is OP_Packet on channel 2, etc. and the same +// with OP_Oversized for 0x0d00-0x1000. Only channel 0 seems used. +static const uint16_t OP_SessionRequest = 0x0100; +static const uint16_t OP_SessionResponse = 0x0200; +static const uint16_t OP_Combined = 0x0300; +static const uint16_t OP_SessionDisconnect = 0x0500; +static const uint16_t OP_KeepAlive = 0x0600; +static const uint16_t OP_SessionStatRequest = 0x0700; +static const uint16_t OP_SessionStatResponse= 0x0800; +static const uint16_t OP_Packet = 0x0900; +static const uint16_t OP_Oversized = 0x0d00; +static const uint16_t OP_Resend = 0x1100; +static const uint16_t OP_Ack = 0x1500; +static const uint16_t OP_AppCombined = 0x1900; - private: - union - { - struct - { - unsigned int m_unknown1:1; // 0x01 = ? - unsigned int m_arq:1; // 0x02 = arq - unsigned int m_closingLo:1; // 0x04 = closingLo - unsigned int m_fragment:1; // 0x08 = fragment - unsigned int m_asq:1; // 0x10 = asq - unsigned int m_seqStart:1; // 0x20 = seqStart - unsigned int m_closingHi:1; // 0x40 = closingHi - unsigned int m_seqEnd:1; // 0x80 = seqEnd - } m_flagsHi; - uint8_t m_flagsHiVal; - }; - union - { - struct - { - unsigned int m_specARQ:1; // 0x01 = speckARQ - unsigned int m_unknown1:1; // 0x02 = ? - unsigned int m_arsp:1; // 0x04 = ARSP - unsigned int m_nak:1; // 0x08 = NAK? - unsigned int m_skip:4; // amount of data to skip - } m_flagsLo; - uint8_t m_flagsLoVal; - }; - uint8_t m_data[]; -}; -#pragma pack() +// Detect app opcode vs net opcode by the 2nd byte. 0x00 = net opcode. +#define IS_APP_OPCODE(uint16) (((uint16) & 0x00ff) != 0x0000) +#define IS_NET_OPCODE(uint16) (((uint16) & 0x00ff) == 0x0000) //---------------------------------------------------------------------- -// EQPacketFormat -class EQPacketFormat +// EQProtocolPacket +// A wrapper around a byte array which is the wire data for an +// specific protocol packet. Protocol packets have an owning EQUDPIPPacket +// which has the udp/ip packet info. They may not necessaryily directly be +// the payload of the udp/ip packet, since one udp/ip packet may be +// multiple protocol packets, combined together. +class EQProtocolPacket { public: // constructors - EQPacketFormat() - : m_packet(NULL), m_length(0), - m_postSkipData(NULL), m_postSkipDataLength(0), - m_payload(NULL), m_payloadLength(0), - m_arq(0), m_ownCopy(false), m_isValid(false) + EQProtocolPacket() + : m_packet(NULL), + m_length(0), + m_payload(NULL), + m_payloadLength(0), + m_arqSeq(0), + m_ownCopy(false), + m_isValid(false), + m_subpacket(false) { } - EQPacketFormat(uint8_t* data, - uint16_t length, - bool copy = false) - { - init((EQPacketFormatRaw*)data, length, copy); - } - - EQPacketFormat(EQPacketFormatRaw* packet, - uint16_t length, - bool copy = false) + EQProtocolPacket(uint8_t* packet, uint16_t length, + bool copy=false, bool subpacket=false) { - init(packet, length, copy); + init(packet, length, copy, subpacket); } - EQPacketFormat(EQPacketFormat& packet, bool copy = false); + EQProtocolPacket(EQProtocolPacket& packet, bool copy = false); // destructor - ~EQPacketFormat(); + ~EQProtocolPacket(); // operators - EQPacketFormat& operator=(const EQPacketFormat& packet); - - // accessors to check for individual flags - bool isARQ() const { return m_packet->isARQ(); } - bool isClosingLo() const { return m_packet->isClosingLo(); } - bool isFragment() const { return m_packet->isFragment(); } - bool isASQ() const { return m_packet->isASQ(); } - bool isSEQStart() const { return m_packet->isSEQStart(); } - bool isClosingHi() const { return m_packet->isClosingHi(); } - bool isSEQEnd() const { return m_packet->isSEQEnd(); } - bool isARSP() const { return m_packet->isARSP(); } - bool isNAK() const { return m_packet->isNAK(); } - bool isSpecARQ() const - { return m_packet->isSpecARQ(); } - - // Check flag against the EQPacketHeaderFlag{Hi, Lo} values - bool checkFlagHi(uint8_t mask) const - { return m_packet->checkFlagHi(mask); } - bool checkFlagLo(uint8_t mask) const - { return m_packet->checkFlagLo(mask); } + EQProtocolPacket& operator=(const EQProtocolPacket& packet); - // accessors to return the flag values - uint8_t flagsHi() const { return m_packet->flagsHi(); } - uint8_t flagsLo() const { return m_packet->flagsLo(); } + uint16_t getNetOpCode() const { return m_netOp; } - uint8_t skip() const { return m_packet->skip(); } + bool hasArqSeq() const + { + return getNetOpCode() == OP_Packet || getNetOpCode() == OP_Oversized; + } + uint16_t arqSeq() const { return m_arqSeq; } - uint16_t seq() const { return m_packet->seq(); } + bool hasCRC() const + { + // Subpackets don't have CRC, the outer packet does. + if (m_subpacket) return false; - // The following accessors are only valid if the corresponding - // flag is set. - uint16_t arsp() const { return m_packet->arsp(); } - uint16_t arq() const { return m_arq; } - uint16_t fragSeq() const - { return eqntohuint16(&m_postSkipData[4]); } - uint16_t fragCur() const - { return eqntohuint16(&m_postSkipData[6]); } - uint16_t fragTot() const - { return eqntohuint16(&m_postSkipData[8]); } - uint8_t asqHigh() const { return m_postSkipData[10]; } - uint8_t asqLow() const { return m_postSkipData[11]; } - uint32_t crc32() const - { - // return CRC in the appropriate endianess or DEADBEEF if invalid - return (m_length >= 4) ? eqntohuint32(&((uint8_t*)m_packet)[m_length - 4]) : 0xDEADBEEF; + switch (m_netOp) + { + case OP_SessionStatRequest: + case OP_SessionStatResponse: + case OP_Combined: + case OP_Packet: + case OP_Oversized: + case OP_AppCombined: + return true; + default : + return IS_APP_OPCODE(m_netOp); + } } - uint32_t calcCRC32() const - { - // calculate the CRC on the packet data, up to but not including the - // CRC32 stored at the end or return different invalid packet value - // then crc32() above. - return (m_length >= 4) ? ::calcCRC32((uint8_t*)m_packet, m_length - 4) : 0xFEEDDEAD; + uint16_t crc() const + { + // return CRC in the appropriate endianess or DEAD if invalid + return (m_length >= 2) ? eqntohuint16(&m_packet[m_length - 2]) : 0xDEAD; } - bool isValid() const { return m_isValid; } - bool validate(); + bool isSubpacket() const { return m_subpacket; } uint8_t* payload() const { return m_payload; } uint16_t payloadLength() const { return m_payloadLength; } - - const EQPacketFormatRaw* getRawPacket() const { return m_packet; } - uint16_t getRawPacketLength() const { return m_length; } - - QString headerFlags(const QString& prefix = "", - bool brief = false) const; + uint8_t* rawPayload() const { return m_packet; } + uint16_t rawPayloadLength() const { return m_length; } protected: void init(); - void init(EQPacketFormatRaw* packet, - uint16_t length, - bool copy = false); + void init(uint8_t* packet, uint16_t length, + bool copy=false, bool subpacket=false); + + QString headerFlags(const QString& prefix, bool brief = false) const; private: - EQPacketFormatRaw* m_packet; + uint8_t* m_packet; // raw packet uint16_t m_length; - uint8_t* m_postSkipData; - uint16_t m_postSkipDataLength; - uint8_t* m_payload; + uint16_t m_netOp; + uint8_t* m_payload; // packet without netop, crc. Mem owned by m_packet. uint16_t m_payloadLength; - uint16_t m_arq; // local copy to speed up comparisons + uint16_t m_arqSeq; // local copy to speed up comparisons bool m_ownCopy; bool m_isValid; + bool m_subpacket; }; -inline bool operator<(const EQPacketFormat& p1, - const EQPacketFormat& p2) +inline bool operator<(const EQProtocolPacket& p1, const EQProtocolPacket& p2) { - return p1.arq() < p2.arq(); + return p1.arqSeq() < p2.arqSeq(); } -inline bool operator==(const EQPacketFormat& p1, - const EQPacketFormat& p2) +inline bool operator==(const EQProtocolPacket& p1, const EQProtocolPacket& p2) { - return p1.arq() == p2.arq(); + return p1.arqSeq() == p2.arqSeq(); } //---------------------------------------------------------------------- // EQUDPIPPacketFormat -class EQUDPIPPacketFormat : public EQPacketFormat +class EQUDPIPPacketFormat : public EQProtocolPacket { public: // constructors @@ -326,7 +191,8 @@ in_port_t getSourcePortN() const { return m_udp->uh_sport; } in_port_t getDestPort() const { return ntohs(m_udp->uh_dport); } in_port_t getDestPortN() const { return m_udp->uh_dport; } - uint8_t * getUDPPayload() const { return m_rawpayload; } + uint8_t* getUDPPayload() const { return m_rawpayload; } + uint32_t getUDPPayloadLength() const { return m_rawpayloadSize; } // IP accessors uint8_t getIPVersion() const { return (uint8_t)m_ip->ip_v; } @@ -351,6 +217,9 @@ QString headerFlags(bool brief = false) const; + uint32_t getSessionKey() const { return m_sessionKey; } + void setSessionKey(uint32_t sessionKey) { m_sessionKey = sessionKey; } + protected: void init(uint8_t* data); @@ -360,6 +229,8 @@ struct udphdr *m_udp; bool m_ownCopy; uint8_t* m_rawpayload; + uint32_t m_rawpayloadSize; + uint32_t m_sessionKey; }; #endif // _PACKETFORMAT_H_ Index: packetlog.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/packetlog.cpp,v retrieving revision 1.1.6.5 retrieving revision 1.1.6.6 diff -u -d -r1.1.6.5 -r1.1.6.6 --- packetlog.cpp 7 Nov 2004 23:10:24 -0000 1.1.6.5 +++ packetlog.cpp 9 Feb 2005 07:07:38 -0000 1.1.6.6 @@ -35,6 +35,9 @@ QString tempStr; tempStr.sprintf("[OPCode: %#.04x]", opCode); + // Flags are gone? Combined and implicit don't make sense anymore and + // nothing is compressed or encrypted at this point... + /* if (opCode & FLAG_DECODE) { tempStr += " "; @@ -47,6 +50,7 @@ if (opCode & FLAG_IMPLICIT) tempStr += "[FLAG_IMPLICIT]"; } + */ return tempStr; } @@ -225,33 +229,33 @@ m_out << QDateTime::currentDateTime().toString(m_timeDateFormat) << " [" << sourceStr << ":" << QString::number(packet.getSourcePort()) << "->" << destStr << ":" << QString::number(packet.getDestPort()) - << "] [Size: " << QString::number(packet.getRawPacketLength()) << "]" + << "] [Size: " << QString::number(packet.getUDPPayloadLength()) << "]" << endl; - if (packet.isValid()) - { - const EQPacketFormatRaw* raw = packet.getRawPacket(); - if (raw) - m_out << raw->headerFlags(QString(), false) << endl; + uint16_t calcedCRC; - if (packet.payloadLength() >= 2) - { - QString tempStr; - uint16_t opcode = *(uint16_t*)(packet.payload()); - m_out << opCodeToString(opcode) << endl; - } + if (! packet.hasCRC() || + packet.crc() == (calcedCRC = ::calcCRC16( + packet.rawPayload(), packet.rawPayloadLength()-2, + packet.getSessionKey()))) + { + m_out << packet.headerFlags(false) << endl; } else - m_out << "[BAD CRC32 (" << QString::number(packet.calcCRC32(), 16) - << " != " << QString::number(packet.crc32()) - << ")! Possibly non-EQ packet?! ]" << endl; + { + m_out << "[BAD CRC (" << QString::number(calcedCRC, 16) + << " != " << QString::number(packet.crc(), 16) + << ")! Sessions crossed or unitialized or non-EQ packet! ]" << endl; + m_out << "[SessionKey: " << QString::number(packet.getSessionKey(), 16) << + "]" << endl; + } flush(); // make sure there is a len before attempting to output it - if (packet.getRawPacketLength()) - outputData(packet.getRawPacketLength(), - (const uint8_t*)packet.getRawPacket()); + if (packet.payloadLength()) + outputData(packet.getUDPPayloadLength(), + (const uint8_t*)packet.getUDPPayload()); else m_out << endl; Index: packetfragment.cpp =================================================================== RCS file: /cvsroot/seq/showeq/src/packetfragment.cpp,v retrieving revision 1.1.6.1 retrieving revision 1.1.6.2 diff -u -d -r1.1.6.1 -r1.1.6.2 --- packetfragment.cpp 7 Dec 2003 06:30:44 -0000 1.1.6.1 +++ packetfragment.cpp 9 Feb 2005 07:07:38 -0000 1.1.6.2 @@ -17,10 +17,7 @@ //---------------------------------------------------------------------- // Macros -//#define DEBUG_PACKET -//#undef DEBUG_PACKET - -// diagnose structure size changes +// diagnose fragmentation problems //#define PACKET_PROCESS_FRAG_DIAG //---------------------------------------------------------------------- @@ -31,11 +28,9 @@ EQPacketFragmentSequence::EQPacketFragmentSequence() : m_streamid(unknown_stream), m_data(0), + m_totalLength(0), m_dataSize(0), - m_dataAllocSize(0), - m_seq(0), - m_current(0), - m_total(0) + m_dataAllocSize(0) { } @@ -44,11 +39,9 @@ EQPacketFragmentSequence::EQPacketFragmentSequence(EQStreamID streamid) : m_streamid(streamid), m_data(0), + m_totalLength(0), m_dataSize(0), - m_dataAllocSize(0), - m_seq(0), - m_current(0), - m_total(0) + m_dataAllocSize(0) { } @@ -64,103 +57,78 @@ // Reset the fragment sequence void EQPacketFragmentSequence::reset() { +#ifdef PACKET_PROCESS_FRAG_DIAG + debug ("EQPacketFragmentSequence::reset() stream %d (complete fragment? %s)", + m_streamid, (isComplete() ? "yes" : "no")); +#endif m_dataSize = 0; - m_seq = 0; - m_current = 0; - m_total = 0; + m_totalLength = 0; } //////////////////////////////////////////////////// // Add a fragment to the sequence -void EQPacketFragmentSequence::addFragment(EQPacketFormat& pf) +void EQPacketFragmentSequence::addFragment(EQProtocolPacket& packet) { -#ifdef DEBUG_PACKET - debug ("EQPacketFragmentSequence::addFragment()"); -#endif /* DEBUG_PACKET */ - #ifdef PACKET_PROCESS_FRAG_DIAG - seqDebug("EQPacketFragmentSequence::addFragment(): pf.arq 0x%04x, pf.fragSeq 0x%04x, pf.fragCur 0x%04x, pf.fragTot 0x%04x", pf.arq(), pf.fragSeq(), pf.fragCur(), pf.fragTot()); -#endif /* PACKET_PROCESS_FRAG_DIAG */ + debug ("EQPacketFragmentSequence::addFragment() stream %d", m_streamid); +#endif - // fragments with ASQ signify the beginning of a new series - // warn if previous series is incomplete - // clear and allocate space for the new series - if (pf.isASQ()) + // If dataSize isn't filled in, this is first fragment. Need to alloc. + if (m_dataSize == 0) { - if (m_dataSize) - { - if (!pf.fragSeq() == 0) // surpress WARNING for duplicate SEQStart/fragment start (e.g.0x3a) - { - seqWarn("EQPacketFragmentSequence::addFragment(): WARNING OpCode 0x%04x will not be processed due to loss", - eqntohuint16(m_data)); - seqWarn("EQPacketFragmentSequence::addFragment(): recieved new fragment seq 0x%04x before completion of 0x%04x", - pf.fragSeq(), m_seq); - } - } + // Buffer length is on the wire past the sequence number. + m_totalLength = eqntohuint32(&(packet.payload()[2])); - size_t needs = (pf.fragTot() * pf.payloadLength()); - if (needs > m_dataAllocSize) + if (m_totalLength == 0) { - delete [] m_data; - m_dataAllocSize = needs; - m_data = new uint8_t[m_dataAllocSize]; // should be an over estimate + seqWarn("Oversized packet fragment requested buffer of size 0 on stream %d OpCode %04x seq %04x", + m_streamid, *(uint16_t*)(&packet.payload()[6]), packet.arqSeq()); } - - m_dataSize = 0; - m_seq = pf.fragSeq(); - m_current = pf.fragCur(); - m_total = pf.fragTot(); - + else if (m_totalLength > m_dataAllocSize) + { + // Buffer isn't big enough. Enlargen it. + if (m_data) + { + delete[] m_data; + } + m_dataAllocSize = m_totalLength; + m_data = new uint8_t[m_dataAllocSize]; #ifdef PACKET_PROCESS_FRAG_DIAG - seqDebug("EQPacketFragmentSequence::addFragment(): Allocating %d bytes for fragmentSeq %d, stream %d, OpCode 0x%04x", - (pf.fragTot() * pf.payloadLength()), pf.fragSeq(), m_streamid, eqntohuint16(m_data)); + seqDebug("EQPacketFragmentSequence::addFragment(): Allocating %d bytes for seq %04x, stream %d, OpCode 0x%04x", + m_dataAllocSize, packet.arqSeq(), m_streamid, + *(uint16_t*)(&packet.payload()[6])); #endif - } - - if (m_data != NULL) - { - if (pf.fragSeq() != m_seq || pf.fragCur() != m_current) - { - seqWarn("EQPacketFragmentSequence::addFragment: WARNING OpCode 0x%04x will not be processed due to loss", - eqntohuint16(m_data)); - seqWarn("EQPacketFragmentSequence::addFragment(): recieved Out-Of-Order fragment seq 0x%04x (0x%04x) expected 0x%04x", - pf.fragCur(), pf.fragSeq(), m_current); - return; - } - else if ((m_dataSize + pf.payloadLength()) > m_dataAllocSize) - { - // theoretically should never get here, but... - // calculate needed size - size_t needs = m_dataSize + pf.payloadLength(); - - // allocate new buffer - uint8_t* newData = new uint8_t[needs]; - - // copy old data - memcpy((void*)newData, (void*)m_data, m_dataSize); - - // delete old data - delete [] m_data; - - m_dataAllocSize = needs; - m_data = newData; - } - else - { - memcpy((void*)(m_data + m_dataSize), (void*)pf.payload(), pf.payloadLength()); - - m_dataSize += pf.payloadLength(); - m_current = pf.fragCur()+1; - - return; } + + // Now put in this fragment. Payload starts after seq, unknown, + // and alloc size. #ifdef PACKET_PROCESS_FRAG_DIAG + seqDebug("EQPacketFragmentSequence::addFragment(): Putting initial %d byte fragment into buffer for seq %04x, stream %d, OpCode 0x%04x", + packet.payloadLength() - 6, packet.arqSeq(), m_streamid, + *(uint16_t*)(&packet.payload()[6])); +#endif + memcpy(m_data, &packet.payload()[6], packet.payloadLength()-6); + m_dataSize = packet.payloadLength() - 6; } else { - seqWarn("EQPacketFragmentSequence::addFragment(): recieved fragment component (fragSeq 0x%04x, fragCur 0x%04x) before fragment start", - pf.fragSeq(), pf.fragCur()); + // Add this fragment to the buffer. Payload starts immediately after seq. +#ifdef PACKET_PROCESS_FRAG_DIAG + seqDebug("EQPacketFragmentSequence::addFragment(): Putting %d byte fragment into buffer for seq %04x, stream %d, OpCode 0x%04x", + packet.payloadLength() - 2, packet.arqSeq(), m_streamid, + *(uint16_t*)(m_data)); #endif + + if (m_data + m_dataSize + packet.payloadLength() - 2 > m_data + m_dataAllocSize) + { + seqFatal("!!!! EQPacketFragmentSequence::addFragment(): buffer overflow adding in new fragment to buffer with seq %04x on stream %d, opcode %04x. Buffer is size %d and has been filled up to %d, but tried to add %d more!", + packet.arqSeq(), m_streamid, *(uint16_t*)(m_data), + m_dataAllocSize, m_dataSize, packet.payloadLength() - 2); + } + + memcpy(m_data + m_dataSize, + &packet.payload()[2], packet.payloadLength() - 2); + m_dataSize += (packet.payloadLength() - 2); } } Index: packetfragment.h =================================================================== RCS file: /cvsroot/seq/showeq/src/packetfragment.h,v retrieving revision 1.1 retrieving revision 1.1.6.1 diff -u -d -r1.1 -r1.1.6.1 --- packetfragment.h 25 Oct 2003 00:21:00 -0000 1.1 +++ packetfragment.h 9 Feb 2005 07:07:38 -0000 1.1.6.1 @@ -15,7 +15,7 @@ #include "packetcommon.h" -class EQPacketFormat; +class EQProtocolPacket; //---------------------------------------------------------------------- // EQPacketFragmentSequence @@ -26,7 +26,7 @@ EQPacketFragmentSequence(EQStreamID streamid); ~EQPacketFragmentSequence(); void reset(); - void addFragment(EQPacketFormat& pf); + void addFragment(EQProtocolPacket& pf); bool isComplete(); uint8_t* data(); @@ -35,16 +35,14 @@ protected: EQStreamID m_streamid; uint8_t *m_data; + uint32_t m_totalLength; size_t m_dataSize; - uint16_t m_dataAllocSize; - uint16_t m_seq; - uint16_t m_current; - uint16_t m_total; + uint32_t m_dataAllocSize; }; inline bool EQPacketFragmentSequence::isComplete() { - return m_current == m_total; + return m_dataSize != 0 && m_totalLength == m_dataSize; } inline uint8_t* EQPacketFragmentSequence::data() Index: everquest.h =================================================================== RCS file: /cvsroot/s... [truncated message content] |