/// <summary> /// Turn a packet into an array of bytes. If necessary zerocde it. The returned array will be the correct length. /// </summary> /// <param name="packet">The packet to encode</param> protected byte[] GetBytes(OpenMetaverse.Packets.Packet packet) { byte[] bytes = packet.ToBytes(); int length = bytes.Length; if (packet.Header.Zerocoded) { byte[] zerod = new byte[8192]; length = Helpers.ZeroEncode(bytes, bytes.Length, zerod); bytes = zerod.Take(length).ToArray(); } return(bytes); }
public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) { // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount < 1) m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; m_scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); } ); } } else { byte[] data = packet.ToBytes(); m_scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); } ); } }
// Inject: inject a packet public void Inject(Packet packet, Direction direction) { if (direction == Direction.Incoming) { if (firstReceive) { proxy.queuedIncomingInjections.Add(packet); return; } incomingInjections.Add(++incomingSequence); packet.Header.Sequence = incomingSequence; } else { outgoingInjections.Add(++outgoingSequence); packet.Header.Sequence = outgoingSequence; } if (packet.Header.Reliable) WaitForAck(packet, direction); if (direction == Direction.Incoming) { byte[] buffer = packet.ToBytes(); if (!packet.Header.Zerocoded) socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint); else { int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer); socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint); } } else proxy.SendPacket(packet, remoteEndPoint, false); }
// SendPacket: send a packet from the sim to the client via our fake sim endpoint public void SendPacket(Packet packet, bool skipZero) { byte[] buffer = packet.ToBytes(); if (skipZero || !packet.Header.Zerocoded) socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint); else { int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer); socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint); } }
/// <summary> /// Sends a packet directly to the simulator without queuing /// </summary> /// <param name="packet">Packet to be sent</param> /// <param name="setSequence">True to set the sequence number, false to /// leave it as is</param> public void SendPacketUnqueued(Packet packet, 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 Sequence, 0, Settings.MAX_SEQUENCE); // Increment and fetch the current sequence number packet.Header.Sequence = (uint)Interlocked.Increment(ref Sequence); if (packet.Header.Reliable) { // Wrap this packet in a struct to track timeouts and resends NetworkManager.OutgoingPacket outgoing = new NetworkManager.OutgoingPacket(this, packet, true); // Keep track of when this packet was first sent out (right now) outgoing.TickCount = Environment.TickCount; // Add this packet to the list of ACK responses we are waiting on from the server lock (NeedAck) { NeedAck[packet.Header.Sequence] = outgoing; } if (packet.Header.Resent) { // 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 // server 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 (PendingAcks) { foreach (uint sequence in packet.Header.AckList) { if (!PendingAcks.ContainsKey(sequence)) PendingAcks[sequence] = sequence; } } packet.Header.AppendedAcks = false; packet.Header.AckList = new uint[0]; } // Update the sent time for this packet SetResentTime(packet.Header.Sequence); } else { // This packet is not a resend, check if the conditions are favorable // to ACK appending if (packet.Type != PacketType.PacketAck && packet.Type != PacketType.LogoutRequest) { lock (PendingAcks) { if (PendingAcks.Count > 0 && PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS) { // Append all of the queued up outgoing ACKs to this packet packet.Header.AckList = new uint[PendingAcks.Count]; for (int i = 0; i < PendingAcks.Count; i++) packet.Header.AckList[i] = PendingAcks.Values[i]; PendingAcks.Clear(); packet.Header.AppendedAcks = true; } } } } } 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(ipEndPoint); // 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); }
// Inject: inject a packet public void Inject(Packet packet, Direction direction) { if (direction == Direction.Incoming) { if (firstReceive) { proxy.queuedIncomingInjections.Add(packet); return; } incomingInjections.Add(++incomingSequence); packet.Header.Sequence = incomingSequence; } else { outgoingInjections.Add(++outgoingSequence); packet.Header.Sequence = outgoingSequence; } #if DEBUG_SEQUENCE Console.WriteLine("INJECT " + (direction == Direction.Incoming ? "<-" : "->") + " " + packet.Type + " #" + packet.Header.Sequence); #endif if ((packet.Header.Data[0] & Helpers.MSG_RELIABLE) != 0) WaitForAck(packet, direction); if (direction == Direction.Incoming) { byte[] buffer = packet.ToBytes(); if ((packet.Header.Data[0] & Helpers.MSG_ZEROCODED) == 0) socket.SendTo(buffer, buffer.Length, SocketFlags.None, clientEndPoint); else { int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer); socket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, clientEndPoint); } } else proxy.SendPacket(packet, remoteEndPoint, false); }
// SendPacket: send a packet to a sim from our fake client endpoint public void SendPacket(Packet packet, IPEndPoint endPoint, bool skipZero) { byte[] buffer = packet.ToBytes(); if (skipZero || (packet.Header.Data[0] & Helpers.MSG_ZEROCODED) == 0) simFacingSocket.SendTo(buffer, buffer.Length, SocketFlags.None, endPoint); else { int zeroLength = Helpers.ZeroEncode(buffer, buffer.Length, zeroBuffer); simFacingSocket.SendTo(zeroBuffer, zeroLength, SocketFlags.None, endPoint); } }
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { // CoarseLocationUpdate packets cannot be split in an automated way if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; //if (packetCount > 1) // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(udpClient, data, packet.Type, category); } } else { byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category); } }
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod) { // CoarseLocationUpdate packets cannot be split in an automated way if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount < 1) MainConsole.Instance.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod); data = null; } datas = null; } else { byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet, category, resendMethod, finishedMethod); data = null; } packet = null; }
public void SendPacket(LLAgent agent, Packet packet, ThrottleCategory category, bool allowSplitting) { // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) allowSplitting = false; try { if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount < 1) m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(agent, data, packet.Type, category); } } else { byte[] data = packet.ToBytes(); SendPacketData(agent, data, packet.Type, category); } } catch (NullReferenceException) { System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); m_log.Error("An invalid " + packet.Type + " packet was built in:" + Environment.NewLine + trace.ToString()); } }
public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) { // CoarseLocationUpdate packets cannot be split in an automated way if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; //if (packetCount > 1) // m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; m_scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); } ); } } else { byte[] data = packet.ToBytes(); m_scene.ForEachClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category); } ); } }
/// <summary> /// Load a packet to be received by the LLUDPServer on the next receive call /// </summary> /// <param name="packet"></param> public void LoadReceive(Packet packet, EndPoint epSender) { LoadReceive(packet.ToBytes(), epSender); }
public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting, UnackedPacketMethod resendMethod, UnackedPacketMethod finishedMethod) { // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount < 1) MainConsole.Instance.Error("[LLUDP Server]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; ForEachInternalClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView) client).UDPClient, data, packet, category, resendMethod, finishedMethod); } ); } } else { byte[] data = packet.ToBytes(); ForEachInternalClient( delegate(IClientAPI client) { if (client is LLClientView) SendPacketData(((LLClientView) client).UDPClient, data, packet, category, resendMethod, finishedMethod); } ); } }
public void SendPacket(LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting) { // CoarseLocationUpdate packets cannot be split in an automated way if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas; int[] sizes; if (packet.UsesBufferPooling) { datas = packet.ToBytesMultiple(_bufferPool, out sizes); } else { datas = packet.ToBytesMultiple(); sizes = new int[datas.Length]; for (int i = 0; i < datas.Length; i++) { sizes[i] = datas[i].Length; } } //add up all the sizes of the data going out for this packet. if it is more than MAX_PACKET_SIZE //drop it and log it long totalSz = 0; foreach (int size in sizes) { totalSz += size; } if (totalSz > MAX_PACKET_SIZE) { m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, totalSz); datas = null; return; } int packetCount = datas.Length; if (packetCount < 1) m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(udpClient, data, sizes[i], packet.Type, category, packet.UsesBufferPooling); } } else { byte[] data; int size = 0; if (packet.UsesBufferPooling) { data = packet.ToBytes(_bufferPool, ref size); } else { data = packet.ToBytes(); size = data.Length; } if (size > MAX_PACKET_SIZE) { m_log.ErrorFormat("[LLUDPSERVER] Not sending HUGE packet Type:{0}, Size: {1}", packet.Type, size); data = null; return; } SendPacketData(udpClient, data, size, packet.Type, category, packet.UsesBufferPooling); } }
/// <summary> /// Start the process of sending a packet to the client. /// </summary> /// <param name="udpClient"></param> /// <param name="packet"></param> /// <param name="category"></param> /// <param name="allowSplitting"></param> /// <param name="method"> /// The method to call if the packet is not acked by the client. If null, then a standard /// resend of the packet is done. /// </param> public virtual void SendPacket( LLUDPClient udpClient, Packet packet, ThrottleOutPacketType category, bool allowSplitting, UnackedPacketMethod method) { // CoarseLocationUpdate packets cannot be split in an automated way if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) allowSplitting = false; if (allowSplitting && packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount < 1) m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(udpClient, data, packet.Type, category, method); } } else { byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category, method); } PacketPool.Instance.ReturnPacket(packet); m_dataPresentEvent.Set(); }
/// <summary> /// Sends a packet /// </summary> /// <param name="packet">Packet to be sent</param> public void SendPacket(Packet packet) { // DEBUG: This can go away after we are sure nothing in the library is trying to do this if (packet.Header.AppendedAcks || (packet.Header.AckList != null && packet.Header.AckList.Length > 0)) Logger.Log("Attempting to send packet " + packet.Type + " with ACKs appended before serialization", Helpers.LogLevel.Error); if (packet.HasVariableBlocks) { byte[][] datas = packet.ToBytesMultiple(); int packetCount = datas.Length; if (packetCount > 1) Logger.DebugLog("Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded); } } else { byte[] data = packet.ToBytes(); SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded); } }
/// <summary> /// Sends a packet /// </summary> /// <param name="packet">Packet to be sent</param> public void SendPacket(Packet packet) { // DEBUG: This can go away after we are sure nothing in the library is trying to do this if (packet.Header.AppendedAcks || (packet.Header.AckList != null && packet.Header.AckList.Length > 0)) Logger.Log("Attempting to send packet " + packet.Type + " with ACKs appended before serialization", Helpers.LogLevel.Error); if (packet.HasVariableBlocks) { byte[][] datas; try { datas = packet.ToBytesMultiple(); } catch (NullReferenceException) { Logger.Log("Failed to serialize " + packet.Type + " packet to one or more payloads due to a missing block or field. StackTrace: " + Environment.StackTrace, Helpers.LogLevel.Error); return; } int packetCount = datas.Length; if (packetCount > 1) Logger.DebugLog("Split " + packet.Type + " packet into " + packetCount + " packets"); for (int i = 0; i < packetCount; i++) { byte[] data = datas[i]; SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded); } } else { byte[] data = packet.ToBytes(); SendPacketData(data, data.Length, packet.Type, packet.Header.Zerocoded); } }
public void SendPacket(Packet packet, bool setSequence) { byte[] buffer; int bytes; // Keep track of when this packet was sent out packet.TickCount = Environment.TickCount; if (setSequence) { // Reset to zero if we've hit the upper sequence number limit Interlocked.CompareExchange(ref currentSequence, 0, 0xFFFFFF); // Increment and fetch the current sequence number uint sequence = (uint)Interlocked.Increment(ref currentSequence); packet.Header.Sequence = sequence; if (packet.Header.Reliable) { // Add this packet to the list of ACK responses we are waiting on from the client lock (needAcks) needAcks[sequence] = packet; if (packet.Header.Resent) { // 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 (pendingAcks) { foreach (uint ack in packet.Header.AckList) { if (!pendingAcks.ContainsKey(ack)) pendingAcks[ack] = ack; } } packet.Header.AppendedAcks = false; packet.Header.AckList = new uint[0]; } } else { // This packet is not a resend, check if the conditions are favorable // to ACK appending if (packet.Type != PacketType.PacketAck) { lock (pendingAcks) { if (pendingAcks.Count > 0 && pendingAcks.Count < 10) { // Append all of the queued up outgoing ACKs to this packet packet.Header.AckList = new uint[pendingAcks.Count]; for (int i = 0; i < pendingAcks.Count; i++) packet.Header.AckList[i] = pendingAcks.Values[i]; pendingAcks.Clear(); packet.Header.AppendedAcks = true; } } } } } 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; // Zerocode if needed if (packet.Header.Zerocoded) { buf = new UDPPacketBuffer(address, true, false); bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data); buf.DataLength = bytes; } else { buf = new UDPPacketBuffer(address, false, false); buf.Data = buffer; buf.DataLength = bytes; } udpServer.AsyncBeginSend(buf); }