public void SendAcks(UDPClient client) { PacketAckPacket acks = null; lock (client.PendingAcks) { int count = client.PendingAcks.Count; if (count > 250) { Logger.Log("Too many ACKs queued up!", Helpers.LogLevel.Error); return; } else if (count > 0) { acks = new PacketAckPacket(); acks.Header.Reliable = false; acks.Packets = new PacketAckPacket.PacketsBlock[count]; for (int i = 0; i < count; i++) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = client.PendingAcks.Values[i]; } client.PendingAcks.Clear(); } } if (acks != null) { SendPacket(client, acks, PacketCategory.Overhead, true); } }
public void SendAcks(LLUDPClient udpClient) { uint ack; if (udpClient.PendingAcks.Dequeue(out ack)) { List <PacketAckPacket.PacketsBlock> blocks = new List <PacketAckPacket.PacketsBlock>(); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); while (udpClient.PendingAcks.Dequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true); } }
public void SendAcks(LLAgent agent) { const int MAX_ACKS_PER_PACKET = Byte.MaxValue; uint ack; if (agent.PendingAcks.TryDequeue(out ack)) { List <PacketAckPacket.PacketsBlock> blocks = new List <PacketAckPacket.PacketsBlock>(agent.PendingAcks.Count); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); int count = 1; while (count < MAX_ACKS_PER_PACKET && agent.PendingAcks.TryDequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); ++count; } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); SendPacket(agent, packet, ThrottleCategory.Unknown, false); } }
private void SendAcks() { lock (PendingAcks) { if (PendingAcks.Count > 0) { if (PendingAcks.Count > 250) { // FIXME: Handle the odd case where we have too many pending ACKs queued up OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Too many ACKs queued up!"); return; } //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck"); int i = 0; PacketAckPacket acks = new PacketAckPacket(); acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; foreach (uint ack in PendingAcks.Values) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = ack; i++; } acks.Header.Reliable = false; OutPacket(acks); PendingAcks.Clear(); } } }
/// <summary> /// Sends out pending acknowledgements /// </summary> private void SendAcks() { lock (PendingAcks) { if (PendingAcks.Count > 0) { if (PendingAcks.Count > 250) { Logger.Log("Too many ACKs queued up!", Helpers.LogLevel.Error, Client); return; } PacketAckPacket acks = new PacketAckPacket(); acks.Header.Reliable = false; acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; for (int i = 0; i < PendingAcks.Count; i++) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = PendingAcks.Values[i]; } SendPacket(acks, true); PendingAcks.Clear(); } } }
/// <summary> /// Sends out pending acknowledgements /// </summary> /// <returns>Number of ACKs sent</returns> private int SendAcks() { uint ack; int ackCount = 0; if (PendingAcks.TryDequeue(out ack)) { List <PacketAckPacket.PacketsBlock> blocks = new List <PacketAckPacket.PacketsBlock>(); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); while (PendingAcks.TryDequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); ackCount = blocks.Count; SendPacket(packet); } return(ackCount); }
// Send the pending packet acks to the client // Will send blocks of acks for up to 250 packets // private void SendAcks() { lock (m_NeedAck) { if (m_PendingAcks.Count == 0) { return; } PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); // The case of equality is more common than one might think, // because this function will be called unconditionally when // the counter reaches 250. So there is a good chance another // packet with 250 blocks exists. // if (acks.Packets == null || acks.Packets.Length != m_PendingAcks.Count) { acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count]; } int i = 0; foreach (uint ack in new List <uint>(m_PendingAcks.Keys)) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = ack; m_PendingAcks.Remove(ack); i++; } acks.Header.Reliable = false; OutPacket(acks, ThrottleOutPacketType.Unknown); } }
public void InPacket(Packet packet) { if (packet == null) { return; } // When too many acks are needed to be sent, the client sends // a packet consisting of acks only // if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) { ProcessAck(block.ID); } PacketPool.Instance.ReturnPacket(packet); return; } // Any packet can have some packet acks in the header. // Process them here // if (packet.Header.AppendedAcks) { foreach (uint id in packet.Header.AckList) { ProcessAck(id); } } // If this client is on another partial instance, no need // to handle packets // if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest) { PacketPool.Instance.ReturnPacket(packet); return; } if (packet.Type == PacketType.StartPingCheck) { StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck); endPing.PingID.PingID = startPing.PingID.PingID; OutPacket(endPing, ThrottleOutPacketType.Task); } else { LLQueItem item = new LLQueItem(); item.Packet = packet; item.Incoming = true; m_PacketQueue.Enqueue(item); } }
/// <summary> /// Sends out pending acknowledgements /// </summary> private void SendAcks(NetworkInfo User_info) { lock (User_info.PendingAcks) { if (connected && User_info.PendingAcks.Count > 0) { if (User_info.PendingAcks.Count > 250) { // FIXME: Handle the odd case where we have too many pending ACKs queued up //Client.Log("Too many ACKs queued up!", Helpers.LogLevel.Error); return; } int i = 0; PacketAckPacket acks = new PacketAckPacket(); acks.Packets = new PacketAckPacket.PacketsBlock[User_info.PendingAcks.Count]; foreach (uint ack in User_info.PendingAcks.Values) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = ack; i++; } acks.Header.Reliable = false; SendPacket(acks, true, User_info); User_info.PendingAcks.Clear(); } } }
/// <summary> /// Return a packet to the packet pool /// </summary> /// <param name="packet"></param> public void ReturnPacket(Packet packet) { if (!RecyclePackets) { return; } bool trypool = false; PacketType type = packet.Type; switch (type) { case PacketType.ObjectUpdate: ObjectUpdatePacket oup = (ObjectUpdatePacket)packet; oup.ObjectData = null; trypool = true; break; case PacketType.ImprovedTerseObjectUpdate: ImprovedTerseObjectUpdatePacket itoup = (ImprovedTerseObjectUpdatePacket)packet; itoup.ObjectData = null; trypool = true; break; case PacketType.PacketAck: PacketAckPacket ackup = (PacketAckPacket)packet; ackup.Packets = null; trypool = true; break; case PacketType.AgentUpdate: trypool = true; break; default: return; } if (!trypool) { return; } lock (pool) { if (!pool.ContainsKey(type)) { pool[type] = new Stack <Packet>(); } if ((pool[type]).Count < 50) { // m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); pool[type].Push(packet); } } }
public void TestAddClient() { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); AddUdpServer(); UUID myAgentUuid = TestHelpers.ParseTail(0x1); UUID mySessionUuid = TestHelpers.ParseTail(0x2); uint myCircuitCode = 123456; IPEndPoint testEp = new IPEndPoint(IPAddress.Loopback, 999); UseCircuitCodePacket uccp = new UseCircuitCodePacket(); UseCircuitCodePacket.CircuitCodeBlock uccpCcBlock = new UseCircuitCodePacket.CircuitCodeBlock(); uccpCcBlock.Code = myCircuitCode; uccpCcBlock.ID = myAgentUuid; uccpCcBlock.SessionID = mySessionUuid; uccp.CircuitCode = uccpCcBlock; byte[] uccpBytes = uccp.ToBytes(); UDPPacketBuffer upb = new UDPPacketBuffer(testEp, uccpBytes.Length); upb.DataLength = uccpBytes.Length; // God knows why this isn't set by the constructor. Buffer.BlockCopy(uccpBytes, 0, upb.Data, 0, uccpBytes.Length); m_udpServer.PacketReceived(upb); // Presence shouldn't exist since the circuit manager doesn't know about this circuit for authentication yet Assert.That(m_scene.GetScenePresence(myAgentUuid), Is.Null); AgentCircuitData acd = new AgentCircuitData(); acd.AgentID = myAgentUuid; acd.SessionID = mySessionUuid; m_scene.AuthenticateHandler.AddNewCircuit(myCircuitCode, acd); m_udpServer.PacketReceived(upb); // Should succeed now ScenePresence sp = m_scene.GetScenePresence(myAgentUuid); Assert.That(sp.UUID, Is.EqualTo(myAgentUuid)); Assert.That(m_udpServer.PacketsSent.Count, Is.EqualTo(1)); Packet packet = m_udpServer.PacketsSent[0]; Assert.That(packet, Is.InstanceOf(typeof(PacketAckPacket))); PacketAckPacket ackPacket = packet as PacketAckPacket; Assert.That(ackPacket.Packets.Length, Is.EqualTo(1)); Assert.That(ackPacket.Packets[0].ID, Is.EqualTo(0)); }
void SendAck(UDPClient client, uint ack) { PacketAckPacket acks = new PacketAckPacket(); acks.Header.Reliable = false; acks.Packets = new PacketAckPacket.PacketsBlock[1]; acks.Packets[0] = new PacketAckPacket.PacketsBlock(); acks.Packets[0].ID = ack; SendPacket(client, acks, PacketCategory.Overhead, true); }
public virtual void InPacket(Packet NewPack) { // Handle appended ACKs if (NewPack.Header.AppendedAcks) { lock (NeedAck) { foreach (uint ack in NewPack.Header.AckList) { NeedAck.Remove(ack); } } } // Handle PacketAck packets if (NewPack.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)NewPack; lock (NeedAck) { foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) { NeedAck.Remove(block.ID); } } } else if ((NewPack.Type == PacketType.StartPingCheck)) { //reply to pingcheck libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); endPing.PingID.PingID = startPing.PingID.PingID; OutPacket(endPing); } else { QueItem item = new QueItem(); item.Packet = NewPack; item.Incoming = true; this.PacketQueue.Enqueue(item); } }
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) { PacketAckPacket ack = new PacketAckPacket(); ack.Header.Reliable = false; ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0].ID = sequenceNumber; byte[] packetData = ack.ToBytes(); int length = packetData.Length; UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); buffer.DataLength = length; Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); AsyncBeginSend(buffer); }
private void SendACK(uint id) { try { PacketAckPacket ack = new PacketAckPacket(); ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0].ID = id; ack.Header.Reliable = false; // Set the sequence number ack.Header.Sequence = ++Sequence; Listener.SendTo(ack.ToBytes(), RemoteEndpoint); } catch (Exception e) { Console.WriteLine(e.ToString()); } }
private void ack_pack(Packet Pack) { if (Pack.Header.Reliable) { libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); ack_it.Packets[0].ID = Pack.Header.Sequence; ack_it.Header.Reliable = false; OutPacket(ack_it); } /* * if (Pack.Header.Reliable) * { * lock (PendingAcks) * { * uint sequence = (uint)Pack.Header.Sequence; * if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } * } * }*/ }
public void SendAcks(LLUDPClient udpClient) { uint ack; if (udpClient.PendingAcks.Dequeue(out ack)) { List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); while (udpClient.PendingAcks.Dequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); SendPacket(udpClient, packet, ThrottleOutPacketType.Unknown, true, null); } }
public virtual void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack) { byte[] packetData = ack.ToBytes(); int length = packetData.Length; UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); buffer.DataLength = length; Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); AsyncBeginSend(buffer); }
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) { PacketAckPacket ack = new PacketAckPacket(); ack.Header.Reliable = false; ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0].ID = sequenceNumber; byte[] packetData = ack.ToBytes(); int length = packetData.Length; UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length); buffer.DataLength = length; Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); // AsyncBeginSend(buffer); SyncSend(buffer); }
// SeparateAck: create a standalone PacketAck for packet's appended ACKs public Packet SeparateAck(Packet packet) { PacketAckPacket seperate = new PacketAckPacket(); seperate.Packets = new PacketAckPacket.PacketsBlock[packet.Header.AckList.Length]; for (int i = 0; i < packet.Header.AckList.Length; ++i) { seperate.Packets[i] = new PacketAckPacket.PacketsBlock(); seperate.Packets[i].ID = packet.Header.AckList[i]; } Packet ack = seperate; ack.Header.Sequence = packet.Header.Sequence; return ack; }
// SpoofAck: create an ACK for the given packet public Packet SpoofAck(uint sequence) { PacketAckPacket spoof = new PacketAckPacket(); spoof.Packets = new PacketAckPacket.PacketsBlock[1]; spoof.Packets[0] = new PacketAckPacket.PacketsBlock(); spoof.Packets[0].ID = sequence; return (Packet)spoof; //Legacy: ////Hashtable blocks = new Hashtable(); ////Hashtable fields = new Hashtable(); ////fields["ID"] = (uint)sequence; ////blocks[fields] = "Packets"; ////return .BuildPacket("PacketAck", proxyConfig.protocol, blocks, Helpers.MSG_ZEROCODED); }
void SendAcks() { PacketAckPacket acks = null; lock (pendingAcks) { if (pendingAcks.Count > 0) { if (pendingAcks.Count > 250) { Logger.Log("Too many ACKs queued up!", Helpers.LogLevel.Error); return; } acks = new PacketAckPacket(); acks.Header.Reliable = false; acks.Packets = new PacketAckPacket.PacketsBlock[pendingAcks.Count]; for (int i = 0; i < pendingAcks.Count; i++) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = pendingAcks.Values[i]; } pendingAcks.Clear(); } } if (acks != null) SendPacket(acks, true); }
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) { PacketAckPacket ack = new PacketAckPacket {Header = {Reliable = false}, Packets = new PacketAckPacket.PacketsBlock[1]}; ack.Packets[0] = new PacketAckPacket.PacketsBlock {ID = sequenceNumber}; byte[] packetData = ack.ToBytes(); int length = packetData.Length; UDPPacketBuffer buffer = new UDPPacketBuffer(remoteEndpoint, length) {DataLength = length}; Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); SyncSend(buffer); }
public void SendAcks(LLAgent agent) { const int MAX_ACKS_PER_PACKET = Byte.MaxValue; uint ack; if (agent.PendingAcks.TryDequeue(out ack)) { List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(agent.PendingAcks.Count); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); int count = 1; while (count < MAX_ACKS_PER_PACKET && agent.PendingAcks.TryDequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); ++count; } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); SendPacket(agent, packet, ThrottleCategory.Unknown, false); } }
// SeparateAck: create a standalone PacketAck for packet's appended ACKs public Packet SeparateAck(Packet packet) { PacketAckPacket seperate = new PacketAckPacket(); int ackCount = ((packet.Header.Data[0] & Helpers.MSG_APPENDED_ACKS) == 0 ? 0 : (int)packet.Header.Data[packet.Header.Data.Length - 1]); seperate.Packets = new PacketAckPacket.PacketsBlock[ackCount]; for (int i = 0; i < ackCount; ++i) { int offset = packet.Header.Data.Length - (ackCount - i) * 4 - 1; seperate.Packets[i].ID = (uint) ((packet.Header.Data[offset++] << 0) + (packet.Header.Data[offset++] << 8) + (packet.Header.Data[offset++] << 16) + (packet.Header.Data[offset++] << 24)) ; } Packet ack = (Packet)seperate; ack.Header.Sequence = packet.Header.Sequence; return ack; }
private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) { PacketAckPacket ack = new PacketAckPacket(); ack.Header.Reliable = false; ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0].ID = sequenceNumber; byte[] packetData = ack.ToBytes(); int length = packetData.Length; OutgoingPacket outgoingPacket = new OutgoingPacket(null, packetData, 0, length, remoteEndpoint, false, PacketType.PacketAck); AsyncBeginSend(outgoingPacket); }
protected override void PacketReceived(UDPPacketBuffer buffer) { // Debugging/Profiling //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } //catch (Exception) { } LLUDPClient udpClient = null; Packet packet = null; int packetEnd = buffer.DataLength - 1; IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; #region Decoding try { packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } catch (MalformedDataException) { } // Fail-safe check if (packet == null) { m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", buffer.DataLength, buffer.RemoteEndPoint); m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); return; } #endregion Decoding #region Packet to Client Mapping // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) { object[] array = new object[] { buffer, packet }; if (m_asyncPacketHandling) { Util.FireAndForget(HandleUseCircuitCode, array); } else { HandleUseCircuitCode(array); } return; } // Determine which agent this packet came from IClientAPI client; if (!m_scene.TryGetClient(address, out client) || !(client is LLClientView)) { //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); return; } udpClient = ((LLClientView)client).UDPClient; if (!udpClient.IsConnected) { return; } #endregion Packet to Client Mapping // Stats tracking Interlocked.Increment(ref udpClient.PacketsReceived); int now = Environment.TickCount & Int32.MaxValue; udpClient.TickLastPacketReceived = now; #region ACK Receiving // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { for (int i = 0; i < packet.Header.AckList.Length; i++) { udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; for (int i = 0; i < ackPacket.Packets.Length; i++) { udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); } // We don't need to do anything else with PacketAck packets return; } #endregion ACK Receiving #region ACK Sending if (packet.Header.Reliable) { udpClient.PendingAcks.Enqueue(packet.Header.Sequence); // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove // 2*MTU bytes from the value and send ACKs, and finally add the local value back to // client.BytesSinceLastACK. Lockless thread safety int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); bytesSinceLastACK += buffer.DataLength; if (bytesSinceLastACK > LLUDPServer.MTU * 2) { bytesSinceLastACK -= LLUDPServer.MTU * 2; SendAcks(udpClient); } Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK); } #endregion ACK Sending #region Incoming Packet Accounting // Check the archive of received reliable packet IDs to see whether we already received this packet if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) { if (packet.Header.Resent) { m_log.DebugFormat( "[LLUDPSERVER]: Received a resend of already processed packet #{0}, type {1} from {2}", packet.Header.Sequence, packet.Type, client.Name); } else { m_log.WarnFormat( "[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #{0}, type {1} from {2}", packet.Header.Sequence, packet.Type, client.Name); } // Avoid firing a callback twice for the same packet return; } #endregion Incoming Packet Accounting #region BinaryStats LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); #endregion BinaryStats #region Ping Check Handling if (packet.Type == PacketType.StartPingCheck) { // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(udpClient, startPing.PingID.PingID); if ((Environment.TickCount - m_elapsedMSSinceLastStatReport) >= 3000) { udpClient.SendPacketStats(); m_elapsedMSSinceLastStatReport = Environment.TickCount; } return; } else if (packet.Type == PacketType.CompletePingCheck) { // We don't currently track client ping times return; } #endregion Ping Check Handling // Inbox insertion packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); }
/// <summary> /// Sends out pending acknowledgements /// </summary> private void SendAcks(NetworkInfo User_info) { lock (User_info.PendingAcks) { if (connected && User_info.PendingAcks.Count > 0) { if (User_info.PendingAcks.Count > 250) { // FIXME: Handle the odd case where we have too many pending ACKs queued up //Client.Log("Too many ACKs queued up!", Helpers.LogLevel.Error); return; } int i = 0; PacketAckPacket acks = new PacketAckPacket(); acks.Packets = new PacketAckPacket.PacketsBlock[User_info.PendingAcks.Count]; foreach (uint ack in User_info.PendingAcks.Values) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = ack; i++; } acks.Header.Reliable = false; SendPacket(acks, true,User_info); User_info.PendingAcks.Clear(); } } }
public override void SendAckImmediate(IPEndPoint remoteEndpoint, PacketAckPacket ack) { PacketsSent.Add(ack); }
protected override void PacketReceived(UDPPacketBuffer buffer) { Packet packet = null; // Check if this packet came from the server we expected it to come from if (!remoteEndPoint.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; try { packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[8192] : null); } catch (MalformedDataException) { Logger.Log(String.Format("Malformed data, cannot parse packet:\n{0}", Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)), Helpers.LogLevel.Error); } // Fail-safe check if (packet == null) { Logger.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning, Client); return; } Interlocked.Add(ref Stats.RecvBytes, buffer.DataLength); Interlocked.Increment(ref Stats.RecvPackets); #endregion Packet Decoding if (packet.Header.Resent) { Interlocked.Increment(ref Stats.ReceivedResends); } #region ACK Receiving // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { lock (NeedAck) { for (int i = 0; i < packet.Header.AckList.Length; i++) { NeedAck.Remove(packet.Header.AckList[i]); } } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; lock (NeedAck) { for (int i = 0; i < ackPacket.Packets.Length; i++) { NeedAck.Remove(ackPacket.Packets[i].ID); } } } #endregion ACK Receiving if (packet.Header.Reliable) { #region ACK Sending // Add this packet to the list of ACKs that need to be sent out uint sequence = (uint)packet.Header.Sequence; PendingAcks.Enqueue(sequence); // Send out ACKs if we have a lot of them if (PendingAcks.Count >= Client.Settings.MAX_PENDING_ACKS) { SendAcks(); } #endregion ACK Sending // Check the archive of received packet IDs to see whether we already received this packet if (!PacketArchive.TryEnqueue(packet.Header.Sequence)) { if (packet.Header.Resent) { Logger.DebugLog("Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); } else { Logger.Log("Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type, Helpers.LogLevel.Warning); } // Avoid firing a callback twice for the same packet return; } } #region Inbox Insertion NetworkManager.IncomingPacket incomingPacket; incomingPacket.Simulator = this; incomingPacket.Packet = packet; Network.PacketInbox.Enqueue(incomingPacket); #endregion Inbox Insertion #region Stats Tracking if (Client.Settings.TRACK_UTILIZATION) { Client.Stats.Update(packet.Type.ToString(), OpenMetaverse.Stats.Type.Packet, 0, packet.Length); } #endregion }
protected override void PacketReceived(UDPPacketBuffer buffer) { // Debugging/Profiling //try { Thread.CurrentThread.Name = "PacketReceived (" + m_scene.RegionInfo.RegionName + ")"; } //catch (Exception) { } Packet packet = null; int packetEnd = buffer.DataLength - 1; IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; int now = Util.TickCount(); #region Decoding try { packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } catch (MalformedDataException) { m_log.ErrorFormat("Malformed data, cannot parse packet from {0}:\n{1}", buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); } // Fail-safe check if (packet == null) { m_log.Warn("Couldn't build a message from incoming data " + buffer.DataLength + " bytes long from " + buffer.RemoteEndPoint); return; } #endregion Decoding #region Packet to Client Mapping // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) { m_log.Debug("Handling UseCircuitCode packet from " + buffer.RemoteEndPoint); HandleUseCircuitCode(buffer, (UseCircuitCodePacket)packet, now); return; } // Determine which agent this packet came from LLAgent agent; if (!m_clients.TryGetValue(address, out agent)) { m_log.Debug("Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + Scene.Name); return; } if (!agent.IsConnected) { return; } #endregion Packet to Client Mapping #region Stats Tracking Interlocked.Increment(ref m_packetsReceived); Interlocked.Increment(ref agent.PacketsReceived); agent.TickLastPacketReceived = now; if (LoggingEnabled) { m_log.Debug("--> (" + buffer.RemoteEndPoint + ") " + packet.Type); } #endregion Stats Tracking #region ACK Receiving // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { for (int i = 0; i < packet.Header.AckList.Length; i++) { agent.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent); } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; for (int i = 0; i < ackPacket.Packets.Length; i++) { agent.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent); } // We don't need to do anything else with PacketAck packets return; } #endregion ACK Receiving #region Incoming Packet Accounting // Check the archive of received reliable packet IDs to see whether we already received this packet if (packet.Header.Reliable && !agent.PacketArchive.TryEnqueue(packet.Header.Sequence)) { if (packet.Header.Resent) { m_log.Debug("Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); } else { m_log.Warn("Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type); } // ACK this packet immediately to avoid further resends of this same packet SendAckImmediate((IPEndPoint)buffer.RemoteEndPoint, packet.Header.Sequence); // Avoid firing a callback twice for the same packet return; } #endregion Incoming Packet Accounting #region ACK Sending if (packet.Header.Reliable) { agent.PendingAcks.Enqueue(packet.Header.Sequence); } #endregion ACK Sending #region Ping Check Handling if (packet.Type == PacketType.StartPingCheck) { // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(agent, startPing.PingID.PingID); return; } else if (packet.Type == PacketType.CompletePingCheck) { // We don't currently track client ping times return; } #endregion Ping Check Handling // Inbox insertion m_packetInbox.Enqueue(new IncomingPacket(agent, packet, now)); }
public void SendAck(uint ack) { PacketAckPacket acks = new PacketAckPacket(); acks.Header.Reliable = false; acks.Packets = new PacketAckPacket.PacketsBlock[1]; acks.Packets[0] = new PacketAckPacket.PacketsBlock(); acks.Packets[0].ID = ack; SendPacket(acks, true); }
/// <summary> /// Callback handler for incomming data /// </summary> /// <param name="result"></param> private void OnReceivedData(IAsyncResult result) { ipeSender = new IPEndPoint(IPAddress.Any, 0); epSender = (EndPoint)ipeSender; Packet packet = null; int numBytes; // If we're receiving data the sim connection is open connected = true; // Update the disconnect flag so this sim doesn't time out DisconnectCandidate = false; NetworkInfo User_info = null; lock (RecvBuffer) { // Retrieve the incoming packet try { numBytes = Connection.EndReceiveFrom(result, ref epSender); //find user_agent_info int packetEnd = numBytes - 1; packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer); //should check if login/useconnection packet first if (packet.Type == PacketType.UseCircuitCode) { //new connection //TODO check that this circuit and session is expected UseCircuitCodePacket cir_pack = (UseCircuitCodePacket)packet; NetworkInfo new_user = new NetworkInfo(); new_user.CircuitCode = cir_pack.CircuitCode.Code; new_user.User.AgentID = cir_pack.CircuitCode.ID; new_user.User.SessionID = cir_pack.CircuitCode.SessionID; new_user.endpoint = epSender; new_user.Inbox = new Queue <uint>(Settings.INBOX_SIZE); new_user.Connection = new ClientConnection(); new_user.Connection.NetInfo = new_user; new_user.Connection.Start(); //this.CallbackObject.NewUserCallback(new_user); this.User_agents.Add(new_user); } NetworkInfo temp_agent = null; IPEndPoint send_ip = (IPEndPoint)epSender; // this.callback_object.error("incoming: address is "+send_ip.Address +"port number is: "+send_ip.Port.ToString()); for (int ii = 0; ii < this.User_agents.Count; ii++) { temp_agent = (NetworkInfo)this.User_agents[ii]; IPEndPoint ag_ip = (IPEndPoint)temp_agent.endpoint; //this.callback_object.error("searching: address is "+ag_ip.Address +"port number is: "+ag_ip.Port.ToString()); if ((ag_ip.Address.ToString() == send_ip.Address.ToString()) && (ag_ip.Port.ToString() == send_ip.Port.ToString())) { //this.callback_object.error("found user"); User_info = temp_agent; break; } } Connection.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); } catch (SocketException) { // Client.Log(endPoint.ToString() + " socket is closed, shutting down " + this.Region.Name, // Helpers.LogLevel.Info); connected = false; //Network.DisconnectSim(this); return; } } if (User_info == null) { //error finding agent //this.CallbackObject.ErrorCallback("no user found"); return; } // Fail-safe check if (packet == null) { //this.CallbackObject.ErrorCallback("couldn't build packet"); // Client.Log("Couldn't build a message from the incoming data", Helpers.LogLevel.Warning); return; } //this.callback_object.error("past tests"); // Track the sequence number for this packet if it's marked as reliable if (packet.Header.Reliable) { if (User_info.PendingAcks.Count > Settings.MAX_PENDING_ACKS) { SendAcks(User_info); } // Check if we already received this packet if (User_info.Inbox.Contains(packet.Header.Sequence)) { //Client.Log("Received a duplicate " + packet.Type.ToString() + ", sequence=" + // packet.Header.Sequence + ", resent=" + ((packet.Header.Resent) ? "Yes" : "No") + // ", Inbox.Count=" + Inbox.Count + ", NeedAck.Count=" + NeedAck.Count, // Helpers.LogLevel.Info); // Send an ACK for this packet immediately //SendAck(packet.Header.Sequence); // TESTING: Try just queuing up ACKs for resent packets instead of immediately triggering an ACK lock (User_info.PendingAcks) { uint sequence = (uint)packet.Header.Sequence; if (!User_info.PendingAcks.ContainsKey(sequence)) { User_info.PendingAcks[sequence] = sequence; } } // Avoid firing a callback twice for the same packet // this.callback_object.error("avoiding callback"); return; } else { lock (User_info.PendingAcks) { uint sequence = (uint)packet.Header.Sequence; if (!User_info.PendingAcks.ContainsKey(sequence)) { User_info.PendingAcks[sequence] = sequence; } } } } // Add this packet to our inbox lock (User_info.Inbox) { while (User_info.Inbox.Count >= Settings.INBOX_SIZE) { User_info.Inbox.Dequeue(); } User_info.Inbox.Enqueue(packet.Header.Sequence); } // Handle appended ACKs if (packet.Header.AppendedAcks) { lock (User_info.NeedAck) { foreach (uint ack in packet.Header.AckList) { User_info.NeedAck.Remove(ack); } } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; lock (User_info.NeedAck) { foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) { User_info.NeedAck.Remove(block.ID); } } } //if it is a ping check send return if ((packet.Type == PacketType.StartPingCheck)) { //reply to pingcheck libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)packet; libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); endPing.PingID.PingID = startPing.PingID.PingID; SendPacket(endPing, true, User_info); } else if (packet.Type != PacketType.PacketAck) { User_info.Connection.InQueue.Enqueue(packet); } }
/// <summary> /// Sends out pending acknowledgements /// </summary> /// <returns>Number of ACKs sent</returns> private int SendAcks() { uint ack; int ackCount = 0; if (PendingAcks.TryDequeue(out ack)) { List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); while (PendingAcks.TryDequeue(out ack)) { block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); ackCount = blocks.Count; SendPacket(packet); } return ackCount; }
/// <summary> /// Add a new client circuit. /// </summary> /// <param name="packet"></param> /// <param name="epSender"></param> /// <param name="epProxy"></param> protected virtual void AddNewClient(UseCircuitCodePacket useCircuit, EndPoint epSender, EndPoint epProxy) { //Slave regions don't accept new clients if (m_localScene.RegionStatus != RegionStatus.SlaveScene) { AuthenticateResponse sessionInfo; bool isNewCircuit = false; if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) { m_log.WarnFormat( "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, epSender); return; } lock (clientCircuits) { if (!clientCircuits.ContainsKey(epSender)) { clientCircuits.Add(epSender, useCircuit.CircuitCode.Code); isNewCircuit = true; } } if (isNewCircuit) { // This doesn't need locking as it's synchronized data clientCircuits_reverse[useCircuit.CircuitCode.Code] = epSender; lock (proxyCircuits) { proxyCircuits[useCircuit.CircuitCode.Code] = epProxy; } m_packetServer.AddNewClient(epSender, useCircuit, m_assetCache, sessionInfo, epProxy); //m_log.DebugFormat( // "[CONNECTION SUCCESS]: Incoming client {0} (circuit code {1}) received and authenticated for {2}", // useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, m_localScene.RegionInfo.RegionName); } } // Ack the UseCircuitCode packet PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck); // TODO: don't create new blocks if recycling an old packet ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); ack_it.Packets[0].ID = useCircuit.Header.Sequence; // ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) is just a failsafe to ensure that we don't overflow. ack_it.Header.Sequence = ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) + 1; ack_it.Header.Reliable = false; byte[] ackmsg = ack_it.ToBytes(); // Need some extra space in case we need to add proxy // information to the message later byte[] msg = new byte[4096]; Buffer.BlockCopy(ackmsg, 0, msg, 0, ackmsg.Length); SendPacketTo(msg, ackmsg.Length, SocketFlags.None, useCircuit.CircuitCode.Code); PacketPool.Instance.ReturnPacket(useCircuit); }
// CheckAcks: check for and remove ACKs of packets we've injected public Packet CheckAcks(Packet packet, Direction direction, ref int length, ref bool needsCopy) { Dictionary<uint, Packet> acks = direction == Direction.Incoming ? outgoingAcks : incomingAcks; List<uint> seenAcks = direction == Direction.Incoming ? outgoingSeenAcks : incomingSeenAcks; if (acks.Count == 0) return packet; // check for embedded ACKs if (packet.Type == PacketType.PacketAck) { bool changed = false; List<PacketAckPacket.PacketsBlock> newPacketBlocks = new List<PacketAckPacket.PacketsBlock>(); foreach (PacketAckPacket.PacketsBlock pb in ((PacketAckPacket)packet).Packets) { uint id = pb.ID; #if DEBUG_SEQUENCE string hrup = "Check !" + id; #endif if (acks.ContainsKey(id)) { #if DEBUG_SEQUENCE hrup += " get's"; #endif acks.Remove(id); seenAcks.Add(id); changed = true; } else newPacketBlocks.Add(pb); #if DEBUG_SEQUENCE Console.WriteLine(hrup); #endif } if (changed) { PacketAckPacket newPacket = new PacketAckPacket(); newPacket.Packets = new PacketAckPacket.PacketsBlock[newPacketBlocks.Count]; int a = 0; foreach (PacketAckPacket.PacketsBlock pb in newPacketBlocks) { newPacket.Packets[a++] = pb; } SwapPacket(packet, (Packet)newPacket); packet = newPacket; length = packet.Header.Data.Length; needsCopy = false; } } // check for appended ACKs if ((packet.Header.Data[0] & Helpers.MSG_APPENDED_ACKS) != 0) { int ackCount = packet.Header.AckList.Length; for (int i = 0; i < ackCount; ) { uint ackID = packet.Header.AckList[i]; // FIXME FIXME FIXME #if DEBUG_SEQUENCE string hrup = "Check @" + ackID; #endif if (acks.ContainsKey(ackID)) { #if DEBUG_SEQUENCE hrup += " get's"; #endif uint[] newAcks = new uint[ackCount - 1]; Array.Copy(packet.Header.AckList, 0, newAcks, 0, i); Array.Copy(packet.Header.AckList, i + 1, newAcks, i, ackCount - i - 1); packet.Header.AckList = newAcks; --ackCount; acks.Remove(ackID); seenAcks.Add(ackID); needsCopy = false; } else ++i; #if DEBUG_SEQUENCE Console.WriteLine(hrup); #endif } if (ackCount == 0) { packet.Header.Flags ^= Helpers.MSG_APPENDED_ACKS; packet.Header.AckList = new uint[0]; } } return packet; }
private void PacketHandler() { IncomingPacket incomingPacket = new IncomingPacket(); Packet packet = null; Simulator simulator = null; while (connected) { // Reset packet to null for the check below packet = null; if (PacketInbox.Dequeue(200, ref incomingPacket)) { packet = incomingPacket.Packet; simulator = incomingPacket.Simulator; if (packet != null) { // Skip the ACK handling on packets synthesized from CAPS messages if (packet.Header.Sequence != 0) { #region ACK accounting // TODO: Replace PacketArchive Queue<> with something more efficient // Check the archives to see whether we already received this packet lock (simulator.PacketArchive) { if (simulator.PacketArchive.Contains(packet.Header.Sequence)) { if (packet.Header.Resent) { Client.DebugLog("Received resent packet #" + packet.Header.Sequence); } else { Client.Log(String.Format("Received a duplicate of packet #{0}, current type: {1}", packet.Header.Sequence, packet.Type), Helpers.LogLevel.Warning); } // Avoid firing a callback twice for the same packet continue; } else { // Keep the PacketArchive size within a certain capacity while (simulator.PacketArchive.Count >= Settings.PACKET_ARCHIVE_SIZE) { simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue(); simulator.PacketArchive.Dequeue(); } simulator.PacketArchive.Enqueue(packet.Header.Sequence); } } #endregion ACK accounting #region ACK handling // Handle appended ACKs if (packet.Header.AppendedAcks) { lock (simulator.NeedAck) { for (int i = 0; i < packet.Header.AckList.Length; i++) { simulator.NeedAck.Remove(packet.Header.AckList[i]); } } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; lock (simulator.NeedAck) { for (int i = 0; i < ackPacket.Packets.Length; i++) { simulator.NeedAck.Remove(ackPacket.Packets[i].ID); } } } #endregion ACK handling } #region FireCallbacks if (Client.Settings.SYNC_PACKETCALLBACKS) { PacketEvents.RaiseEvent(PacketType.Default, packet, simulator); PacketEvents.RaiseEvent(packet.Type, packet, simulator); } else { PacketEvents.BeginRaiseEvent(PacketType.Default, packet, simulator); PacketEvents.BeginRaiseEvent(packet.Type, packet, simulator); } #endregion FireCallbacks } } } }
private void ack_pack(Packet Pack) { if (Pack.Header.Reliable) { libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); ack_it.Packets[0].ID = Pack.Header.Sequence; ack_it.Header.Reliable = false; OutPacket(ack_it); } /* if (Pack.Header.Reliable) { lock (PendingAcks) { uint sequence = (uint)Pack.Header.Sequence; if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } } }*/ }
// SpoofAck: create an ACK for the given packet public Packet SpoofAck(uint sequence) { PacketAckPacket spoof = new PacketAckPacket(); spoof.Packets = new PacketAckPacket.PacketsBlock[1]; spoof.Packets[0] = new PacketAckPacket.PacketsBlock(); spoof.Packets[0].ID = sequence; return (Packet)spoof; }
// CheckAcks: check for and remove ACKs of packets we've injected public Packet CheckAcks(Packet packet, Direction direction, ref int length, ref bool needsCopy) { Dictionary<uint, Packet> acks = direction == Direction.Incoming ? outgoingAcks : incomingAcks; List<uint> seenAcks = direction == Direction.Incoming ? outgoingSeenAcks : incomingSeenAcks; if (acks.Count == 0) return packet; // check for embedded ACKs if (packet.Type == PacketType.PacketAck) { bool changed = false; List<PacketAckPacket.PacketsBlock> newPacketBlocks = new List<PacketAckPacket.PacketsBlock>(); foreach (PacketAckPacket.PacketsBlock pb in ((PacketAckPacket)packet).Packets) { uint id = pb.ID; if (acks.ContainsKey(id)) { acks.Remove(id); seenAcks.Add(id); changed = true; } else { newPacketBlocks.Add(pb); } } if (changed) { PacketAckPacket newPacket = new PacketAckPacket(); newPacket.Packets = new PacketAckPacket.PacketsBlock[newPacketBlocks.Count]; int a = 0; foreach (PacketAckPacket.PacketsBlock pb in newPacketBlocks) { newPacket.Packets[a++] = pb; } SwapPacket(packet, (Packet)newPacket); packet = newPacket; needsCopy = false; } } // check for appended ACKs if (packet.Header.AppendedAcks) { int ackCount = packet.Header.AckList.Length; for (int i = 0; i < ackCount; ) { uint ackID = packet.Header.AckList[i]; // FIXME FIXME FIXME if (acks.ContainsKey(ackID)) { uint[] newAcks = new uint[ackCount - 1]; Array.Copy(packet.Header.AckList, 0, newAcks, 0, i); Array.Copy(packet.Header.AckList, i + 1, newAcks, i, ackCount - i - 1); packet.Header.AckList = newAcks; --ackCount; acks.Remove(ackID); seenAcks.Add(ackID); needsCopy = false; } else ++i; } if (ackCount == 0) { packet.Header.AppendedAcks = false; packet.Header.AckList = new uint[0]; } } return packet; }
private void SendAck(ushort id) { PacketAckPacket ack = new PacketAckPacket(); ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0].ID = id; ack.Header.Reliable = false; lock (PendingAcks) { if (PendingAcks.Contains(id)) { PendingAcks.Remove(id); } } SendPacket(ack, true); }
/// <summary> /// Send an ack immediately to the given endpoint. /// </summary> /// <remarks> /// FIXME: Might be possible to use SendPacketData() like everything else, but this will require refactoring so /// that we can obtain the UDPClient easily at this point. /// </remarks> /// <param name="remoteEndpoint"></param> /// <param name="sequenceNumber"></param> private void SendAckImmediate(IPEndPoint remoteEndpoint, uint sequenceNumber) { PacketAckPacket ack = new PacketAckPacket(); ack.Header.Reliable = false; ack.Packets = new PacketAckPacket.PacketsBlock[1]; ack.Packets[0] = new PacketAckPacket.PacketsBlock(); ack.Packets[0].ID = sequenceNumber; SendAckImmediate(remoteEndpoint, ack); }
private void SendAcks() { lock (PendingAcks) { if (PendingAcks.Count > 0) { int i = 0; PacketAckPacket acks = new PacketAckPacket(); acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; foreach (uint ack in PendingAcks) { acks.Packets[i] = new PacketAckPacket.PacketsBlock(); acks.Packets[i].ID = ack; i++; } acks.Header.Reliable = false; SendPacket(acks, true); PendingAcks.Clear(); } } }
/// <summary> /// Sends out pending acknowledgements /// </summary> private void SendAcks() { uint ack; if (PendingAcks.TryDequeue(out ack)) { Interlocked.Decrement(ref PendingAckCount); List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>(); PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); while (PendingAcks.TryDequeue(out ack)) { Interlocked.Decrement(ref PendingAckCount); block = new PacketAckPacket.PacketsBlock(); block.ID = ack; blocks.Add(block); } PacketAckPacket packet = new PacketAckPacket(); packet.Header.Reliable = false; packet.Packets = blocks.ToArray(); SendPacket(packet); } }
void IncomingPacketHandler() { IncomingPacket incomingPacket = new IncomingPacket(); Packet packet = null; UDPClient client = null; while (IsRunning) { // Reset packet to null for the check below packet = null; if (packetInbox.Dequeue(100, ref incomingPacket)) { packet = incomingPacket.Packet; client = incomingPacket.Client; if (packet != null) { #region ACK accounting // Check the archives to see whether we already received this packet lock (client.PacketArchive) { if (client.PacketArchive.Contains(packet.Header.Sequence)) { if (packet.Header.Resent) { Logger.DebugLog("Received resent packet #" + packet.Header.Sequence); } else { Logger.Log(String.Format("Received a duplicate of packet #{0}, current type: {1}", packet.Header.Sequence, packet.Type), Helpers.LogLevel.Warning); } // Avoid firing a callback twice for the same packet continue; } else { // Keep the PacketArchive size within a certain capacity while (client.PacketArchive.Count >= Settings.PACKET_ARCHIVE_SIZE) { client.PacketArchive.Dequeue(); client.PacketArchive.Dequeue(); client.PacketArchive.Dequeue(); client.PacketArchive.Dequeue(); } client.PacketArchive.Enqueue(packet.Header.Sequence); } } #endregion ACK accounting #region ACK handling // Handle appended ACKs if (packet.Header.AppendedAcks) { lock (client.NeedAcks) { for (int i = 0; i < packet.Header.AckList.Length; i++) { client.NeedAcks.Remove(packet.Header.AckList[i]); } } } // Handle PacketAck packets if (packet.Type == PacketType.PacketAck) { PacketAckPacket ackPacket = (PacketAckPacket)packet; lock (client.NeedAcks) { for (int i = 0; i < ackPacket.Packets.Length; i++) { client.NeedAcks.Remove(ackPacket.Packets[i].ID); } } } #endregion ACK handling packetEvents.BeginRaiseEvent(packet.Type, packet, client.Agent); } } } }