/// <summary> /// /// </summary> public void SendPing() { uint oldestUnacked = 0; // Get the oldest NeedAck value, the first entry in the sorted dictionary lock (NeedAck) { if (NeedAck.Count > 0) { SortedDictionary <uint, NetworkManager.OutgoingPacket> .KeyCollection.Enumerator en = NeedAck.Keys.GetEnumerator(); en.MoveNext(); oldestUnacked = en.Current; } } //if (oldestUnacked != 0) // Logger.DebugLog("Sending ping with oldestUnacked=" + oldestUnacked); StartPingCheckPacket ping = new StartPingCheckPacket(); ping.PingID.PingID = Stats.LastPingID++; ping.PingID.OldestUnacked = oldestUnacked; ping.Header.Reliable = false; SendPacket(ping); Stats.LastPingSent = Environment.TickCount; }
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> /// /// </summary> public void SendPing() { StartPingCheckPacket ping = new StartPingCheckPacket(); ping.PingID.PingID = Stats.LastPingID++; ping.PingID.OldestUnacked = 0; // FIXME ping.Header.Reliable = false; SendPacket(ping, true); Stats.LastPingSent = Environment.TickCount; }
void StartPingCheckHandler(Packet packet, Agent agent) { StartPingCheckPacket start = (StartPingCheckPacket)packet; CompletePingCheckPacket complete = new CompletePingCheckPacket(); complete.Header.Reliable = false; complete.PingID.PingID = start.PingID.PingID; server.UDP.SendPacket(agent.AgentID, complete, PacketCategory.Overhead); }
public void SendPing(LLUDPClient udpClient) { StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); pc.Header.Reliable = false; pc.PingID.PingID = (byte)udpClient.CurrentPingSequence++; // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit pc.PingID.OldestUnacked = 0; SendPacket(udpClient, pc, ThrottleOutPacketType.Unknown, false); }
public void SendPing(LLAgent agent) { StartPingCheckPacket pc = new StartPingCheckPacket(); pc.Header.Reliable = false; pc.PingID.PingID = (byte)agent.CurrentPingSequence++; // We *could* get OldestUnacked, but it would hurt performance and not provide any benefit pc.PingID.OldestUnacked = 0; SendPacket(agent, pc, ThrottleCategory.Unknown, false); }
private void StartPingCheckHandler(Packet packet, Simulator simulator) { StartPingCheckPacket incomingPing = (StartPingCheckPacket)packet; CompletePingCheckPacket ping = new CompletePingCheckPacket(); ping.PingID.PingID = incomingPing.PingID.PingID; ping.Header.Reliable = false; // TODO: We can use OldestUnacked to correct transmission errors // I don't think that's right. As far as I can tell, the Viewer // only uses this to prune its duplicate-checking buffer. -bushing SendPacket(ping, simulator); }
/// <summary> /// /// </summary> public void SendPing() { uint oldestUnacked = 0; // Get the oldest NeedAck value, the first entry in the sorted dictionary lock (NeedAck) { if (NeedAck.Count > 0) { SortedDictionary<uint, NetworkManager.OutgoingPacket>.KeyCollection.Enumerator en = NeedAck.Keys.GetEnumerator(); en.MoveNext(); oldestUnacked = en.Current; } } //if (oldestUnacked != 0) // Logger.DebugLog("Sending ping with oldestUnacked=" + oldestUnacked); StartPingCheckPacket ping = new StartPingCheckPacket(); ping.PingID.PingID = Stats.LastPingID++; ping.PingID.OldestUnacked = oldestUnacked; ping.Header.Reliable = false; SendPacket(ping); Stats.LastPingSent = Environment.TickCount; }
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)); }
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)); }