void StartPingCheckHandler(Packet packet, Agent agent) { StartPingCheckPacket start = (StartPingCheckPacket)packet; CompletePingCheckPacket complete = new CompletePingCheckPacket(); complete.Header.Reliable = false; complete.PingID.PingID = start.PingID.PingID; agent.SendPacket(complete); }
public void CompletePing(LLUDPClient udpClient, byte pingID) { CompletePingCheckPacket completePing = new CompletePingCheckPacket(); completePing.PingID.PingID = pingID; SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false, null); }
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); }
private void StartPingCheckHandler(Packet packet, Simulator simulator) { StartPingCheckPacket incomingPing = (StartPingCheckPacket)packet; CompletePingCheckPacket ping = new CompletePingCheckPacket(); ping.PingID.PingID = incomingPing.PingID.PingID; // TODO: We can use OldestUnacked to correct transmission errors SendPacket((Packet)ping, simulator); }
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); } }
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) { m_log.ErrorFormat("[LLUDPSERVER]: 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("[LLUDPSERVER]: 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("[LLUDPSERVER]: Handling UseCircuitCode packet from " + buffer.RemoteEndPoint); 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.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type); else m_log.Warn("[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type); // Avoid firing a callback twice for the same packet return; } #endregion Incoming Packet Accounting #region Ping Check Handling if (packet.Type == PacketType.StartPingCheck) { // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePingCheckPacket completePing = new CompletePingCheckPacket(); completePing.PingID.PingID = startPing.PingID.PingID; SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false); 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)); }
public void CompletePing(LLAgent agent, byte pingID) { CompletePingCheckPacket completePing = new CompletePingCheckPacket(); completePing.Header.Reliable = false; completePing.PingID.PingID = pingID; SendPacket(agent, completePing, ThrottleCategory.Unknown, false); }
/// <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); } }