internal SessionRequestPacket(RawEQPacket rawPacket) { this._clientIPE = rawPacket.ClientIPE; this._data = rawPacket.RawPacketData; this._SentCRC = rawPacket.SentCRC; this._OpCode = rawPacket.OpCode; GCHandle pinnedBytes = GCHandle.Alloc(GetPayload(), GCHandleType.Pinned); _sessionRequest = (SessionRequest)Marshal.PtrToStructure(pinnedBytes.AddrOfPinnedObject(), typeof(SessionRequest)); pinnedBytes.Free(); }
internal EQRawApplicationPacket(RawEQPacket rawPacket) : base(rawPacket.ClientIPE, rawPacket.RawPacketData) { _OpCode = (AppOpCode)rawPacket.RawOpCode; }
// Process the different protocol packet types private void ProcessRecvPacket(RawEQPacket packet, Client client) { if (packet.RawOpCode > 0x00ff) // Check for application level packet { //_log.Debug("OPCode above 0x00ff."); packet.RawOpCode = (ushort)IPAddress.NetworkToHostOrder((short)packet.RawOpCode); // orig code says opcode byte order is backwards in this case ApplicationPacketReceived(new EQRawApplicationPacket(packet), client); // Handled by specialized server type return; } int subPacketLen = 0, processed = 0; switch (packet.OpCode) { case ProtocolOpCode.None: _log.Error("Protocol OpCode found not set during packet processing... please fix."); break; case ProtocolOpCode.SessionRequest: // Check for existing client - may be getting blitzed w/ session requests if (client.SessionId != 0 && client.ConnectionState == ConnectionState.Established) { _log.Warn("Recv a sessionRequest for an existing open client."); break; } bool add = (client.SessionId == 0); // handles case of existing clients that aren't connected (no need to re-add) EQPacket<SessionRequest> sessReqPacket = new EQPacket<SessionRequest>(packet); lock (client.syncRoot) { client.SessionId = (UInt32)IPAddress.NetworkToHostOrder((int)sessReqPacket.PacketStruct.SessionId); client.MaxLength = (UInt32)IPAddress.NetworkToHostOrder((int)sessReqPacket.PacketStruct.MaxLength); client.Key = 0x11223344; client.ConnectionState = ConnectionState.Established; //_log.Debug(string.Format("Received Session Request: session {0} maxlength {1}", client.SessionId, client.MaxLength)); PreSendSessionResponse(client); } if (add) { _clientListLock.EnterWriteLock(); try { _clients.Add(client.IPEndPoint.ToString(), client); _log.InfoFormat("New client connecting from {0}", client.IPEndPoint.ToString()); } finally { _clientListLock.ExitWriteLock(); } } break; case ProtocolOpCode.SessionResponse: _log.Warn("Received unhandled SessionResponse OPCode"); break; case ProtocolOpCode.Combined: while (processed < packet.GetPayload().Length) { subPacketLen = Buffer.GetByte(packet.GetPayload(), processed); //_log.Debug("Extracting combined packet of length " + subPacketLen); byte[] embBytes = new byte[subPacketLen]; Buffer.BlockCopy(packet.GetPayload(), processed + 1, embBytes, 0, subPacketLen); RawEQPacket embPacket = new RawEQPacket(client.IPEndPoint, embBytes); ProcessRecvPacket(embPacket, client); processed += subPacketLen + 1; } break; case ProtocolOpCode.SessionDisconnect: lock (client.syncRoot) { switch (client.ConnectionState) { case ConnectionState.Established: _log.Debug("Received client initiated disconnect"); lock (client.syncRoot) client.ConnectionState = ConnectionState.Closed; //client.SendDisconnect(ConnectionState.Closed); break; case ConnectionState.Closing: _log.Debug("Received disconnect during a pending close"); lock (client.syncRoot) client.SendDisconnect(ConnectionState.Closed); break; case ConnectionState.Closed: case ConnectionState.Disconnecting: // This is never sent back... handling a different way _log.Debug("Received expected disconnect"); lock (client.syncRoot) client.ConnectionState = ConnectionState.Closed; break; } } break; case ProtocolOpCode.KeepAlive: lock (client.syncRoot) client.NonSequencedQueue.Enqueue(new RawEQPacket(client.IPEndPoint, packet.RawPacketData)); _log.Debug("Received and replied to a KeepAlive"); break; case ProtocolOpCode.SessionStatRequest: EQPacket<SessionStats> statsPacket = new EQPacket<SessionStats>(packet); //_log.DebugFormat("Received Stats: {0} packets recv, {1} packets sent, Deltas: local {2}, ({3} <- {4} -> {5}) remote {6}", // RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.PacketsRecieved), RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.PacketsRecieved), RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.LastLocalDelta), // RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.LowDelta), RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.AverageDelta), // RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.HighDelta), RawEQPacket.NetToHostOrder(statsPacket.PacketStruct.LastRemoteDelta)); lock (client.syncRoot) client.SendSessionStats(statsPacket); break; case ProtocolOpCode.SessionStatResponse: _log.Debug("Received SessionStatResponse OPCode, ignoring"); break; case ProtocolOpCode.Packet: ushort seqNum = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(packet.GetPayload(), 0)); // get seq num //_log.Debug(string.Format("Received Data Packet: session {0} sequence {1}", client.SessionId, seqNum)); // TODO: figure out the locking strategy here // determine the packet sequence if (seqNum > client.NextInSeq) { _log.DebugFormat("Recv future data packet - expected {0} but got {1}", client.NextInSeq, seqNum); lock (client.syncRoot) { client.DataPackets.Remove(seqNum); client.DataPackets.Add(seqNum, packet); // shove into the deferred packet list } } else if (seqNum < client.NextInSeq) { //_log.DebugFormat("Recv duplicate data packet - expected {0} but got {1}", client.NextInSeq, seqNum); client.SendOutOfOrderAck(seqNum); } else { // Received packet w/ expected seq lock (client.syncRoot) { client.DataPackets.Remove(seqNum); // Remove if it was previously queued as a future packet client.SetNextAckToSend(seqNum); // sequenced packets must be ack'd } // check for embedded OP_AppCombined (0x19) ProtocolOpCode embOp = (ProtocolOpCode)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(packet.GetPayload(), 2)); if (embOp == ProtocolOpCode.AppCombined) { //_log.Debug("Found and extracted an embedded packet in a data packet"); byte[] embBytes = new byte[packet.GetPayload().Length - 4]; // snip the data packet sequence num & AppCombined OpCode Buffer.BlockCopy(packet.GetPayload(), 4, embBytes, 0, packet.GetPayload().Length - 4); RawEQPacket embPacket = new RawEQPacket(ProtocolOpCode.AppCombined, embBytes, client.IPEndPoint); ProcessRecvPacket(embPacket, client); } else { // Needs to be handled by specialized server, let's get us an app packet going byte[] appBytes = new byte[packet.GetPayload().Length - 2]; // snip the data packet sequence num Buffer.BlockCopy(packet.GetPayload(), 2, appBytes, 0, packet.GetPayload().Length - 2); ApplicationPacketReceived(new EQRawApplicationPacket(client.IPEndPoint, appBytes), client); } } break; case ProtocolOpCode.Fragment: ushort fragSeqNum = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(packet.GetPayload(), 0)); if (fragSeqNum > client.NextInSeq) { _log.DebugFormat("Recv future fragment - expected {0} but got {1}", client.NextInSeq, fragSeqNum); lock (client.syncRoot) client.DataPackets.Add(fragSeqNum, packet); // shove into the deferred data packet list } else if (fragSeqNum < client.NextInSeq) { //_log.DebugFormat("Recv duplicate data fragment - expected {0} but got {1}", client.NextInSeq, fragSeqNum); client.SendOutOfOrderAck(fragSeqNum); } else { // Received packet w/ expected seq BasePacket bigPacket = null; lock (client.syncRoot) { client.DataPackets.Remove(fragSeqNum); // Remove if it was previously queued as a future packet client.SetNextAckToSend(fragSeqNum); if (client.OversizedBuffer != null) { // copy this round's fragment into the oversized buffer Buffer.BlockCopy(packet.GetPayload(), 2, client.OversizedBuffer, client.OversizedOffset, packet.GetPayload().Length - 2); client.OversizedOffset += packet.GetPayload().Length - 2; //_log.DebugFormat("Recv fragment - seq {0} now at {1}", fragSeqNum, client.OversizedBuffer.Length / client.OversizedOffset); if (client.OversizedOffset == client.OversizedBuffer.Length) { // I totally don't get this first comparison (shouldn't we be looking in the oversized buffer), but ok... if (Buffer.GetByte(packet.GetPayload(), 2) == 0x00 && Buffer.GetByte(packet.GetPayload(), 3) == 0x19) bigPacket = new RawEQPacket(packet.ClientIPE, client.OversizedBuffer); else bigPacket = new EQRawApplicationPacket(client.IPEndPoint, client.OversizedBuffer); client.OversizedBuffer = null; client.OversizedOffset = 0; //_log.Debug("Completed combined oversized packet."); } } else { uint oversizedLen = (uint)IPAddress.NetworkToHostOrder((int)BitConverter.ToUInt32(packet.GetPayload(), 2)); client.OversizedBuffer = new byte[oversizedLen]; // initialize the oversized packet buffer Buffer.BlockCopy(packet.GetPayload(), 6, client.OversizedBuffer, 0, packet.GetPayload().Length - 6); client.OversizedOffset = packet.GetPayload().Length - 6; //_log.DebugFormat("Recv initial fragment packet - total size: {0} fragment len: {1}", oversizedLen, packet.GetPayload().Length - 6); } } if (bigPacket is RawEQPacket) ProcessRecvPacket(bigPacket as RawEQPacket, client); else if(bigPacket is EQRawApplicationPacket) ApplicationPacketReceived(bigPacket as EQRawApplicationPacket, client); } break; case ProtocolOpCode.OutOfOrderAck: _log.Debug("Received OutOfOrderAck OPCode"); break; case ProtocolOpCode.Ack: ushort ackSeqNum = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(packet.GetPayload(), 0)); // get seq num lock (client.syncRoot) client.AckPackets(ackSeqNum); break; case ProtocolOpCode.AppCombined: //_log.Debug("Processing App Combined packet: " + BitConverter.ToString(packet.RawPacketData)); processed = 0; EQRawApplicationPacket appPacket = null; while (processed < packet.GetPayload().Length) { appPacket = null; subPacketLen = Buffer.GetByte(packet.GetPayload(), processed); if (subPacketLen != 0xff) { //_log.Debug("Extracting App Combined packet of length " + subPacketLen); byte[] appBytes = new byte[subPacketLen]; Buffer.BlockCopy(packet.GetPayload(), processed + 1, appBytes, 0, subPacketLen); appPacket = new EQRawApplicationPacket(client.IPEndPoint, appBytes); processed += (subPacketLen + 1); } else { subPacketLen = IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(packet.GetPayload(), processed + 1)); //_log.Debug("Extracting App Combined packet of length " + subPacketLen); byte[] appBytes = new byte[subPacketLen]; Buffer.BlockCopy(packet.GetPayload(), processed + 3, appBytes, 0, subPacketLen); appPacket = new EQRawApplicationPacket(client.IPEndPoint, appBytes); processed += (subPacketLen + 3); } ApplicationPacketReceived(appPacket, client); } break; case ProtocolOpCode.OutOfSession: _log.Debug("Received OutOfSession OPCode, ignoring"); break; default: _log.Warn("Received Unknown Protocol OPCode: " + (ushort)packet.OpCode); break; } }
private void EnqueueSendPacket(RawEQPacket packet) { lock (((ICollection)_sendQueue).SyncRoot) _sendQueue.Enqueue(packet); _writerWaitHandle.Set(); // Signal writer proc }
/// <summary>Implemented by derived class to perform any necessary packet decompression and/or decryption.</summary> internal virtual void PreProcessOutPacket(ref RawEQPacket packet) { }
internal override void PreProcessOutPacket(ref RawEQPacket packet) { // compress the packet byte[] compBuffer = new byte[COMPRESSION_BUFFER_SIZE]; int compLen = EQRawApplicationPacket.Deflate(packet.RawPacketData, ref compBuffer); Array.Resize<byte>(ref compBuffer, compLen); packet = new RawEQPacket(packet.ClientIPE, compBuffer); }
public void SendSequencedPacket(BasePacket appPacket, ProtocolOpCode opCode) { // Wrap in a raw packet and throw on sequenced queue ushort nextOutSeq_no = (ushort)IPAddress.HostToNetworkOrder((short)_nextOutSeq); RawEQPacket packet = new RawEQPacket(opCode, nextOutSeq_no, appPacket.RawPacketData, appPacket.ClientIPE); _nextOutSeq++; lock (((ICollection)_seqQueue).SyncRoot) _seqQueue.Enqueue(packet); }
public void SendDisconnect(ConnectionState connState) { _connState = connState; uint session_no = (uint)IPAddress.HostToNetworkOrder((int)_sessionId); RawEQPacket discPacket = new RawEQPacket(ProtocolOpCode.SessionDisconnect, BitConverter.GetBytes(session_no), _ipe); _log.DebugFormat("Sending Disconnect for session {0}", _sessionId); _nonSeqQueue.Enqueue(discPacket); }
public void SendAck(ushort seqNum) { _lastAckSent = seqNum; ushort seq_no = (ushort)IPAddress.HostToNetworkOrder((short)seqNum); RawEQPacket ackPacket = new RawEQPacket(ProtocolOpCode.Ack, BitConverter.GetBytes(seq_no), _ipe); //_log.Debug(string.Format("Sending Ack with sequence: {0}", seqNum)); _nonSeqQueue.Enqueue(ackPacket); }