示例#1
0
文件: guild.cpp 项目: brainiac/showeq
void GuildMgr::readGuildList()
{
	QFile guildsfile(guildsFileName);

	m_guildMap.clear();
	if (guildsfile.open(QIODevice::ReadOnly))
	{
		while (!guildsfile.atEnd())
		{
			char szGuildName[64] = {0};
			
			guildsfile.readBlock(szGuildName, sizeof(szGuildName));
			
			// seqDebug("GuildMgr::readGuildList - read guild '%s'", szGuildName);
			m_guildMap.push_back(QString::fromUtf8(szGuildName));
		}

		guildsfile.close();
		seqInfo("GuildMgr: Guildsfile loaded");
	}
	else
		seqWarn("GuildMgr: Could not load guildsfile, %s", (const char*)guildsFileName);
}
示例#2
0
bool OPCodeXmlContentHandler::startElement(const QString&, const QString&, 
					   const QString& name, 
					   const QXmlAttributes& attr)
{
  if (name == "opcode")
  {
    bool ok = false;

    // get the index of the id attribute
    int index = attr.index("id");
    if (index == -1)
    {
      seqWarn("OPCodeXmlContentHandler::startElement(): opcode element without id!");
	      
      return false; // this is an error, something is wrong
    }

    // the id attribute is the opcode value
    uint16_t opcode = attr.value(index).toUShort(&ok, 16);

#if 0 // ZBTEMP
    opcode += 2;
#endif 

    if (!ok)
    {
      seqWarn("OPCodeXmlContentHandler::startElement(): opcode '%s' failed to convert to uint16_t (result: %#04x)",
	      attr.value(index).latin1(), opcode);

      return false; // this is an error
    }

    // get the index of the name attribute
    index = attr.index("name");
    
    // if name attribute was found, set the opcode objects name
    if (index == -1)
    {
      seqWarn("OPCodeXmlContentHandler::startElement(): opcode %#04x missing name parameter!",
	      opcode);

      return false;
    }

    // add/create the new opcode object
    m_currentOPCode = m_opcodeDB.add(opcode, attr.value(index));

    if (!m_currentOPCode)
    {
      seqWarn("Failed to add opcode %04x", opcode);
      return false;
    }


    // get the index of the updated attribute
    index = attr.index("updated");
    
    // if the updated attribute was found, set the objects updated field
    if (index != -1)
      m_currentOPCode->setUpdated(attr.value(index));

    // get the index of the implicitlen attribute
    index = attr.index("implicitlen");

    // if implicitlen attribute was found, set the objects implicitLen field
    if (index != -1)
      m_currentOPCode->setImplicitLen(attr.value(index).toUShort());

    return true;
  }

  if ((name == "comment") && (m_currentOPCode))
  {
    // clear any current comment
    m_currentComment = "";
    m_inComment = true;

    return true;
  }

  if ((name == "payload") && (m_currentOPCode))
  {
    // create a new payload object and make it the current one
    m_currentPayload = new EQPacketPayload();

    // add the payload object to the opcode
    m_currentOPCode->append(m_currentPayload);

    // check for direction attribute
    int index = attr.index("dir");

    // if an index attribute exists, then use it
    if (index != -1)
    {
      QString value = attr.value(index);

      if (value == "both")
	m_currentPayload->setDir(DIR_Client | DIR_Server);
      else if (value == "server")
	m_currentPayload->setDir(DIR_Server);
      else if (value == "client")
	m_currentPayload->setDir(DIR_Client);
    }

    // get the typename attribute
    index = attr.index("typename");

    // if a typename attribute exist, then set the payload type
    if (index != -1)
    {
      QString value = attr.value(index);
      
      if (!value.isEmpty())
      {
	if (!m_currentPayload->setType(m_typeDB, value))
	  seqWarn("Unknown payload typename '%s' for opcode '%04x'",
		  value.latin1(), m_currentOPCode->opcode());
      }
    }

    // attempt to retrieve the sizechecktype
    index = attr.index("sizechecktype");

    // if a sizechecktype exists, then set the payload size check type
    if (index != -1)
    {
      QString value = attr.value(index);

      if (value.isEmpty() || (value == "none"))
	m_currentPayload->setSizeCheckType(SZC_None);
      else if (value == "match")
	m_currentPayload->setSizeCheckType(SZC_Match);
      else if (value == "modulus")
	m_currentPayload->setSizeCheckType(SZC_Modulus);
    }

    return true;
  }

  return true;
}
示例#3
0
void SpawnMonitor::loadSpawnPoints()
{
  QString fileName;
  
  fileName = m_zoneName + ".sp";

  QFileInfo fileInfo = 
    m_dataLocMgr->findExistingFile("spawnpoints", fileName, false);

  if (!fileInfo.exists())
  {
    seqWarn("Can't find spawn point file %s", 
	   (const char*)fileInfo.absFilePath());
    return;
  }
  
  fileName = fileInfo.absFilePath();

  QFile spFile(fileName);
  
  if (!spFile.open(IO_ReadOnly))
  {
    seqWarn( "Can't open spawn point file %s", (const char*)fileName );
    return;
  }
  
  QTextStream input( &spFile );
  
  int16_t x, y, z;
  unsigned long diffTime;
  uint32_t count;
  QString name;

  while (!input.atEnd())
  {
    input >> x;
    input >> y;
    input >> z;
    input >> diffTime;
    input >> count;
    name = input.readLine();
    name = name.stripWhiteSpace();
    
    EQPoint	loc(x, y, z);
    SpawnPoint*	p = new SpawnPoint( 0, loc, name, diffTime, count );
    if (p)
    {
      QString key = p->key();
      
      if (!m_points.find(key))
      {
	m_points.insert(key, p);
	emit newSpawnPoint(p);
      }
      else
      {
	seqWarn("Warning: spawn point key already in use!");
	delete p;
      }
    }
  }

  seqInfo("Loaded spawn points: %s", (const char*)fileName);
  m_modified = false;
}
示例#4
0
void SpawnMonitor::saveSpawnPoints()
{
  // only save if modified
  if (!m_modified)
    return;

  if ( !m_zoneName.length() )
  {
    seqWarn("Zone name not set in 'SpawnMonitor::saveSpawnPoints'!" );
    return;
  }
  
  QString fileName;
  
  fileName = m_zoneName + ".sp";

  QFileInfo fileInfo = 
    m_dataLocMgr->findWriteFile("spawnpoints", fileName, false);

  fileName = fileInfo.absFilePath();

  QString newName = fileName + ".new";
  QFile spFile( newName );
  
  if (!spFile.open(IO_WriteOnly))
  {
    seqWarn("Failed to open %s for writing", (const char*)newName);
    return;
  }
  
  QTextStream output(&spFile);
  
  QAsciiDictIterator<SpawnPoint> it( m_points );
  SpawnPoint* sp;
  
  while ((sp = it.current()))
  {
    ++it;
    output	<< sp->x()
		<< " "
		<< sp->y()
		<< " "
		<< sp->z()
		<< " "
		<< (unsigned long)sp->diffTime()
		<< " "
		<< sp->count()
		<< " "
		<< sp->name()
		<< '\n';
  }
  
  spFile.close();
  
  QFileInfo fi( spFile );
  QFile old( fileName );
  QDir dir( fi.dir() );
  QString backupName = fileName + ".bak";
  
  if (old.exists())
  {
    if (dir.rename( fileName, backupName))
    {
      if (!dir.rename( newName, fileName))
	seqWarn( "Failed to rename %s to %s", 
		(const char*)newName, (const char*)fileName);
    }
  }
  else
  {
    if (!dir.rename(newName, fileName))
      seqWarn("Failed to rename %s to %s", 
	     (const char*)newName, (const char*)fileName);
  }
  m_modified = false;
  seqInfo("Saved spawn points: %s", (const char*)fileName);
}
示例#5
0
bool EQStr::load(const QString& fileName)
{
  // clear out any existing contents
  m_messageStrings.clear();

  // create a QFile on the file
  QFile formatFile(fileName);

  // open the file read only
  if (!formatFile.open(IO_ReadOnly))
  {
    seqWarn("EQStr: Failed to open '%s'",
	    fileName.latin1());
    return false;
  }

  // allocate a QCString large enough to hold the entire file
  QCString textData(formatFile.size() + 1);
  
  // read in the entire file
  formatFile.readBlock(textData.data(), textData.size());
  
  // construct a regex to deal with either style line termination
  QRegExp lineTerm("[\r\n]{1,2}");
  
  // split the data into lines at the line termination
  QStringList lines = QStringList::split(lineTerm, 
					 QString::fromUtf8(textData), false);
  
  // start iterating over the lines
  QStringList::Iterator it = lines.begin();
  
  // first is the magic id string
  QString magicString = (*it++);
  int spc;
  uint32_t formatId;
  QString formatString;
  uint32_t maxFormatId = 0;
  
  // next skip over the count, etc...
  it++;
  
  // now iterate over the format lines
  for (; it != lines.end(); ++it)
  {
    // find the beginning space
    spc = (*it).find(' ');
    
    // convert the beginnign of the string to a ULong
    formatId = (*it).left(spc).toULong();
    
    if (formatId > maxFormatId) 
      maxFormatId = formatId;
    
    // insert the format string into the dictionary.
    m_messageStrings.insert(formatId, new QString((*it).mid(spc+1)));    
  }

  // note that strings are loaded
  m_loaded = true;

  seqInfo("Loaded %d message strings from '%s' maxFormat=%d",
	  m_messageStrings.count(), fileName.latin1(),
	  maxFormatId);
  
  return true;
}
示例#6
0
/////////////////////////////////////////////////////
// Handle a protocol level packet. This could be either a top-level
// EQUDPIPPacket or a subpacket that is just an EQProtocolPacket. Either way
// we use net opcodes here.
void EQPacketStream::processPacket(EQProtocolPacket& packet, bool /*isSubpacket*/)
{
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
  seqDebug("-->EQPacketStream::processPacket, subpacket=%s on stream %s (%d)",
    (isSubpacket ? "true" : "false"), EQStreamStr[m_streamid], m_streamid);
#endif

  if (IS_APP_OPCODE(packet.getNetOpCode()))
  {
    // This is an app-opcode directly on the wire with no wrapping protocol
    // information. Weird, but whatever gets the stream read, right?
	dispatchPacket(packet.payload(), packet.payloadLength(), 
      packet.getNetOpCode(), m_opcodeDB.find(packet.getNetOpCode()));
    return;
  }

  // Process the net opcode
  switch (packet.getNetOpCode())
  {
    case OP_Combined:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: found combined packet (net op: %04x, size %d) on stream %s (%d). Unrolling.", 
        packet.getNetOpCode(), packet.payloadLength(), 
        EQStreamStr[m_streamid], m_streamid);
#endif

      // Rolled up multiple packets inside this packet. Need to unroll them
      // and process them individually. subpacket starts after the net opcode.
      uint8_t* subpacket = packet.payload();

      while (subpacket < packet.payload() + packet.payloadLength())
      {
        // Length specified first on the wire.
        uint8_t subpacketLength = subpacket[0];

        // Move past the length
        subpacket++;

        // OpCode (in net order)
        uint16_t subOpCode = *(uint16_t*)subpacket;
        
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif
        
        // Opcode is next. Net opcode or app opcode?
        if (subOpCode == 0)
        {
          // App opcode < 0x00ff. Skip the first byte and dispatch the app
          // opcode appropriately
          subpacket++;

          subOpCode = *(uint16_t*)subpacket;

#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
          seqDebug("EQPacket: processing unrolled special app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
            subpacketLength-3, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // App opcode. Dispatch it, skipping opcode.
          dispatchPacket(&subpacket[2], subpacketLength-2, 
            subOpCode, m_opcodeDB.find(subOpCode));

        }
        else if (IS_NET_OPCODE(subOpCode))
        {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
          seqDebug("EQPacket: processing unrolled net opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
            subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Net opcode. false = copy. true = subpacket
          EQProtocolPacket spacket(subpacket, subpacketLength, false, true);

          processPacket(spacket, true);
        }
        else
        {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // App opcode. Dispatch it, skipping opcode.
          dispatchPacket(&subpacket[2], subpacketLength-2, 
            subOpCode, m_opcodeDB.find(subOpCode));
        }
        subpacket += subpacketLength;
      }
    }
    break;
    case OP_AppCombined:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: found appcombined packet (net op: %04x, size %d) on stream %s (%d). Unrolling.", 
        packet.getNetOpCode(), packet.payloadLength(), 
        EQStreamStr[m_streamid], m_streamid);
#endif

      // Multiple app op codes in the same packet. Need to unroll and dispatch
      // them.
      uint8_t* subpacket = packet.payload();

      while (subpacket < packet.payload() + packet.payloadLength())
      {
        // Length specified first on the wire.
        uint8_t subpacketLength = subpacket[0];

        // Move past the length
        subpacket++;

        if (subpacketLength != 0xff)
        {
          // Dispatch app op code using given packet length. Net order!
          uint16_t subOpCode = *(uint16_t*)(subpacket);

          // Handle 3 byte opcodes properly
          if (subOpCode == 0)
          {
            // 3 byte opcode. Drop the first byte, opcode is byte 2 and 3
            subpacket++;
            subpacketLength--;
            subOpCode = *(uint16_t*)(subpacket);
          }

#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Dispatch, skipping op code.
          dispatchPacket(&subpacket[2], subpacketLength-2, 
            subOpCode, m_opcodeDB.find(subOpCode));

          // Move ahead
          subpacket += subpacketLength;
        }
        else
        {
          // If original length is 0xff, it means it is a long one. The length
          // is 2 bytes and next.
          uint16_t longOne = eqntohuint16(subpacket);
 
          // Move past the 2 byte length
          subpacket += 2;

          // OpCode next. Net order for op codes.
          uint16_t subOpCode = *(uint16_t*)subpacket;

          // Handle 3 byte opcodes properly
          if (subOpCode == 0)
          {
            // 3 byte opcode. Drop the first byte, opcode is byte 2 and 3
            subpacket++;
            longOne--;
            subOpCode = *(uint16_t*)(subpacket);
          }
          
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          longOne, EQStreamStr[m_streamid], m_streamid, subOpCode);
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          longOne-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Dispatch, skipping op code.
          dispatchPacket(&subpacket[2], longOne-2, 
            subOpCode, m_opcodeDB.find(subOpCode));

          // Move ahead
          subpacket += longOne;
        }
      }
    }
    break;
    case OP_Packet:
    {
      // Normal unfragmented sequenced packet.
      uint16_t seq = packet.arqSeq();
      emit seqReceive(seq, (int)m_streamid);

      // Future packet?
      if (seq == m_arqSeqExp)
      {
        // Expected packet.
        m_arqSeqExp++;
        emit seqExpect(m_arqSeqExp, (int)m_streamid);

        // OpCode next. Net order for op codes.
        uint16_t subOpCode = *(uint16_t*)(packet.payload());
       
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
        seqDebug("SEQ: Found next sequence number in data stream %s (%d), incrementing expected seq, %04x (op code %04x, sub opcode %04x)", 
          EQStreamStr[m_streamid], m_streamid, seq, 
          packet.getNetOpCode(), subOpCode);
#endif

        // Opcode is next. Net opcode or app opcode?
        if (subOpCode == 0)
        {
          // App opcode < 0x00ff. Skip the first byte and dispatch the app
          // opcode appropriately
          subOpCode = *(uint16_t*)&packet.payload()[1];

#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
          seqDebug("EQPacket: special app opcode extracted for opcode 0000 on stream %s (%d). Opcode %04x", 
            EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // App opcode. Dispatch it, skipping opcode.
          dispatchPacket(&packet.payload()[3], packet.payloadLength()-3, 
            subOpCode, m_opcodeDB.find(subOpCode));

        }
        else if (IS_NET_OPCODE(subOpCode))
        {
          // Net opcode. false = no copy. true = subpacket.
          EQProtocolPacket spacket(packet.payload(), 
            packet.payloadLength(), false, true);

          processPacket(spacket, true);
        }
        else
        {
          // App opcode. Dispatch, skipping opcode.
          dispatchPacket(&packet.payload()[2], packet.payloadLength()-2,
            subOpCode, m_opcodeDB.find(subOpCode));
        }
      }
      else if ((seq > m_arqSeqExp && 
                  seq < (uint32_t(m_arqSeqExp + arqSeqWrapCutoff))) ||
               seq < (int32_t(m_arqSeqExp) - arqSeqWrapCutoff))
      {
        // Yeah, future packet. Push it on the packet cache.
#ifdef PACKET_PROCESS_DIAG
        seqDebug("SEQ: out of order sequence %04x stream %s (%d) expecting %04x, sending to cache, %04d",
          seq, EQStreamStr[m_streamid], m_streamid, 
          m_arqSeqExp, m_cache.size());
#endif
        setCache(seq, packet);
      }
      else
      {
#ifdef PACKET_PROCESS_DIAG
        // Past packet outside the cut off
        seqWarn("SEQ: received sequenced %spacket outside expected window on stream %s (%d) netopcode=%04x size=%d. Expecting seq=%04x got seq=%04x, window size %d, dropping packet as in the past.", 
          (isSubpacket ? "sub" : ""),
          EQStreamStr[m_streamid], m_streamid,
          packet.getNetOpCode(), packet.payloadLength(), 
          m_arqSeqExp, seq, arqSeqWrapCutoff);
#endif
      }
    }
    break;
    case OP_Oversized:
    {
      // Fragmented sequenced data packet.
      uint16_t seq = packet.arqSeq();
      emit seqReceive(seq, (int)m_streamid);

      // Future packet?
      if (seq == m_arqSeqExp)
      {
        // Expected packet.
        m_arqSeqExp++;
        emit seqExpect(m_arqSeqExp, (int)m_streamid);
       
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
        seqDebug("SEQ: Found next sequence number in data stream %s (%d), incrementing expected seq, %04x (op code %04x)", 
          EQStreamStr[m_streamid], m_streamid, seq, packet.getNetOpCode());
#endif

        // Push the fragment on.
        m_fragment.addFragment(packet);

        if (m_fragment.isComplete())
        {
          // OpCode from fragment. In network order.
          uint16_t fragOpCode = *(uint16_t*)(m_fragment.data());

#ifdef PACKET_PROCESS_DIAG
        seqDebug("SEQ: Completed oversized app packet on stream %s with seq %04x, total size %d opcode %04x", 
          EQStreamStr[m_streamid], seq, m_fragment.size()-2, fragOpCode);
#endif

          // dispatch fragment. Skip opcode.
          if (fragOpCode == 0)
          {
            // Special app opcode. Skip first byte and op is byte 2 and 3.
            fragOpCode = *(uint16_t*)(&m_fragment.data()[1]);

#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
            seqDebug("EQPacket: special app opcode on completed fragment for opcode 0000 on stream %s (%d). Opcode %04x", 
            EQStreamStr[m_streamid], m_streamid, fragOpCode);
#endif

            dispatchPacket(&m_fragment.data()[3], m_fragment.size()-3,
              fragOpCode, m_opcodeDB.find(fragOpCode)); 
          }
          else
          {
            dispatchPacket(&m_fragment.data()[2], m_fragment.size()-2,
              fragOpCode, m_opcodeDB.find(fragOpCode)); 
          }

          m_fragment.reset();
        }
      }
      else if ((seq > m_arqSeqExp && 
                  seq < (uint32_t(m_arqSeqExp + arqSeqWrapCutoff))) ||
               seq < (int32_t(m_arqSeqExp) - arqSeqWrapCutoff))
      {
        // Yeah, future packet. Push it on the packet cache.
#ifdef PACKET_PROCESS_DIAG
        seqDebug("SEQ: out of order sequence %04x stream %s (%d) expecting %04x, sending to cache, %04d",
          seq, EQStreamStr[m_streamid], m_streamid, 
          m_arqSeqExp, m_cache.size());
#endif
        setCache(seq, packet);
      }
      else
      {
#ifdef PACKET_PROCESS_DIAG
        // Past packet outside the cut off
        seqWarn("SEQ: received sequenced %spacket outside expected window on stream %s (%d) netopcode=%04x size=%d. Expecting seq=%04x got seq=%04x, window size %d, dropping packet as in the past.", 
          (isSubpacket ? "sub" : ""),
          EQStreamStr[m_streamid], m_streamid,
          packet.getNetOpCode(), packet.payloadLength(), 
          m_arqSeqExp, seq, arqSeqWrapCutoff);
#endif
      }
    }
    break;
    case OP_SessionRequest:
    {
      // Session request from client to server.
      // 
      // Sanity check the size. Don't assume any packet we see is an EQ
      // session request, since we're gonna cause a huge freakin' malloc
      // on the maxlength of the session which for some reason some people
      // won't enjoy!
      if (packet.payloadLength() != sizeof(SessionRequestStruct))
      {
          // Either SessionRequestStruct changed or this isn't a session
          // request.
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
          seqDebug("EQPacket: Ignoring SessionRequest %s:%u->%s:%u with invalid size %d.",
            ((EQUDPIPPacketFormat&) packet).getIPv4SourceA().ascii(),
            ((EQUDPIPPacketFormat&) packet).getSourcePort(),
            ((EQUDPIPPacketFormat&) packet).getIPv4DestA().ascii(),
            ((EQUDPIPPacketFormat&) packet).getDestPort(),
            packet.payloadLength());
#endif
          break;
      }

      // Pull off session request information
      SessionRequestStruct* request = (SessionRequestStruct*) packet.payload();

      m_sessionId = eqntohuint32((uint8_t*)&(request->sessionId));
      m_maxLength = eqntohuint32((uint8_t*)&(request->maxLength));

      // Sanity check the max length requested
      if (m_maxLength > maxPacketSize)
      {
        seqWarn("EQPacket: SessionRequest wanted a max packet size of %d which is above our sane max packet size of %d. Using our max",
          m_maxLength, maxPacketSize);

        m_maxLength = maxPacketSize;
      }

      emit maxLength((int) m_maxLength, (int) m_streamid);

#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionRequest found, resetting expected seq, stream %s (%d) (session tracking %s)",
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif

#if defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionRequest %s:%u->%s:%u, sessionId %u maxLength %u, awaiting key for stream %s (%d)",
        ((EQUDPIPPacketFormat&) packet).getIPv4SourceA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getSourcePort(),
        ((EQUDPIPPacketFormat&) packet).getIPv4DestA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getDestPort(),
        m_sessionId, m_maxLength, EQStreamStr[m_streamid], m_streamid);
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 1)
      seqDebug("EQPacket: SessionRequest contents: unknown %u, sessionId %u, maxLength %u",
        eqntohuint32((uint8_t*)&(request->unknown0000)), 
        m_sessionId, m_maxLength);
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 2)
      seqDebug("EQPacket: Raw SessionRequest: %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x",
        packet.payload()[0], packet.payload()[1], packet.payload()[2], 
        packet.payload()[3], packet.payload()[4], packet.payload()[5], 
        packet.payload()[6], packet.payload()[7], packet.payload()[8], 
        packet.payload()[9], packet.payload()[10], packet.payload()[11]);
#endif

      m_arqSeqExp = 0;
      m_arqSeqFound = true;

      if (m_session_tracking_enabled)
      {
        // Save off client port for the stream so we can match against it
        // later. SessionRequest should always be an outer protocol packet
        // so we can cast it to EQUDPIPPacketFormat to get the ip headers.
        m_sessionClientPort = ((EQUDPIPPacketFormat&) packet).getSourcePort();
      }
    }
    break;
    case OP_SessionResponse:
    {
      // Session response from server

      // Sanity check the size. Don't assume any packet we see is an EQ
      // session response, since we're gonna cause a huge freakin' malloc
      // on the maxlength of the session which for some reason some people
      // won't enjoy!
      if (packet.payloadLength() != sizeof(SessionResponseStruct))
      {
          // Either SessionResponseStruct changed or this isn't a session
          // response.
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
          seqDebug("EQPacket: Ignoring SessionResponse %s:%u->%s:%u with invalid size %d.",
            ((EQUDPIPPacketFormat&) packet).getIPv4SourceA().ascii(),
            ((EQUDPIPPacketFormat&) packet).getSourcePort(),
            ((EQUDPIPPacketFormat&) packet).getIPv4DestA().ascii(),
            ((EQUDPIPPacketFormat&) packet).getDestPort(),
            packet.payloadLength());
#endif
          break;
      }

      // Pull off session response information
      SessionResponseStruct* response = 
        (SessionResponseStruct*) packet.payload();

      m_maxLength = eqntohuint32((uint8_t*)&(response->maxLength));
      m_sessionKey = eqntohuint32((uint8_t*)&(response->key));
      m_sessionId = eqntohuint32((uint8_t*)&(response->sessionId));

      // Sanity check the max length requested
      if (m_maxLength > maxPacketSize)
      {
        seqWarn("EQPacket: SessionResponse wanted a max packet size of %d which is above our sane max packet size of %d. Using our max",
          m_maxLength, maxPacketSize);

        m_maxLength = maxPacketSize;
      }

      emit maxLength((int) m_maxLength, (int) m_streamid);

#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionResponse found %s:%u->%s:%u, resetting expected seq, stream %s (%d) (session tracking %s)",
        ((EQUDPIPPacketFormat&) packet).getIPv4SourceA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getSourcePort(),
        ((EQUDPIPPacketFormat&) packet).getIPv4DestA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getDestPort(),
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif
      
#if defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionResponse sessionId %u maxLength %u, key is %u for stream %s (%d)",
        m_sessionId, m_maxLength, m_sessionKey, 
        EQStreamStr[m_streamid], m_streamid);
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 1)
      seqDebug("EQPacket: SessionResponse contents: sessionId %u, key %u, unknown %u, unknown %u, maxLength %u, unknown %u",
        m_sessionId, m_sessionKey, 
        eqntohuint16((uint8_t*)&(response->unknown0008)),
        response->unknown0010, m_maxLength,
        eqntohuint32((uint8_t*) &(response->unknown0015)));
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 2)
      seqDebug("EQPacket: Raw SessionResponse: %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x",
        packet.payload()[0], packet.payload()[1], packet.payload()[2], 
        packet.payload()[3], packet.payload()[4], packet.payload()[5], 
        packet.payload()[6], packet.payload()[7], packet.payload()[8], 
        packet.payload()[9], packet.payload()[10], packet.payload()[11],
        packet.payload()[12], packet.payload()[13], packet.payload()[14], 
        packet.payload()[15], packet.payload()[16], packet.payload()[17], 
        packet.payload()[18]);
#endif

      // Provide key to corresponding stream from this session/stream
      emit sessionKey(m_sessionId, m_streamid, m_sessionKey);

      m_arqSeqExp = 0;
      m_arqSeqFound = true;

      // Session tracking
      if (m_session_tracking_enabled)
      {
        // Save off client port for the stream so we can match against it
        // later. SessionRequest should always be an outer protocol packet
        // so we can cast it to EQUDPIPPacketFormat to get the ip headers.
        m_sessionClientPort = ((EQUDPIPPacketFormat&) packet).getDestPort();

        // If this is the world server talking to us, reset session tracking if
        // it is on so we unlatch the client in case of getting kicked.
        if (m_streamid == world2client)
        {
          m_session_tracking_enabled = 1;
          emit sessionTrackingChanged(m_session_tracking_enabled);
        }
        // If this is the zone server talking to us, close the latch and lock
        else if (m_streamid == zone2client)
        {
          // SessionResponse should always be an outer protocol packet, so
          // the EQProtocolPacket passed in can be cast back to
          // EQUDPIPPacketFormat, which we need to go to get access to the IP
          // headers!
          m_session_tracking_enabled = 2;
  
          emit lockOnClient(((EQUDPIPPacketFormat&) packet).getSourcePort(), 
            ((EQUDPIPPacketFormat&) packet).getDestPort());
          emit sessionTrackingChanged(m_session_tracking_enabled);
        }
      }
    }
    break;
    case OP_SessionDisconnect:
    {
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionDisconnect found %s:%u->%s:%u, resetting expected seq, stream %s (%d) (session tracking %s)",
        ((EQUDPIPPacketFormat&) packet).getIPv4SourceA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getSourcePort(),
        ((EQUDPIPPacketFormat&) packet).getIPv4DestA().ascii(),
        ((EQUDPIPPacketFormat&) packet).getDestPort(),
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 2)
      seqDebug("EQPacket: Raw SessionDisconnect: %02x%02x %02x%02x %02x%02x %02x%02x",
        packet.payload()[0], packet.payload()[1], packet.payload()[2], 
        packet.payload()[3], packet.payload()[4], packet.payload()[5], 
        packet.payload()[6], packet.payload()[7]);
#endif

      m_arqSeqExp = 0;

      // Clear cache
      resetCache();

      // Signal closing. Unlatch session tracking if it is on.
      if (m_session_tracking_enabled)
      {
        m_session_tracking_enabled = 1;
        emit sessionTrackingChanged(m_session_tracking_enabled);

        m_sessionClientPort = 0;
      }

      emit closing(m_sessionId, m_streamid);
    }
    break;
    case OP_Ack:
    case OP_AckFuture:
    case OP_AckAfterDisconnect:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: no-op on ACK for net opcode %04x seq %04x, stream %s (%d)",
	    packet.getNetOpCode(), eqntohuint16(packet.payload()), 
        EQStreamStr[m_streamid], m_streamid);
#endif
    }
    break;
    case OP_KeepAlive:
    case OP_SessionStatRequest:
    case OP_SessionStatResponse:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: no-op on stats for net opcode %04x, stream %s (%d)",
	    packet.getNetOpCode(), EQStreamStr[m_streamid], m_streamid);
#endif
    }
    break;
    default :
    {
      seqWarn("EQPacket: Unhandled net opcode %04x, stream %s, size %d",
        packet.getNetOpCode(), EQStreamStr[m_streamid], packet.payloadLength());
    }
  }
}
示例#7
0
////////////////////////////////////////////////////
// handle a new packet on the stream
void EQPacketStream::handlePacket(EQUDPIPPacketFormat& packet)
{
  emit numPacket(++m_packetCount, (int)m_streamid);

  // Packet is ours now. Logging needs to know this later on.
  packet.setSessionKey(getSessionKey());

  // Only accept packets if we've been initialized unless they are
  // initialization packets!
  if (packet.getNetOpCode() != OP_SessionRequest &&
      packet.getNetOpCode() != OP_SessionResponse &&
      ! m_sessionKey)
  {
#if (defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)) || (defined(PACKET_SESSION_DIAG) && PACKET_SESSION_DIAG > 1)
    seqDebug("discarding packet %s:%d ==>%s:%d netopcode=%04x size=%d. Session not initialized. Need to zone to start picking up packets. Session tracking %s.",
      (const char*)packet.getIPv4SourceA(), packet.getSourcePort(),
      (const char*)packet.getIPv4DestA(), packet.getDestPort(),
      packet.getNetOpCode(), packet.payloadLength(),
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif
    return;
  }

  // Only accept packets that correspond to our latched client port, if
  // it is set. This helps filter out multiple sessions on the same physical
  // host when two eq clients zone at the same time. The first one will win.
  if (m_sessionClientPort != 0 &&
      ((dir() == DIR_Server && m_sessionClientPort != packet.getDestPort()) ||
       (dir() == DIR_Client && m_sessionClientPort != packet.getSourcePort())))
  {
#if (defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)) || (defined(PACKET_SESSION_DIAG) && PACKET_SESSION_DIAG > 1)
    seqDebug("discarding packet %s:%d ==>%s:%d netopcode=%04x size=%d. Multiple sessions on the same box? Ignoring all but one of them. Latched client port %d. Session tracking %s.",
      (const char*)packet.getIPv4SourceA(), packet.getSourcePort(),
      (const char*)packet.getIPv4DestA(), packet.getDestPort(),
      packet.getNetOpCode(), packet.payloadLength(),
      m_sessionClientPort,
        (m_session_tracking_enabled == 2 ? "locked on" :
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif
    return;
  }

  // Only accept packets that pass the EQ protocol-level CRC check. This helps
  // weed out non-EQ packets that we might see.
#ifdef APPLY_CRC_CHECK
  if (packet.hasCRC())
  {
    uint16_t calcedCRC = calculateCRC(packet);

    if (calcedCRC != packet.crc())
    {
      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;
    }
  }
#endif /* APPLY_CRC_CHECK */

  // Decode the packet first
  if (! packet.decode(m_maxLength))
  {
    seqWarn("Packet decode failed for stream %s (%d), op %04x, flags %02x packet dropped.",
      EQStreamStr[m_streamid], m_streamid, packet.getNetOpCode(),
      packet.getFlags());
    return;
  }
#ifdef PACKET_DECODE_DIAG
  else if (packet.hasFlags())
  {
    seqDebug("Successful decode for stream %s (%d), op %04x, flags %02x.",
        EQStreamStr[m_streamid], m_streamid, packet.getNetOpCode(),
        packet.getFlags());
  }
#endif

  // Raw packet
  emit rawPacket(packet.rawPayload(), packet.rawPayloadLength(), m_dir, 
    packet.getNetOpCode());

  processPacket(packet, false); // false = isn't subpacket

  // if the cache isn't empty, then process it.
  if (!m_cache.empty()) 
    processCache();
}
示例#8
0
void EQPacketStream::dispatchPacket(const uint8_t* data, size_t len, 
				    uint16_t opCode, 
				    const EQPacketOPCode* opcodeEntry)
{
  emit decodedPacket(data, len, m_dir, opCode, opcodeEntry);

  bool unknown = true;

  // unless there is an opcode entry, there is nothing to dispatch...
  if (opcodeEntry)
  {
    EQPacketPayload* payload;
    EQPacketDispatch* dispatch;

#ifdef PACKET_INFO_DIAG
    seqDebug(
	    "dispatchPacket: attempting to dispatch opcode %#04x '%s'",
	    opcodeEntry->opcode(), (const char*)opcodeEntry->name());
#endif

    // iterate over the payloads in the opcode entry, and dispatch matches
    EQPayloadListIterator pit(*opcodeEntry);
    bool found = false;
    while ((payload = pit.current()) != 0)
    {
      // see if this packet matches
      if (payload->match(data, len, m_dir))
      {
	found = true;
	unknown = false; // 

#ifdef PACKET_INFO_DIAG
	seqDebug(
		"\tmatched payload, find dispatcher in dict (%d/%d)",
		m_dispatchers.count(), m_dispatchers.size());
#endif

	// find the dispather for the payload
	dispatch = m_dispatchers.find((void*)payload);
	
	// if found, dispatch
	if (dispatch)
	{
#ifdef PACKET_INFO_DIAG
	  seqDebug("\tactivating signal...");
#endif
	  dispatch->activate(data, len, m_dir);
	}
      }

      // go to next possible payload
      ++pit;
    }

 #ifdef PACKET_PAYLOAD_SIZE_DIAG
    if (!found && !opcodeEntry->isEmpty())
    {
      QString tempStr;
      tempStr.sprintf("%s  (%#04x) (dataLen: %u) doesn't match:",
		      (const char*)opcodeEntry->name(), opcodeEntry->opcode(), 
		      len);
      
      for (payload = pit.toFirst(); 
	   payload != 0; 
	   payload = ++pit)
      {
	if (payload->dir() & m_dir)
        {
	  if (payload->sizeCheckType() == SZC_Match)
	    tempStr += QString(" sizeof(%1):%2")
	      .arg(payload->typeName()).arg(payload->typeSize());
	  else if (payload->sizeCheckType() == SZC_Modulus)
	    tempStr += QString(" modulus of sizeof(%1):%2")
	      .arg(payload->typeName()).arg(payload->typeSize());
	}
      }      

      seqWarn(tempStr);
    }
#endif // PACKET_PAYLOAD_SIZE_DIAG
  }
#ifdef PACKET_INFO_DIAG
  else
  {
    seqWarn("dispatchPacket(): buffer size %d opcode %04x stream %s (%d) not in opcodeDB",
       len, opCode, EQStreamStr[m_streamid], m_streamid);
  }
#endif

  emit decodedPacket(data, len, m_dir, opCode, opcodeEntry, unknown);
}
示例#9
0
////////////////////////////////////////////////////
// Cache processing
void EQPacketStream::processCache()
{
#if defined(PACKET_CACHE_DIAG)
  seqDebug("SEQ: START checking stream %s cache, arq %04x, cache count %04d",
         EQStreamStr[m_streamid], m_arqSeqExp, m_cache.size());
#endif
  EQPacketMap::iterator it;
  EQPacketMap::iterator eraseIt;
  EQProtocolPacket* packet;

  // check if the cache has grown large enough that we should give up
  // on seeing the current serverArqSeqExp
  // 
  // If people see this a lot, they either have pathetic network cards, or
  // are having problems keeping up with packets (slow computer? Too much
  // net traffic?). Some possible solutions to this are to turn on session
  // tracking to filter out more PF_PACKET packets from getting passed out of
  // the kernel and to up the socket receive buffer sizes. See FAQ for
  // more information.
  if (m_cache.size() >= m_arqSeqGiveUp)
  {
    // ok, if the expected server arq sequence isn't here yet, give up
    
    // attempt to find the current expencted arq seq
    it = m_cache.find(m_arqSeqExp);
    
    // keep trying to find a new serverArqSeqExp if we haven't found a good
    // one yet...
    while(it == m_cache.end())
    {
      seqWarn("SEQ: Giving up on finding arq %04x in stream %s cache, skipping!",
	     m_arqSeqExp, EQStreamStr[m_streamid]);
      
      // incremente the expected arq sequence number
      m_arqSeqExp++;
      emit seqExpect(m_arqSeqExp, (int)m_streamid);
      
      // attempt to find the new current expencted arq seq
      it = m_cache.find(m_arqSeqExp);
    }
  }
  else
  {
    // haven't given up yet, just try to find the current serverArqSeqExp
    // attempt to find the current expected ARQ seq
    it = m_cache.find(m_arqSeqExp);
  }


  // iterate over cache until we reach the end or run out of
  // immediate followers
  while (it != m_cache.end())
  {
    // get the PacketFormat for the iterator
    packet = it->second;
    
    // make sure this is the expected packet
    // (we might have incremented to the one after the one returned
    // by find above).
    if (packet->arqSeq() != m_arqSeqExp)
      break;
    
#ifdef PACKET_CACHE_DIAG
    seqDebug("SEQ: found next arq %04x in stream %s cache, cache count %04d",
	   m_arqSeqExp, EQStreamStr[m_streamid], m_cache.size());
#endif
    
    // validate the packet with a crc check. If the packet is for an old
    // session, we probably shouldn't be using it!
#ifdef APPLY_CRC_CHECK
    if (packet->hasCRC() && packet->crc() != calculateCRC(*packet))
    {
#if defined (PACKET_CACHE_DIAG)
      // Something's screwed up
      seqDebug("SEQ: INVALID PACKET: Bad CRC in packet in stream %s cache with arq %04x! Droping it, but leaving expected seq as %04x",
	    EQStreamStr[m_streamid], packet->arqSeq(), m_arqSeqExp);
#endif

      // Need to drop from the cache
      eraseIt = it;
        
      // increment the current position iterator
      it++;
        
      // erase the packet from the cache
      m_cache.erase(eraseIt);
      emit cacheSize(m_cache.size(), (int)m_streamid);
        
    #ifdef PACKET_CACHE_DIAG
      seqDebug("SEQ: REMOVING arq %04x from stream %s cache, cache count %04d",
         packet->arqSeq(), EQStreamStr[m_streamid], m_cache.size());
    #endif
      // delete the packet
      delete packet;

      // No sense looping some more.
      break;
    }
    else
#endif /* APPLY_CRC_CHECK */
    {
#if defined (PACKET_CACHE_DIAG) && (PACKET_CACHE_DIAG > 2)
      seqDebug("SEQ: Found next arq in stream %s cache, incrementing arq seq, %04x", 
	     EQStreamStr[m_streamid], packet->arqSeq());
#endif
    
      // Process the packet since it's next in the sequence and was just
      // received out of order
      processPacket(*packet, packet->isSubpacket());
      
      // Need to drop from the cache
      eraseIt = it;
      
      // increment the current position iterator
      it++;
      
      // erase the packet from the cache
      m_cache.erase(eraseIt);
      emit cacheSize(m_cache.size(), (int)m_streamid);
    
#ifdef PACKET_CACHE_DIAG
      seqDebug("SEQ: REMOVING arq %04x from stream %s cache, cache count %04d",
	     packet->arqSeq(), EQStreamStr[m_streamid], m_cache.size());
#endif
      // delete the packet
      delete packet;
  
      if (m_arqSeqExp == 0)
        it = m_cache.begin();
    }
  }
  
#ifdef PACKET_CACHE_DIAG
  seqDebug("SEQ: FINISHED checking stream %s cache, arq %04x, cache count %04d",
         EQStreamStr[m_streamid], m_arqSeqExp, m_cache.size());
#endif
}
示例#10
0
////////////////////////////////////////////////////
// Reads packets and processes waiting packets from playback file
void EQPacket::processPlaybackPackets (void)
{
#ifdef DEBUG_PACKET
//   debug ("processPackets()");
#endif /* DEBUG_PACKET */
  /* Make sure we are not called while already busy */
  if (m_busy_decoding)
    return;

  /* Set flag that we are busy decoding */
  m_busy_decoding = true;

  unsigned char  buffer[8192];
  int            size;

  /* in packet playback mode fetch packets from VPacket class */
  time_t now;
  int timein = mTime();
  int i = 0;
    
  long version = PACKETVERSION;
  
  // decode packets from the playback buffer
  do
  {
    size = m_vPacket->Playback((char *) buffer, sizeof(buffer), &now, &version);
    
    if (size)
    {
      i++;
	
      if (PACKETVERSION == version)
      {
	dispatchPacket ( size - sizeof (struct ether_header),
		       (unsigned char *) buffer + sizeof (struct ether_header)
		       );
      }
      else
      {
	seqWarn("Error:  The version of the packet stream has " \
		 "changed since '%s' was recorded - disabling playback",
		 m_vPacket->getFileName());

	// stop the timer, nothing more can be done...
	stop();

	break;
      }
    }
    else
      break;
  } while ( (mTime() - timein) < 100);

  // check if we've reached the end of the recording
  if (m_vPacket->endOfData())
  {
    seqInfo("End of playback file '%s' reached."
	    "Playback Finished!",
	    m_vPacket->getFileName());

    // stop the timer, nothing more can be done...
    stop();
  }

  /* Clear decoding flag */
  m_busy_decoding = false;
}
示例#11
0
////////////////////////////////////////////////////
// decode, decrypt, and unroll packet
void EQPacketStream::decodePacket(uint8_t *data, size_t len, uint16_t opCode)
{
  emit rawPacket(data, len, m_dir, opCode);

  if (opCode & FLAG_CRYPTO || opCode & FLAG_COMP) 
  {
    data = decodeOpCode (data, &len, opCode);
    if (data == NULL)
      return;

    emit rawPacket(data, len, m_dir, opCode);
  }
  
  const EQPacketOPCode* opcodeEntry = 0;

  // this works, but could really use a cleanup - mvern
  while (len > 2) 
  {
    if (opCode & FLAG_COMBINED) 
    {
      bool repeatop = false;
      uint8_t *dptr = data;
      size_t left = len;
      int32_t count = 1;
      
      if (opCode & FLAG_IMPLICIT) 
      {
	opCode = opCode & ~FLAG_IMPLICIT;
	repeatop = true;
      }

#ifdef PACKET_DECODE_DIAG
      seqDebug("unrolling on %s: 0x%04x", EQStreamStr[m_streamid], opCode);
#endif
      opCode = opCode & ~FLAG_COMBINED;
      
      while (count > 0) 
      {
	uint16_t size = 0;

	opcodeEntry = m_opcodeDB.find(opCode);

	if (opcodeEntry)
	{
	  size = opcodeEntry->implicitLen();
#ifdef PACKET_DECODE_DIAG // ZBTEMP
	  seqDebug("opcode %04x implicitlen %d",
		  opCode, size);
#endif
	}
#ifdef PACKET_DECODE_DIAG
	else 
	  seqDebug("No opcodeEntry for %04x", opCode);
#endif 
	
	if (size == 0) 
	{ // Not an implicit length opcode
	  if (dptr[0] == 0xff) 
	  { // > 255 length
	    left--;
	    dptr++;
	    size = ntohs(*((uint16_t *)dptr));
	    left -= 2;
	    dptr += 2;
	  } 
	  else 
	  { // single octet length
	    size = dptr[0];
	    left--;
	    dptr++;
	  }
	}
#ifdef PACKET_DECODE_DIAG
	seqDebug ("size on %s: %d", EQStreamStr[m_streamid], size);
#endif
		
	if (size > left) 
	{
	  seqWarn("error on %s: size > left (size=%d, left=%d, opcode=0x%04x)", 
		     EQStreamStr[m_streamid], size, left, opCode);
	  return;
	}
	
#ifdef PACKET_DECODE_DIAG
	seqDebug("sending from %s: 0x%04x, %d", 
	       EQStreamStr[m_streamid], opCode, size);
#endif
	dispatchPacket(dptr, size, opCode, opcodeEntry);
	
	// next
	dptr += size;
	left -= size;
	
	count--;
	if (repeatop) 
	{
	  count = dptr[0];
	  dptr++;
	  left--;
	  repeatop = false;
#ifdef PACKET_DECODE_DIAG
	  seqDebug ("repeating %d times on %s",
		  count, EQStreamStr[m_streamid]);
#endif
	}
      }
	    
      if (left > 2) 
      {
	opCode = *((unsigned short *)dptr);
	dptr += 2;
	left -= 2;

#ifdef PACKET_DECODE_DIAG
	seqDebug("doing leftover from %s: 0x%04x, %d", 
	       EQStreamStr[m_streamid], opCode, left);
#endif
	if (opCode & FLAG_COMBINED)
	{
	  data = dptr;
	  len = left;
	  continue;
	} 
	else 
	{
#ifdef PACKET_DECODE_DIAG
	  seqDebug("sending from %s: 0x%04x, %d", 
		 EQStreamStr[m_streamid], opCode, size);
#endif
	  dispatchPacket(dptr, left, opCode, m_opcodeDB.find(opCode));
	}
      }

      return;
    }
    else
      break;
  }
  
#ifdef PACKET_DECODE_DIAG
  seqDebug ("sending from %s: 0x%04x, %d",
	  EQStreamStr[m_streamid], opCode, size);
#endif
  dispatchPacket(data, len, opCode, m_opcodeDB.find(opCode));
}
示例#12
0
ExperienceWindow::ExperienceWindow(const DataLocationMgr* dataLocMgr, 
				   Player* player, GroupMgr* groupMgr,
				   ZoneMgr* zoneMgr,
				   QWidget* parent, const char* name) 
  : SEQWindow("Experience", "ShowEQ - Experience", parent, name),
    m_dataLocMgr(dataLocMgr),
    m_player(player),
    m_group(groupMgr),
    m_zoneMgr(zoneMgr)
{
  /* Hopefully this is only called once to set up the window,
     so this is a good place to initialize some things which
     otherwise won't be. */

   m_ratio = 1;
   m_timeframe = 0;
   m_calcZEM=0;
   m_ZEMviewtype = 0;

   m_view_menu = new QPopupMenu( this );
   m_view_menu->insertItem( "&All Mobs", this, SLOT(viewAll()) );
   m_view_menu->insertItem( "Previous &15 Minutes", this, SLOT(view15Minutes()) );
   m_view_menu->insertItem( "Previous &30 Minutes", this, SLOT(view30Minutes()) );
   m_view_menu->insertItem( "Previous &60 Minutes", this, SLOT(view60Minutes()) );
   m_view_menu->setItemChecked( m_view_menu->idAt(0), true );

   m_view_menu->insertSeparator();
   m_exp_rate_menu = new QPopupMenu( this );
   m_exp_rate_menu->insertItem( "per &minute", this, SLOT(viewRatePerMinute()) );
   m_exp_rate_menu->insertItem( "per &hour", this, SLOT(viewRatePerHour()) );
   m_exp_rate_menu->setItemChecked( m_exp_rate_menu->idAt(0), true );
   m_view_menu->insertItem( "Experience &Rate", m_exp_rate_menu );

   m_view_menu->insertSeparator();
   m_view_menu->insertItem( "Clear Kills", this, SLOT(viewClear()) );

   m_view_menu->insertSeparator();
   m_ZEM_menu = new QPopupMenu( this );
   m_ZEM_menu->insertItem( "Calculated Value", this, SLOT(viewZEMcalculated()) );
   m_ZEM_menu->insertItem( "Raw Value", this, SLOT(viewZEMraw()) );
   m_ZEM_menu->insertItem( "Percent Bonus", this, SLOT(viewZEMpercent()) );
   m_ZEM_menu->setItemChecked( m_ZEM_menu->idAt(0), true );
   m_view_menu->insertItem( "ZEM View Options", m_ZEM_menu );
   m_view_menu->insertItem( "Calculate ZEM on next kill", this, SLOT(calcZEMNextKill()) );

   m_layout = new QVBoxLayout(boxLayout());

   m_menu_bar = new QMenuBar( this );
   m_menu_bar->insertItem( "&View", m_view_menu );
   //m_layout->addSpacing( m_menu_bar->height() + 5 );
   m_layout->addWidget(m_menu_bar);

   QGroupBox *listGBox = new QVGroupBox( "Experience Log", this );
   m_layout->addWidget( listGBox );

   m_exp_listview = new SEQListView(preferenceName(), listGBox);
   m_exp_listview->addColumn("Time");
   m_exp_listview->addColumn("Mob");
   m_exp_listview->addColumn("Level");
   m_exp_listview->addColumn("Base Exp");
   m_exp_listview->addColumn("ZEM total");
   m_exp_listview->addColumn("Class total");
   m_exp_listview->addColumn("Group total");
   m_exp_listview->addColumn("Experience Gained");
   
   m_exp_listview->restoreColumns();

   m_exp_listview->setMinimumSize( m_exp_listview->sizeHint().width(),
      200 );

   QGroupBox *statsGBox = new QVGroupBox( "Statistics", this );
   m_layout->addWidget( statsGBox );
   
   QGrid *statsGrid = new QGrid( 4, statsGBox );

   new QLabel( "Total Experience Received:",
      statsGrid );
   m_total_received = new QLabel( statsGrid );

   new QLabel( "Play Time:", statsGrid );
   m_play_time = new QLabel( statsGrid );

   new QLabel( "Total Mobs Killed:", statsGrid );
   m_mob_count = new QLabel( statsGrid );

   m_experience_rate_label = new QLabel( "Experience Rate (per minute):", statsGrid );
   m_experience_rate = new QLabel( statsGrid );

   new QLabel( "Average Experience per Mob:",
      statsGrid );
   m_average_per_mob = new QLabel( statsGrid );

   new QLabel( "Estimated Kills To Level:",
      statsGrid );
   m_kills_to_level = new QLabel( statsGrid );

   new QLabel( "Experience Remaining:",
      statsGrid );
   m_experience_remaining = new QLabel( statsGrid );

   new QLabel( "Estimated Time To Level:",
      statsGrid );
   m_time_to_level = new QLabel( statsGrid );

   // ewww, why can't we just get it from QGrid? :(
   ((QGridLayout *)statsGrid->layout())->setColStretch( 1, 1 );
   ((QGridLayout *)statsGrid->layout())->setColStretch( 3, 1 );
   statsGrid->layout()->setSpacing( 5 );

   updateAverage( );

   // timer to update the average xp
   QTimer *timer = new QTimer( this );
   connect( timer, SIGNAL(timeout()), SLOT(updateAverage()));
   timer->start(15*1000); // calculate every 15 seconds

   QFileInfo fileInfo = m_dataLocMgr->findWriteFile("logs", "exp.log");

   m_log = fopen(fileInfo.absFilePath(), "a");
   if (m_log == 0)
   {
      m_log_exp = 0;
      seqWarn("Error opening exp.log, no exp will be logged this session");
   }

   fileInfo = m_dataLocMgr->findWriteFile("logs", "newexp.log");

   m_newExpLogFile = fileInfo.absFilePath();
}
示例#13
0
////////////////////////////////////////////////////
// This function decides the fate of the Everquest packet 
// and dispatches it to the correct packet stream for handling function
void EQPacket::dispatchPacket(int size, unsigned char *buffer)
{
#ifdef DEBUG_PACKET
  debug ("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())
  {
    if (m_crcWarnings)
      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;
  }

  /* 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;    
  }

  /* Client Detection */
  if (m_detectingClient && packet.getSourcePort() == WorldServerGeneralPort)
  {
    m_ip = packet.getIPv4DestA();
    m_client_addr = packet.getIPv4DestN();
    m_detectingClient = false;
    emit clientChanged(m_client_addr);
    seqInfo("Client Detected: %s", (const char*)m_ip);
  }
  else if (m_detectingClient && packet.getDestPort() == WorldServerGeneralPort)
  {
    m_ip = packet.getIPv4SourceA();
    m_client_addr = packet.getIPv4SourceN();
    m_detectingClient = false;
    emit clientChanged(m_client_addr);
    seqInfo("Client Detected: %s", (const char*)m_ip);
  }
  /* end client detection */



  if (packet.getSourcePort() == WorldServerChatPort)
  {
    dispatchWorldChatData(packet.payloadLength(), packet.payload(), DIR_Server);
    
    return;
  }
  else if (packet.getDestPort() == WorldServerChatPort)
  {
    dispatchWorldChatData(packet.payloadLength(), packet.payload(), DIR_Client);
    
    return;
  }

  /* stream identification */
  if (packet.getIPv4SourceN() == m_client_addr)
  {
    if (packet.getDestPort() == WorldServerGeneralPort)
      m_client2WorldStream->handlePacket(packet);
    else 
      m_client2ZoneStream->handlePacket(packet);
  }
  else if (packet.getIPv4DestN() == m_client_addr)
  {
    if (packet.getSourcePort() == WorldServerGeneralPort)
      m_world2ClientStream->handlePacket(packet);
    else 
      m_zone2ClientStream->handlePacket(packet);
  }

  return;
} /* end dispatchPacket() */
示例#14
0
/////////////////////////////////////////////////////
// Handle a protocol level packet. This could be either a top-level
// EQUDPIPPacket or a subpacket that is just an EQProtocolPacket. Either way
// we use net opcodes here.
void EQPacketStream::processPacket(EQProtocolPacket& packet, bool isSubpacket)
{
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
  seqDebug("-->EQPacketStream::processPacket, subpacket=%s on stream %s (%d)",
    (isSubpacket ? "true" : "false"), EQStreamStr[m_streamid], m_streamid);
#endif

  if (IS_APP_OPCODE(packet.getNetOpCode()))
  {
    // This is an app-opcode directly on the wire with no wrapping protocol
    // information. Weird, but whatever gets the stream read, right?
	dispatchPacket(packet.payload(), packet.payloadLength(), 
        packet.getNetOpCode(), m_opcodeDB.find(packet.getNetOpCode()));
    return;
  }

  // Process the net opcode
  switch (packet.getNetOpCode())
  {
    case OP_Combined:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: found combined packet (net op: %04x, size %d) on stream %s (%d). Unrolling.", 
        packet.getNetOpCode(), packet.payloadLength(),
        EQStreamStr[m_streamid], m_streamid);
#endif

      // Rolled up multiple packets inside this packet. Need to unroll them
      // and process them individually. subpacket starts after the net opcode.
      uint8_t* subpacket = packet.payload();

      while (subpacket < packet.payload() + packet.payloadLength())
      {
        // Length specified first on the wire.
        uint8_t subpacketLength = subpacket[0];

        // Move past the length
        subpacket++;

        // OpCode (in net order)
        uint16_t subOpCode = *(uint16_t*)subpacket;
        
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif
        
        // Opcode is next. Net opcode or app opcode?
        if (IS_NET_OPCODE(subOpCode))
        {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
          seqDebug("EQPacket: processing unrolled net opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
            subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Net opcode. false = copy. true = subpacket
          EQProtocolPacket spacket(subpacket, subpacketLength, false, true);

          processPacket(spacket, true);
        }
        else
        {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // App opcode. Dispatch it, skipping opcode.
          dispatchPacket(&subpacket[2], subpacketLength-2, 
            subOpCode, m_opcodeDB.find(subOpCode));
        }
        subpacket += subpacketLength;
      }
    }
    break;
    case OP_AppCombined:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: found appcombined packet (net op: %04x, size %d) on stream %s (%d). Unrolling.", 
        packet.getNetOpCode(), packet.payloadLength(),
        EQStreamStr[m_streamid], m_streamid);
#endif

      // Multiple app op codes in the same packet. Need to unroll and dispatch
      // them.
      uint8_t* subpacket = packet.payload();

      while (subpacket < packet.payload() + packet.payloadLength())
      {
        // Length specified first on the wire.
        uint8_t subpacketLength = subpacket[0];

        // Move past the length
        subpacket++;

        if (subpacketLength != 0xff)
        {
          // Dispatch app op code using given packet length. Net order!
          uint16_t subOpCode = *(uint16_t*)(subpacket);

#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength, EQStreamStr[m_streamid], m_streamid, subOpCode);
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          subpacketLength-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Dispatch, skipping op code.
          dispatchPacket(&subpacket[2], subpacketLength-2, 
            subOpCode, m_opcodeDB.find(subOpCode));

          // Move ahead
          subpacket += subpacketLength;
        }
        else
        {
          // If original length is 0xff, it means it is a long one. The length
          // is 2 bytes and next.
          uint16_t longOne = eqntohuint16(subpacket);
 
          // Move past the 2 byte length
          subpacket += 2;

          // OpCode next. Net order for op codes.
          uint16_t subOpCode = *(uint16_t*)subpacket;
          
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
        seqDebug("EQPacket: unrolling length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          longOne, EQStreamStr[m_streamid], m_streamid, subOpCode);
        seqDebug("EQPacket: processing unrolled app opcode, length %d bytes from combined packet on stream %s (%d). Opcode %04x", 
          longOne-2, EQStreamStr[m_streamid], m_streamid, subOpCode);
#endif

          // Dispatch, skipping op code.
          dispatchPacket(&subpacket[2], longOne-2, 
            subOpCode, m_opcodeDB.find(subOpCode));

          // Move ahead
          subpacket += longOne;
        }
      }
    }
    break;
    case OP_Packet:
    {
      // Normal unfragmented sequenced packet.
      uint16_t seq = eqntohuint16(packet.payload());
      emit seqReceive(seq, (int)m_streamid);

      if (seq >= m_arqSeqExp)
      {
        // Future packet?
        if (seq == m_arqSeqExp)
        {
          // Expected packet.
          m_arqSeqExp++;
          emit seqExpect(m_arqSeqExp, (int)m_streamid);

          // OpCode next. Net order for op codes.
          uint16_t subOpCode = *(uint16_t*)(&packet.payload()[2]);
       
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
          seqDebug("SEQ: Found next sequence number in data stream %s (%d), incrementing expected seq, %04x (op code %04x, sub opcode %04x)", 
	        EQStreamStr[m_streamid], m_streamid, seq, packet.getNetOpCode(),
            subOpCode);
#endif

          // App opcode or net opcode?
          if (IS_NET_OPCODE(subOpCode))
          {
            // Net opcode. false = no copy. true = subpacket.
            EQProtocolPacket spacket(&packet.payload()[2],
              packet.payloadLength()-2, false, true);

            processPacket(spacket, true);
          }
          else
          {
            // App opcode. Dispatch, skipping seq and opcode.
            dispatchPacket(&packet.payload()[4], packet.payloadLength()-4,
              subOpCode, m_opcodeDB.find(subOpCode));
          }
        }
        else if (seq < (uint32_t(m_arqSeqExp + arqSeqWrapCutoff)) ||
                 seq < (int32_t(m_arqSeqExp - arqSeqWrapCutoff)))
        {
          // Yeah, future packet. Push it on the packet cache.
#ifdef PACKET_PROCESS_DIAG
          seqDebug("SEQ: out of order sequence %04x stream %s (%d) expecting %04x, sending to cache, %04d",
	        seq, EQStreamStr[m_streamid], m_streamid, 
            m_arqSeqExp, m_cache.size());
#endif
          setCache(seq, packet);
        }
        else
        {
          // Past packet outside the cut off
          seqWarn("SEQ: received sequenced %spacket outside the bounds of reasonableness. Expecting seq=%04x got seq=%04x, reasonableness being %d in the future.", 
            (isSubpacket ? "sub" : ""), m_arqSeqExp, seq, arqSeqWrapCutoff);
        }
      }
      else
      {
        // Spooky packet from the past. Boo!
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
        seqDebug("discarding %spacket netopcode=%04x seq=%d size=%d on stream %s (%d). Packet is in the past. We've moved on.",
          (isSubpacket ? "sub" : ""),
          packet.getNetOpCode(), seq, packet.payloadLength(),
          EQStreamStr[m_streamid], m_streamid);
#endif
      }
    }
    break;
    case OP_Oversized:
    {
      // Fragmented sequenced data packet.
      uint16_t seq = eqntohuint16(packet.payload());
      emit seqReceive(seq, (int)m_streamid);

      if (seq >= m_arqSeqExp)
      {
        // Future packet?
        if (seq > m_arqSeqExp)
        {
          // Yeah, future packet. Push it on the packet cache.
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
          seqDebug("SEQ: out of order sequence %04x stream %s (%d) expecting %04x, sending to cache, %04d",
	        seq, EQStreamStr[m_streamid], m_streamid, 
            m_arqSeqExp, m_cache.size());
#endif
          setCache(seq, packet);
        }
        else
        {
          // Expected packet.
          m_arqSeqExp++;
          emit seqExpect(m_arqSeqExp, (int)m_streamid);
       
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
          seqDebug("SEQ: Found next sequence number in data stream %s (%d), incrementing expected seq, %04x (op code %04x)", 
	        EQStreamStr[m_streamid], m_streamid, seq, packet.getNetOpCode());
#endif

          // Push the fragment on.
          m_fragment.addFragment(packet);

          if (m_fragment.isComplete())
          {
            // OpCode from fragment. In network order.
            uint16_t fragOpCode = *(uint16_t*)(m_fragment.data());

#ifdef PACKET_PROCESS_DIAG
          seqDebug("SEQ: Completed oversized app packet on stream %s with seq %04x, total size %d opcode %04x", 
	        EQStreamStr[m_streamid], seq, m_fragment.size()-2, fragOpCode);
#endif

            // dispatch fragment. Skip opcode.
            dispatchPacket(&m_fragment.data()[2], m_fragment.size()-2,
              fragOpCode, m_opcodeDB.find(fragOpCode)); 

            m_fragment.reset();
          }
        }
      }
      else
      {
        // Spooky packet from the past. Boo!
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)
        seqDebug("discarding packet netopcode=%04x seq=%d size=%d on stream %s (%d). Packet is in the past. We've moved on.",
          packet.getNetOpCode(), seq, packet.payloadLength(),
          EQStreamStr[m_streamid], m_streamid);
#endif
      }
    }
    break;
    case OP_SessionRequest:
    {
      // Session request from client to server.
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionRequest found, resetting expected seq, stream %s (%d) (session tracking %s)",
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif
      
      // Pull off session request information
      SessionRequestStruct* request = 
        (SessionRequestStruct*) packet.payload();

      m_sessionId = eqntohuint32((uint8_t*)&(request->sessionId));
      m_maxLength = eqntohuint32((uint8_t*)&(request->maxLength));

#if defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionRequest sessionId %u maxLength %u, awaiting key for stream %s (%d)",
        m_sessionId,
        m_maxLength,
        EQStreamStr[m_streamid],
        m_streamid);
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 1)
      seqDebug("EQPacket: SessionRequest contents: unknown %u, sessionId %u, maxLength %u",
        eqntohuint32((uint8_t*)&(request->unknown0000)),
        m_sessionId,
        m_maxLength);
#endif

      m_arqSeqExp = 0;
      m_arqSeqFound = true;
    }
    break;
    case OP_SessionResponse:
    {
      // Session response from server
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionResponse found, resetting expected seq, stream %s (%d) (session tracking %s)",
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif
      
      // Pull off session response information
      SessionResponseStruct* response = 
        (SessionResponseStruct*) packet.payload();

      m_maxLength = eqntohuint32((uint8_t*)&(response->maxLength));
      m_sessionKey = eqntohuint32((uint8_t*)&(response->key));
      m_sessionId = eqntohuint32((uint8_t*)&(response->sessionId));

#if defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionResponse sessionId %u maxLength %u, key is %u for stream %s (%d)",
        m_sessionId,
        m_maxLength,
        m_sessionKey,
        EQStreamStr[m_streamid],
        m_streamid);
#endif

#if defined(PACKET_SESSION_DIAG) && (PACKET_SESSION_DIAG > 1)
      seqDebug("EQPacket: SessionResponse contents: sessionId %u, key %u, unknown %u, unknown %u, maxLength %u, unknown %u",
        m_sessionId,
        m_sessionKey,
        eqntohuint16((uint8_t*)&(response->unknown0008)),
        response->unknown0010,
        m_maxLength,
        eqntohuint32((uint8_t*) &(response->unknown0015)));
#endif

      // Provide key to corresponding stream from this session/stream
      emit sessionKey(m_sessionId, m_streamid, m_sessionKey);

      m_arqSeqExp = 0;
      m_arqSeqFound = true;

      // Session tracking
      if (m_session_tracking_enabled)
      {
        // If this is the world server talking to us, reset session tracking if
        // it is on so we unlatch the client in case of getting kicked.
        if (m_streamid == world2client)
        {
          m_session_tracking_enabled = 1;
          emit sessionTrackingChanged(m_session_tracking_enabled);
        }
        // If this is the zone server talking to us, close the latch and lock
        else if (m_streamid == zone2client)
        {
          // SessionResponse should always be an outer protocol packet, so
          // the EQProtocolPacket passed in can be cast back to
          // EQUDPIPPacketFormat, which we need to go to get access to the IP
          // headers!
          m_session_tracking_enabled = 2;
  
          emit lockOnClient(((EQUDPIPPacketFormat&) packet).getSourcePort(), 
            ((EQUDPIPPacketFormat&) packet).getDestPort());
          emit sessionTrackingChanged(m_session_tracking_enabled);
        }
      }
    }
    break;
    case OP_SessionDisconnect:
    {
#if defined(PACKET_PROCESS_DIAG) || defined(PACKET_SESSION_DIAG)
      seqDebug("EQPacket: SessionDisconnect found, resetting expected seq, stream %s (%d) (session tracking %s)",
	    EQStreamStr[m_streamid], m_streamid,
        (m_session_tracking_enabled == 2 ? "locked on" : 
          (m_session_tracking_enabled == 1 ? "enabled" : "disabled")));
#endif

      m_arqSeqExp = 0;

      // Clear cache
      resetCache();

      // Signal closing. Unlatch session tracking if it is on.
      if (m_session_tracking_enabled)
      {
        m_session_tracking_enabled = 1;
        emit sessionTrackingChanged(m_session_tracking_enabled);
      }

      emit closing();
    }
    break;
    case OP_Ack:
    case OP_Resend:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: no-op on for net opcode %04x seq %04x, stream %s (%d)",
	    packet.getNetOpCode(), eqntohuint16(packet.payload()),
        EQStreamStr[m_streamid], m_streamid);
#endif
    }
    break;
    case OP_KeepAlive:
    case OP_SessionStatRequest:
    case OP_SessionStatResponse:
    {
#if defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 2)
      seqDebug("EQPacket: no-op on for net opcode %04x, stream %s (%d)",
	    packet.getNetOpCode(), EQStreamStr[m_streamid], m_streamid);
#endif
    }
    break;
    default :
    {
      seqWarn("EQPacket: Unhandled net opcode %04x, stream %s, size %d",
        packet.getNetOpCode(), EQStreamStr[m_streamid], packet.payloadLength());
    }
  }
}
示例#15
0
文件: guild.cpp 项目: brainiac/showeq
void GuildMgr::writeGuildList(const uint8_t* data, size_t len)
{
	QFile guildsfile(guildsFileName);

	if (guildsfile.exists()) {
		if (!guildsfile.remove()) {
			seqWarn("GuildMgr: Could not remove old %s, unable to replace with server data!", guildsFileName.latin1());
			return;
		}
	}

	if (!guildsfile.open(QIODevice::WriteOnly))
		seqWarn("GuildMgr: Could not open %s for writing, unable to replace with server data!", guildsFileName.latin1());

	QDataStream guildDataStream(&guildsfile);
	
	NetStream netStream(data, len);
	QString guildName;
	uint32_t size = 0; // to keep track of how much we're reading from the packet
	uint32_t guildId = 0;
	
	/* 0x48 in the packet starts the serialized list. See guildListStruct
	 * and worldGuildListStruct in everquest.h */
	
	// Skip the first guild in the list
	netStream.skipBytes(0x44);
	size += 0x44;
	
	while (!netStream.end())
	{
		guildId = netStream.readUInt32NC();
		guildName = netStream.readText();
		size += 4;
		
		if (guildName.length())
		{
			m_guildList[guildId] = guildName;
			
			// add guild name length, plus one for the null character
			size += guildName.length() + 1;
		}
		
		// theres an extra zero at the end of the packet
		if (size + 1 == len)
			break;
	}
	
	std::map<uint32_t, QString>::const_iterator it;
	
	for (it = m_guildList.begin(); it != m_guildList.end(); it++)
	{
		char szGuildName[64] = {0};
		
		strcpy(szGuildName, it->second.latin1());
		
		// seqDebug("GuildMgr::writeGuildList - add guild '%s' (%d)", szGuildName, it->first);
		guildDataStream.writeRawBytes(szGuildName, sizeof(szGuildName));
	}
	
	guildsfile.close();
	seqInfo("GuildMgr: New guildsfile written");
}