Beispiel #1
0
        public void SendSessionStats(EQPacket<SessionStats> statsPacket)
        {
            SessionStats sessStats = statsPacket.PacketStruct;  // new SessionStats();
            ulong packsRecv = statsPacket.PacketStruct.PacketsRecieved;
            sessStats.PacketsRecieved = statsPacket.PacketStruct.PacketsSent;
            sessStats.PacketsSent = packsRecv;

            EQPacket<SessionStats> sessStatsPacket = new EQPacket<SessionStats>(ProtocolOpCode.SessionStatResponse, sessStats, _ipe);
            _nonSeqQueue.Enqueue(sessStatsPacket);

            uint avgDelta = RawEQPacket.NetToHostOrder(sessStats.AverageDelta);
            if (avgDelta > 0)
            {
                _rateThreshold = RATE_BASE / (int)avgDelta;
                _decayRate = DECAY_BASE / (int)avgDelta;
                //_log.DebugFormat("Adjusting data rate to thresh {0}, decay {1} based on avg delta {2}", _rateThreshold, _decayRate, avgDelta);
            }
        }
Beispiel #2
0
        // 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;
            }
        }
Beispiel #3
0
        public void SendSessionResponse(SessionFormat format)
        {
            // re-init the client's queues (might have recv this packet again before the writer had a chance to send the session response (eliminates a race))
            ClearQueues();

            SessionResponse sessResp = new SessionResponse();
            sessResp.SessionId = (UInt32)IPAddress.HostToNetworkOrder((int)_sessionId);
            sessResp.MaxLength = (UInt32)IPAddress.HostToNetworkOrder((int)_maxLen);
            sessResp.CRCLength = 2;
            sessResp.Format = (byte)format;
            sessResp.Key = (UInt32)IPAddress.HostToNetworkOrder((int)_key);

            EQPacket<SessionResponse> sessRespPacket = new EQPacket<SessionResponse>(ProtocolOpCode.SessionResponse, sessResp, _ipe);
            //_log.DebugFormat("Sending SessionResponse to client: session: {0}, maxlen: {1}, key: {2}", _sessionId, _maxLen, _key);
            _nonSeqQueue.Enqueue(sessRespPacket);
        }