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