public EnqueueOutgoing ( OpenSim.Region.ClientStack.LindenUDP.OutgoingPacket packet ) : bool | ||
packet | OpenSim.Region.ClientStack.LindenUDP.OutgoingPacket | |
return | bool |
public void ResendUnacked(LLUDPClient udpClient) { if (!udpClient.IsConnected) return; // Disconnect an agent if no packets are received for some time //FIXME: Make 60 an .ini setting if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) { IClientAPI client; if (m_scene.TryGetClient(udpClient.AgentID, out client)) { if (client.IsActive) // to prevent duplicate reporting m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); RemoveClient(client); } return; } // Get a list of all of the packets that have been sitting unacked longer than udpClient.RTO KeyValuePair<UnackedPacketCollection.ResendReason, List<OutgoingPacket>> expiredPackets = udpClient.NeedAcks.GetExpiredPackets(udpClient.RTO); if (expiredPackets.Key != UnackedPacketCollection.ResendReason.None) { //m_log.Debug("[LLUDPSERVER]: Resending " + expiredPackets.Count + " packets to " + udpClient.AgentID + ", RTO=" + udpClient.RTO); // Exponential backoff of the retransmission timeout if ((expiredPackets.Key & UnackedPacketCollection.ResendReason.TimeoutExpired) != 0) udpClient.BackoffRTO(); var packetList = expiredPackets.Value; // Resend packets for (int i = 0; i < packetList.Count; i++) { OutgoingPacket outgoingPacket = packetList[i]; /*m_log.DebugFormat("[LLUDPSERVER]: {0} Resending packet #{1} (attempt {2}), {3}ms have passed", (expiredPackets.Key & UnackedPacketCollection.ResendReason.FastRetransmit) != 0 ? "(Fast)" : "", outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount); */ // Set the resent flag outgoingPacket.Buffer[0] = (byte)(outgoingPacket.Buffer[0] | Helpers.MSG_RESENT); outgoingPacket.Category = (int) ThrottleOutPacketType.Resend; // Bump up the resend count on this packet Interlocked.Increment(ref outgoingPacket.ResendCount); //Interlocked.Increment(ref Stats.ResentPackets); // Requeue or resend the packet if (!udpClient.EnqueueOutgoing(outgoingPacket)) SendPacketFinal(outgoingPacket); } /* if (packetList.Count != 0) { m_log.DebugFormat("[LLUDPSERVER]: {0} Resent {1} packet(s) for {2}", (expiredPackets.Key & UnackedPacketCollection.ResendReason.FastRetransmit) != 0 ? "(Fast)" : "", packetList.Count, udpClient.AgentID); }*/ } }
public void SendPacketData(LLUDPClient udpClient, byte[] data, int dataLength, PacketType type, ThrottleOutPacketType category, bool bufferAcquiredFromPool) { bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; bool zeroCoded = false; byte[] outBuffer = null; // Zerocode if needed if (doZerocode) { // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here // to accomodate for both common scenarios and provide ample room for ACK appending in both int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200; try { //zerocode and return the current buffer to the pool if necessary outBuffer = _bufferPool.LeaseBytes(bufferSize); dataLength = Helpers.ZeroEncode(data, dataLength, outBuffer); zeroCoded = true; if (bufferAcquiredFromPool) { _bufferPool.ReturnBytes(data); } //now the buffer is from a pool most definitely bufferAcquiredFromPool = true; } catch (IndexOutOfRangeException) { //TODO: Throwing an exception here needs to be revisted. I've seen an issue with //70+ avatars where a very common high freq packet hits this code everytime //that packet either needs to be split, or this needs to be revised to not throw //and instead check the buffer size and return an error condition // The packet grew larger than the bufferSize while zerocoding. // Remove the MSG_ZEROCODED flag and send the unencoded data // instead m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength + " and BufferLength=" + outBuffer.Length + ". Removing MSG_ZEROCODED flag"); data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); _bufferPool.ReturnBytes(outBuffer); } } if (! zeroCoded) { outBuffer = data; } #region Queue or Send OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, outBuffer, (int)category, dataLength, udpClient.RemoteEndPoint, bufferAcquiredFromPool, type); if (!udpClient.EnqueueOutgoing(outgoingPacket)) SendPacketFinal(outgoingPacket); #endregion Queue or Send }