public bool combine(EQProtocolPacket rhs) { bool result = false; if (opcode == (ushort)OpCodes.OP_Combined && size + rhs.size + 5 < 256) { // This packet was previously combined. Add another packet into it. byte[] tmpbuffer = new byte[size + rhs.size + 3]; // Copy the current packet (left-hand side) into the new buffer. Buffer.BlockCopy(pBuffer, 0, tmpbuffer, 0, (int)size); // set the offset for the second packet to the end of the first. var offset = size; // add the size of the second packet. Buffer.BlockCopy(BitConverter.GetBytes(rhs.Size()), 0, tmpbuffer, (int)offset++, sizeof(ushort)); // Copy in the second packet. offset += rhs.serialize(tmpbuffer, offset); // update the total size. size = offset; // Copy the combined packet into this one. pBuffer = tmpbuffer; result = true; } else if (size + rhs.size + 7 < 256) { // This packet hasn't been combined before, so once we're done mark it as a combined packet. var tmpbuffer = new byte[size + rhs.size + 6]; var offset = 0; // Explanation of the shenenagians here. Size() is uint which is 4 bytes in size, so the byte // array produced by GetBytes is length 4. However, we only increase the offset by 1 (1 byte) // because we don't NEED all 4 bytes, we only need the first byte (due to the small size of packets // and Intel CPUs being little endian. Buffer.BlockCopy(BitConverter.GetBytes(Size()), 0, tmpbuffer, offset++, sizeof(uint)); // shouldn't this be an offset of sizeof(uint)? offset += serialize(tmpbuffer, offset); Buffer.BlockCopy(BitConverter.GetBytes(rhs.Size()), 0, tmpbuffer, offset++, sizeof(uint)); offset += rhs.serialize(tmpbuffer, offset); size = offset; pBuffer = tmpbuffer; opcode = (ushort)OpCodes.OP_Combined; result = true; } return(result); }
private void ProcessPacket(string source, string destination, EQProtocolPacket p) { int processed = 0; int subpacket_length = 0; if (null == p) { return; } //// Raw Application packet //if (p.opcode > 0xff) //{ // p.opcode = p.opcode.HToNus(); //byte order is backwards in the protocol packet // var ap = MakeApplicationPacket(p); // if (null != ap) // { // InboundQueue.TryAdd(ap); // } // return; //} //if (0 == Session && p.OpCodeEnum != OpCodes.OP_SessionRequest && p.OpCodeEnum != OpCodes.OP_SessionResponse) //{ // Log.DetailRule.Debug("Session not initialized, packet ignored"); // // _raw(NET__DEBUG, 0xFFFF, p); // return; //} switch (p.OpCodeEnum) { case OpCodes.OP_Combined: { processed = 0; while (processed < p.size) { subpacket_length = p.pBuffer[processed]; // +1 advances past the packet size byte. var subp = EQStream.MakeProtocolPacket(p.pBuffer, processed + 1, subpacket_length); ProcessPacket(source, destination, subp); //delete subp; processed += subpacket_length + 1; } } break; case OpCodes.OP_AppCombined: { processed = 0; while (processed < p.size) { var ap = default(EQRawApplicationPacket); if ((subpacket_length = p.pBuffer[processed]) != 0xff) { // (unsigned char)*(p->pBuffer + processed))!= 0xff) { //Log.DetailRule.Debug($"Extracting combined app packet of length {subpacket_length}, short len"); // + 1 to skip past the packet size. //System.Diagnostics.Trace.WriteLine($"p.pBuffer = {BitConverter.ToString(p.pBuffer)}, processed = {processed} + 1, subpacket_length: {subpacket_length}"); ap = EQStream.MakeApplicationPacket(p.pBuffer, processed + 1, subpacket_length); //System.Diagnostics.Trace.WriteLine($"ap.GetRawOpcode = {ap.GetRawOpcode()}, ap.pBuffer = {BitConverter.ToString(ap.pBuffer)}"); processed += subpacket_length + 1; //System.Diagnostics.Trace.WriteLine($"processed = {processed}"); } else { // If the first byte of the size is 0xff then this is actually a two byte size, so skip the 0xff // to then get the size. subpacket_length = p.pBuffer.NetU16(processed + 1); // BitConverter.ToUInt16(p.pBuffer, processed + 1).NToHus();//ntohs(*(ushort*)(p->pBuffer + processed + 1)); //Log.DetailRule.Debug($"Extracting combined app packet of length {subpacket_length}, short len"); // Skipping 3 because 1 is 0xff, the next two bytes are the size. ap = EQStream.MakeApplicationPacket(p.pBuffer, processed + 3, subpacket_length); processed += subpacket_length + 3; } if (null != ap) { Console.WriteLine( $"{source} => {destination}, ApplicationPacket: OpCode {ap.opcode}, Data: {BitConverter.ToString(ap.pBuffer)}"); //ap.copyInfo(p); //InboundQueue.TryAdd(ap); } } } break; case OpCodes.OP_Packet: { var seq = p.pBuffer.NetU16(0); // Check for an embedded OP_AppCombinded (protocol level 0x19) if (p.pBuffer[2] == 0x00 && p.pBuffer[3] == 0x19) //if (*(p->pBuffer + 2) == 0x00 && *(p->pBuffer + 3) == 0x19) { var subp = EQStream.MakeProtocolPacket(p.pBuffer, 2, p.size - 2); ProcessPacket(source, destination, subp); } else { var ap = EQStream.MakeApplicationPacket(p.pBuffer, 2, p.size - 2); Console.WriteLine( $"{source} => {destination}, ApplicationPacket: OpCode {ap.opcode}, Data: {BitConverter.ToString(ap.pBuffer)}"); } } break; case OpCodes.OP_Fragment: { if (null == p.pBuffer || (p.Size() < 4)) { Console.WriteLine("Received OP_Fragment that was of malformed size"); break; } var seq = p.pBuffer.NetU16(0); // In case we did queue one before as well. if (PacketQueue.Remove(seq)) { Console.WriteLine($"[NET_TRACE] OP_Fragment: Removing older queued packet with sequence {seq}"); //delete qp; } NextInSeq++; if (null != oversize_buffer) { Buffer.BlockCopy(p.pBuffer, 2, oversize_buffer, oversize_offset, p.size - 2); oversize_offset += p.size - 2; // Does the offset match the total length? If so it means we have assembled the full packet. If not, // that means we're still waiting for all of the parts to arrive. if (oversize_offset == oversize_length) { // We have the full packet. What kind is it? if (p.pBuffer[2] == 0x00 && p.pBuffer[3] == 0x19) { var subp = EQStream.MakeProtocolPacket(oversize_buffer, oversize_offset); ProcessPacket(source, destination, subp); } else { var ap = EQStream.MakeApplicationPacket(oversize_buffer, oversize_offset); if (null != ap) { Console.WriteLine($"{source} => {destination}, {ap.opcode}"); } } } } else { // Allocate space for the fragment. The first fragment contains the total size of the // fragment. oversize_length = p.pBuffer.NetU32(2); // BitConverter.ToUInt32(p.pBuffer, 2).NToHui();//ntohl(*(uint*)(p->pBuffer + 2)); oversize_buffer = new byte[oversize_length]; Buffer.BlockCopy(p.pBuffer, 6, oversize_buffer, 0, p.size - 6); //memcpy(oversize_buffer, p->pBuffer + 6, p->size - 6); oversize_offset = p.size - 6; Console.WriteLine( $"First fragment of oversized of seq {seq}: now at {oversize_offset}/{oversize_length}"); } } break; case OpCodes.OP_KeepAlive: break; case OpCodes.OP_Ack: //Console.WriteLine($"OP_Ack: {p.pBuffer.NetU16(0)}"); break; // default: // { // var ap = MakeApplicationPacket(p); // if (null != ap) // { // InboundQueue.TryAdd(ap); // } // } // break; } }