/// <summary>
        /// Disconnect from this simulator
        /// </summary>
        public void Disconnect(bool sendCloseCircuit)
        {
            if (connected)
            {
                connected = false;

                // Destroy the timers
                if (AckTimer != null)
                {
                    AckTimer.Dispose();
                }
                if (StatsTimer != null)
                {
                    StatsTimer.Dispose();
                }
                if (PingTimer != null)
                {
                    PingTimer.Dispose();
                }

                // Kill the current CAPS system
                if (Caps != null)
                {
                    Caps.Disconnect(true);
                    Caps = null;
                }

                if (sendCloseCircuit)
                {
                    // Try to send the CloseCircuit notice
                    CloseCircuitPacket close = new CloseCircuitPacket();
                    UDPPacketBuffer    buf   = new UDPPacketBuffer(ipEndPoint, false);
                    buf.Data       = close.ToBytes();
                    buf.DataLength = buf.Data.Length;

                    AsyncBeginSend(buf);
                }

                // Shut the socket communication down
                Stop();
            }
        }
        /// <summary>
        /// Send a raw byte array payload as a packet
        /// </summary>
        /// <param name="payload">The packet payload</param>
        /// <param name="setSequence">Whether the second, third, and fourth bytes
        /// should be modified to the current stream sequence number</param>
        public void SendPacket(byte[] payload, bool setSequence)
        {
            try
            {
                if (setSequence && payload.Length > 3)
                {
                    lock (SequenceLock)
                    {
                        payload[1] = (byte)(Sequence >> 16);
                        payload[2] = (byte)(Sequence >> 8);
                        payload[3] = (byte)(Sequence % 256);
                        Sequence++;
                    }
                }

                Stats.SentBytes += (ulong)payload.Length;
                Stats.SentPackets++;

                UDPPacketBuffer buf = new UDPPacketBuffer(ipEndPoint, false);
                buf.Data       = payload;
                buf.DataLength = payload.Length;

                AsyncBeginSend(buf);
            }
            catch (SocketException)
            {
                Logger.Log("Tried to send a " + payload.Length +
                           " byte payload on a closed socket, shutting down " + this.ToString(),
                           Helpers.LogLevel.Info, Client);

                Network.DisconnectSim(this, false);
                return;
            }
            catch (Exception e)
            {
                Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e);
            }
        }
Exemple #3
0
 protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent);
Exemple #4
0
 // these abstract methods must be implemented in a derived class to actually do
 // something with the packets that are sent and received.
 protected abstract void PacketReceived(UDPPacketBuffer buffer);
 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
 {
 }
        protected override void PacketReceived(UDPPacketBuffer buffer)
        {
            Packet packet = null;

            // Check if this packet came from the server we expected it to come from
            if (!ipEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
            {
                Logger.Log("Received " + buffer.DataLength + " bytes of data from unrecognized source " +
                           ((IPEndPoint)buffer.RemoteEndPoint).ToString(), Helpers.LogLevel.Warning, Client);
                return;
            }

            // Update the disconnect flag so this sim doesn't time out
            DisconnectCandidate = false;

            #region Packet Decoding

            int packetEnd = buffer.DataLength - 1;
            packet = Packet.BuildPacket(buffer.Data, ref packetEnd, buffer.ZeroData);

            // Fail-safe check
            if (packet == null)
            {
                Logger.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning, Client);
                return;
            }

            Stats.RecvBytes += (ulong)buffer.DataLength;
            Stats.RecvPackets++;

            #endregion Packet Decoding

            #region Reliable Handling

            if (packet.Header.Reliable)
            {
                // Add this packet to the list of ACKs that need to be sent out
                lock (PendingAcks)
                {
                    uint sequence = (uint)packet.Header.Sequence;
                    if (!PendingAcks.ContainsKey(sequence))
                    {
                        PendingAcks[sequence] = sequence;
                    }
                }

                // Send out ACKs if we have a lot of them
                if (PendingAcks.Count >= Client.Settings.MAX_PENDING_ACKS)
                {
                    SendAcks();
                }

                if (packet.Header.Resent)
                {
                    ++Stats.ReceivedResends;
                }
            }

            #endregion Reliable Handling

            #region Inbox Insertion

            NetworkManager.IncomingPacket incomingPacket;
            incomingPacket.Simulator = this;
            incomingPacket.Packet    = packet;

            // TODO: Prioritize the queue
            Network.PacketInbox.Enqueue(incomingPacket);

            #endregion Inbox Insertion
        }
 /// <summary>
 /// Send a prepared <code>UDPPacketBuffer</code> object as a packet
 /// </summary>
 /// <param name="buffer">The prepared packet structure to be sent out</param>
 public void SendPacket(UDPPacketBuffer buffer)
 {
     try { AsyncBeginSend(buffer); }
     catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
 }
        /// <summary>
        /// Sends a packet
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        /// <param name="incrementSequence">Increment sequence number?</param>
        ///

        public void SendPacket(Packet packet, bool incrementSequence)
        {
            byte[] buffer;
            int    bytes;

            // Keep track of when this packet was sent out
            packet.TickCount = Environment.TickCount;

            if (incrementSequence)
            {
                // Set the sequence number
                lock (SequenceLock)
                {
                    if (Sequence > Settings.MAX_SEQUENCE)
                    {
                        Sequence = 1;
                    }
                    else
                    {
                        Sequence++;
                    }

                    packet.Header.Sequence = Sequence;
                }

                if (packet.Header.Reliable)
                {
                    // Add this packet to the list of ACK responses we are waiting on from the server
                    lock (NeedAck)
                    {
                        if (!NeedAck.ContainsKey(packet.Header.Sequence))
                        {
                            NeedAck.Add(packet.Header.Sequence, packet);
                        }
                        else
                        {
                            Logger.Log("Attempted to add a duplicate sequence number (" +
                                       packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
                                       packet.Type.ToString(), Helpers.LogLevel.Warning, Client);
                        }
                    }

                    if (packet.Header.Resent)
                    {
                        // This packet has already been sent out once, strip any appended ACKs
                        // off it and reinsert them into the outgoing ACK queue under the
                        // assumption that this packet will continually be rejected from the
                        // server or that the appended ACKs are possibly making the delivery fail
                        if (packet.Header.AckList.Length > 0)
                        {
                            Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
                                                          packet.Header.Sequence, packet.GetType()));

                            lock (PendingAcks)
                            {
                                foreach (uint sequence in packet.Header.AckList)
                                {
                                    if (!PendingAcks.ContainsKey(sequence))
                                    {
                                        PendingAcks[sequence] = sequence;
                                    }
                                }
                            }

                            packet.Header.AppendedAcks = false;
                            packet.Header.AckList      = new uint[0];
                        }
                    }
                    else
                    {
                        // This packet is not a resend, check if the conditions are favorable
                        // to ACK appending
                        if (packet.Type != PacketType.PacketAck &&
                            packet.Type != PacketType.LogoutRequest)
                        {
                            lock (PendingAcks)
                            {
                                if (PendingAcks.Count > 0 &&
                                    PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS)
                                {
                                    // Append all of the queued up outgoing ACKs to this packet
                                    packet.Header.AckList = new uint[PendingAcks.Count];

                                    for (int i = 0; i < PendingAcks.Count; i++)
                                    {
                                        packet.Header.AckList[i] = PendingAcks.Values[i];
                                    }

                                    PendingAcks.Clear();
                                    packet.Header.AppendedAcks = true;
                                }
                            }
                        }
                    }
                }
                else if (packet.Header.AckList.Length > 0)
                {
                    // Sanity check for ACKS appended on an unreliable packet, this is bad form
                    Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
                }
            }

            // Serialize the packet
            buffer           = packet.ToBytes();
            bytes            = buffer.Length;
            Stats.SentBytes += (ulong)bytes;
            Stats.SentPackets++;

            UDPPacketBuffer buf;

            // Zerocode if needed
            if (packet.Header.Zerocoded)
            {
                buf = new UDPPacketBuffer(ipEndPoint, true, false);

                bytes          = Helpers.ZeroEncode(buffer, bytes, buf.Data);
                buf.DataLength = bytes;
            }
            else
            {
                buf = new UDPPacketBuffer(ipEndPoint, false, false);

                buf.Data       = buffer;
                buf.DataLength = bytes;
            }

            AsyncBeginSend(buf);
        }
Exemple #9
0
 /// <summary>
 /// Send a prepared <code>UDPPacketBuffer</code> object as a packet
 /// </summary>
 /// <param name="buffer">The prepared packet structure to be sent out</param>
 public void SendPacket(UDPPacketBuffer buffer)
 {
     try { AsyncBeginSend(buffer); }
     catch (Exception e) { Client.Log(e.ToString(), Helpers.LogLevel.Error); }
 }
Exemple #10
0
        /// <summary>
        /// Sends a packet
        /// </summary>
        /// <param name="packet">Packet to be sent</param>
        /// <param name="incrementSequence">Increment sequence number?</param>
        public void SendPacket(Packet packet, bool incrementSequence)
        {
            byte[] buffer;
            int    bytes;

            // Keep track of when this packet was sent out
            packet.TickCount = Environment.TickCount;

            if (incrementSequence)
            {
                // Set the sequence number
                lock (SequenceLock)
                {
                    if (Sequence > Settings.MAX_SEQUENCE)
                    {
                        Sequence = 1;
                    }
                    else
                    {
                        Sequence++;
                    }

                    packet.Header.Sequence = Sequence;
                }

                // Scrub any appended ACKs since all of the ACK handling is done here
                if (packet.Header.AckList.Length > 0)
                {
                    packet.Header.AckList = new uint[0];
                }
                packet.Header.AppendedAcks = false;

                if (packet.Header.Reliable)
                {
                    lock (NeedAck)
                    {
                        if (!NeedAck.ContainsKey(packet.Header.Sequence))
                        {
                            NeedAck.Add(packet.Header.Sequence, packet);
                        }
                        else
                        {
                            Client.Log("Attempted to add a duplicate sequence number (" +
                                       packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
                                       packet.Type.ToString(), Helpers.LogLevel.Warning);
                        }
                    }

                    // Don't append ACKs to resent packets, in case that's what was causing the
                    // delivery to fail
                    if (!packet.Header.Resent)
                    {
                        // Append any ACKs that need to be sent out to this packet
                        lock (PendingAcks)
                        {
                            if (PendingAcks.Count > 0 && PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS &&
                                packet.Type != PacketType.PacketAck &&
                                packet.Type != PacketType.LogoutRequest)
                            {
                                packet.Header.AckList = new uint[PendingAcks.Count];

                                for (int i = 0; i < PendingAcks.Count; i++)
                                {
                                    packet.Header.AckList[i] = PendingAcks.Values[i];
                                }

                                PendingAcks.Clear();
                                packet.Header.AppendedAcks = true;
                            }
                        }
                    }
                }
            }

            // Serialize the packet
            buffer           = packet.ToBytes();
            bytes            = buffer.Length;
            Stats.SentBytes += (ulong)bytes;
            Stats.SentPackets++;

            UDPPacketBuffer buf;

            // Zerocode if needed
            if (packet.Header.Zerocoded)
            {
                buf = new UDPPacketBuffer(ipEndPoint, true, false);

                bytes          = Helpers.ZeroEncode(buffer, bytes, buf.Data);
                buf.DataLength = bytes;
            }
            else
            {
                buf = new UDPPacketBuffer(ipEndPoint, false, false);

                buf.Data       = buffer;
                buf.DataLength = bytes;
            }

            AsyncBeginSend(buf);
        }