public static bool FindPacketAction(PacketCategory category, int protocol, out Action <ByteBuffer, Connection> action) { action = null; if (!AllPackets.TryGetValue(category, out var Category)) { return(false); } return(Category.TryGetValue(protocol, out action)); }
public void SendPacket(UUID agentID, Packet packet, PacketCategory category) { // Look up the UDPClient this is going to UDPClient client; if (!clients.TryGetValue(agentID, out client)) { Logger.Log("Attempted to send a packet to unknown UDP client " + agentID.ToString(), Helpers.LogLevel.Warning); return; } SendPacket(client, packet, category, true); }
void SendPacket(UDPClient client, Packet packet, PacketCategory category, bool setSequence) { byte[] buffer; int bytes; // Set sequence implies that this is not a resent packet if (setSequence) { // Reset to zero if we've hit the upper sequence number limit Interlocked.CompareExchange(ref client.CurrentSequence, 0, 0xFFFFFF); // Increment and fetch the current sequence number uint sequence = (uint)Interlocked.Increment(ref client.CurrentSequence); packet.Header.Sequence = sequence; if (packet.Header.Reliable) { OutgoingPacket outgoing; if (packet.Header.Resent && client.NeedAcks.TryGetValue(packet.Header.Sequence, out outgoing)) { // 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 // client 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 (client.PendingAcks) { foreach (uint ack in packet.Header.AckList) { if (!client.PendingAcks.ContainsKey(ack)) { client.PendingAcks[ack] = ack; } } } packet.Header.AppendedAcks = false; packet.Header.AckList = new uint[0]; } } else { // Wrap this packet in a struct to track timeouts and resends outgoing = new OutgoingPacket(packet); // Add this packet to the list of ACK responses we are waiting on from this client lock (client.NeedAcks) client.NeedAcks[sequence] = outgoing; // This packet is not a resend, check if the conditions are favorable // to ACK appending if (packet.Type != PacketType.PacketAck) { lock (client.PendingAcks) { int count = client.PendingAcks.Count; if (count > 0 && count < 10) { // Append all of the queued up outgoing ACKs to this packet packet.Header.AckList = new uint[count]; for (int i = 0; i < count; i++) { packet.Header.AckList[i] = client.PendingAcks.Values[i]; } client.PendingAcks.Clear(); packet.Header.AppendedAcks = true; } } } } // Update the sent time for this packet outgoing.TickCount = Environment.TickCount; } 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 = new UDPPacketBuffer(client.Address); // Zerocode if needed if (packet.Header.Zerocoded) { bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data); } else { Buffer.BlockCopy(buffer, 0, buf.Data, 0, bytes); } buf.DataLength = bytes; AsyncBeginSend(buf); }
public void BroadcastPacket(Packet packet, PacketCategory category) { clients.ForEach( delegate(UDPClient client) { SendPacket(client, packet, category, true); }); }
public void BroadcastPacket(Packet packet, PacketCategory category) { udpServer.BroadcastPacket(packet, category); }
public void SendPacket(UUID agentID, Packet packet, PacketCategory category) { udpServer.SendPacket(agentID, packet, category); }