public void Send(byte[] data, int start, int length, SendOptions options) { //Prepare PacketProperty property = SendOptionsToProperty(options); int headerSize = NetPacket.GetHeaderSize(property); //Check fragmentation if (length + headerSize > _mtu) { if (options == SendOptions.Sequenced || options == SendOptions.Unreliable) { throw new Exception("Unreliable packet size > allowed (" + (_mtu - headerSize) + ")"); } int packetFullSize = _mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int fullPacketsCount = length / packetDataSize; int lastPacketSize = length % packetDataSize; int totalPackets = fullPacketsCount + (lastPacketSize == 0 ? 0 : 1); DebugWrite("MTU: {0}, HDR: {1}, PFS: {2}, PDS: {3}, FPC: {4}, LPS: {5}, TP: {6}", _mtu, headerSize, packetFullSize, packetDataSize, fullPacketsCount, lastPacketSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new Exception("Too many fragments: " + totalPackets + " > " + ushort.MaxValue); } for (ushort i = 0; i < fullPacketsCount; i++) { NetPacket p = GetPacketFromPool(property, packetFullSize); p.FragmentId = _fragmentId; p.FragmentPart = i; p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; p.PutData(data, i * packetDataSize, packetDataSize); SendPacket(p); } if (lastPacketSize > 0) { NetPacket p = GetPacketFromPool(property, lastPacketSize + NetConstants.FragmentHeaderSize); p.FragmentId = _fragmentId; p.FragmentPart = (ushort)fullPacketsCount; //last p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; p.PutData(data, fullPacketsCount * packetDataSize, lastPacketSize); SendPacket(p); } _fragmentId++; return; } //Else just send NetPacket packet = GetPacketFromPool(property, length); packet.PutData(data, start, length); SendPacket(packet); }
private void SendInternal( byte[] data, int start, int length, byte channelNumber, DeliveryMethod deliveryMethod, object userData) { if (_connectionState != ConnectionState.Connected || channelNumber >= _channels.Length) { return; } //Select channel PacketProperty property; BaseChannel channel = null; if (deliveryMethod == DeliveryMethod.Unreliable) { property = PacketProperty.Unreliable; } else { property = PacketProperty.Channeled; channel = CreateChannel((byte)(channelNumber * 4 + (byte)deliveryMethod)); } //Prepare NetDebug.Write("[RS]Packet: " + property); //Check fragmentation int headerSize = NetPacket.GetHeaderSize(property); //Save mtu for multithread int mtu = _mtu; if (length + headerSize > mtu) { //if cannot be fragmented if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) { throw new TooBigPacketException("Unreliable or ReliableSequenced packet size exceeded maximum of " + (mtu - headerSize) + " bytes, Check allowed size by GetMaxSinglePacketSize()"); } int packetFullSize = mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int totalPackets = length / packetDataSize + (length % packetDataSize == 0 ? 0 : 1); NetDebug.Write("FragmentSend:\n" + " MTU: {0}\n" + " headerSize: {1}\n" + " packetFullSize: {2}\n" + " packetDataSize: {3}\n" + " totalPackets: {4}", mtu, headerSize, packetFullSize, packetDataSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); } ushort currentFragmentId = (ushort)Interlocked.Increment(ref _fragmentId); for (ushort partIdx = 0; partIdx < totalPackets; partIdx++) { int sendLength = length > packetDataSize ? packetDataSize : length; NetPacket p = _packetPool.GetPacket(headerSize + sendLength + NetConstants.FragmentHeaderSize); p.Property = property; p.UserData = userData; p.FragmentId = currentFragmentId; p.FragmentPart = partIdx; p.FragmentsTotal = (ushort)totalPackets; p.MarkFragmented(); Buffer.BlockCopy(data, partIdx * packetDataSize, p.RawData, NetConstants.FragmentedHeaderTotalSize, sendLength); channel.AddToQueue(p); length -= sendLength; } return; } //Else just send NetPacket packet = _packetPool.GetPacket(headerSize + length); packet.Property = property; Buffer.BlockCopy(data, start, packet.RawData, headerSize, length); packet.UserData = userData; if (channel == null) //unreliable { lock (_unreliableChannel) _unreliableChannel.Enqueue(packet); } else { channel.AddToQueue(packet); } }
public int GetMaxSinglePacketSize(SendOptions options) { return(_mtu - NetPacket.GetHeaderSize(SendOptionsToProperty(options))); }
internal void AddIncomingPacket(NetPacket p) { if (p.IsFragmented) { NetDebug.Write("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal); //Get needed array from dictionary ushort packetFragId = p.FragmentId; IncomingFragments incomingFragments; if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments)) { incomingFragments = new IncomingFragments { Fragments = new NetPacket[p.FragmentsTotal] }; _holdedFragments.Add(packetFragId, incomingFragments); } //Cache var fragments = incomingFragments.Fragments; //Error check if (p.FragmentPart >= fragments.Length || fragments[p.FragmentPart] != null) { _packetPool.Recycle(p); NetDebug.WriteError("Invalid fragment packet"); return; } //Fill array fragments[p.FragmentPart] = p; //Increase received fragments count incomingFragments.ReceivedCount++; //Increase total size int dataOffset = p.GetHeaderSize() + NetConstants.FragmentHeaderSize; incomingFragments.TotalSize += p.Size - dataOffset; //Check for finish if (incomingFragments.ReceivedCount != fragments.Length) { return; } NetDebug.Write("Received all fragments!"); NetPacket resultingPacket = _packetPool.GetWithProperty(p.Property, incomingFragments.TotalSize); int resultingPacketOffset = resultingPacket.GetHeaderSize(); int firstFragmentSize = fragments[0].Size - dataOffset; for (int i = 0; i < incomingFragments.ReceivedCount; i++) { //Create resulting big packet int fragmentSize = fragments[i].Size - dataOffset; Buffer.BlockCopy( fragments[i].RawData, dataOffset, resultingPacket.RawData, resultingPacketOffset + firstFragmentSize * i, fragmentSize); //Free memory _packetPool.Recycle(fragments[i]); fragments[i] = null; } //Send to process _netManager.ReceiveFromPeer(resultingPacket, _remoteEndPoint); //Clear memory _holdedFragments.Remove(packetFragId); } else //Just simple packet { _netManager.ReceiveFromPeer(p, _remoteEndPoint); } }
/// <summary> /// Gets maximum size of packet that will be not fragmented. /// </summary> /// <param name="options">Type of packet that you want send</param> /// <returns>size in bytes</returns> public int GetMaxSinglePacketSize(DeliveryMethod options) { return(_mtu - NetPacket.GetHeaderSize(options == DeliveryMethod.Unreliable ? PacketProperty.Unreliable : PacketProperty.Channeled)); }
/// <summary> /// Send data to peer /// </summary> /// <param name="data">Data</param> /// <param name="start">Start of data</param> /// <param name="length">Length of data</param> /// <param name="channelNumber">Number of channel (from 0 to channelsCount - 1)</param> /// <param name="options">Send options (reliable, unreliable, etc.)</param> /// <exception cref="TooBigPacketException"> /// If size exceeds maximum limit:<para/> /// MTU - headerSize bytes for Unreliable<para/> /// Fragment count exceeded ushort.MaxValue<para/> /// </exception> public void Send(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options) { if (_connectionState == ConnectionState.ShutdownRequested || _connectionState == ConnectionState.Disconnected) { return; } if (channelNumber >= _channelsTotalCount) { return; } //Select channel PacketProperty property; BaseChannel channel; if (options == DeliveryMethod.Unreliable) { property = PacketProperty.Unreliable; channel = _unreliableChannel; } else { property = PacketProperty.Channeled; channel = CreateChannel(NetConstants.ChannelNumberToId(options, channelNumber, _channelsCount)); } //Prepare NetDebug.Write("[RS]Packet: " + property); //Check fragmentation int headerSize = NetPacket.GetHeaderSize(property); //Save mtu for multithread int mtu = _mtu; if (length + headerSize > mtu) { //if cannot be fragmented if (options != DeliveryMethod.ReliableOrdered && options != DeliveryMethod.ReliableUnordered) { throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (_mtu - headerSize) + " bytes"); } int packetFullSize = mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int fullPacketsCount = length / packetDataSize; int lastPacketSize = length % packetDataSize; int totalPackets = fullPacketsCount + (lastPacketSize == 0 ? 0 : 1); NetDebug.Write("FragmentSend:\n" + " MTU: {0}\n" + " headerSize: {1}\n" + " packetFullSize: {2}\n" + " packetDataSize: {3}\n" + " fullPacketsCount: {4}\n" + " lastPacketSize: {5}\n" + " totalPackets: {6}", mtu, headerSize, packetFullSize, packetDataSize, fullPacketsCount, lastPacketSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); } int dataOffset = headerSize + NetConstants.FragmentHeaderSize; lock (_sendLock) { for (ushort i = 0; i < fullPacketsCount; i++) { NetPacket p = _packetPool.GetWithProperty(property, packetFullSize); p.FragmentId = _fragmentId; p.FragmentPart = i; p.FragmentsTotal = (ushort)totalPackets; p.MarkFragmented(); Buffer.BlockCopy(data, i * packetDataSize, p.RawData, dataOffset, packetDataSize); channel.AddToQueue(p); } if (lastPacketSize > 0) { NetPacket p = _packetPool.GetWithProperty(property, lastPacketSize + NetConstants.FragmentHeaderSize); p.FragmentId = _fragmentId; p.FragmentPart = (ushort)fullPacketsCount; //last p.FragmentsTotal = (ushort)totalPackets; p.MarkFragmented(); Buffer.BlockCopy(data, fullPacketsCount * packetDataSize, p.RawData, dataOffset, lastPacketSize); channel.AddToQueue(p); } _fragmentId++; } return; } //Else just send NetPacket packet = _packetPool.GetWithData(property, data, start, length); channel.AddToQueue(packet); }
/// <summary> /// Send data to peer /// </summary> /// <param name="data">Data</param> /// <param name="start">Start of data</param> /// <param name="length">Length of data</param> /// <param name="options">Send options (reliable, unreliable, etc.)</param> public void Send(byte[] data, int start, int length, SendOptions options) { //Prepare PacketProperty property = SendOptionsToProperty(options); int headerSize = NetPacket.GetHeaderSize(property); //Check fragmentation if (length + headerSize > _mtu) { if (options == SendOptions.Sequenced || options == SendOptions.Unreliable) { throw new Exception("Unreliable packet size > allowed (" + (_mtu - headerSize) + ")"); } int packetFullSize = _mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int fullPacketsCount = length / packetDataSize; int lastPacketSize = length % packetDataSize; int totalPackets = fullPacketsCount + (lastPacketSize == 0 ? 0 : 1); NetUtils.DebugWrite("FragmentSend:\n" + " MTU: {0}\n" + " headerSize: {1}\n" + " packetFullSize: {2}\n" + " packetDataSize: {3}\n" + " fullPacketsCount: {4}\n" + " lastPacketSize: {5}\n" + " totalPackets: {6}", _mtu, headerSize, packetFullSize, packetDataSize, fullPacketsCount, lastPacketSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new Exception("Too many fragments: " + totalPackets + " > " + ushort.MaxValue); } int dataOffset = headerSize + NetConstants.FragmentHeaderSize; for (ushort i = 0; i < fullPacketsCount; i++) { NetPacket p = _packetPool.Get(property, packetFullSize); p.FragmentId = _fragmentId; p.FragmentPart = i; p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; Buffer.BlockCopy(data, i * packetDataSize, p.RawData, dataOffset, packetDataSize); SendPacket(p); } if (lastPacketSize > 0) { NetPacket p = _packetPool.Get(property, lastPacketSize + NetConstants.FragmentHeaderSize); p.FragmentId = _fragmentId; p.FragmentPart = (ushort)fullPacketsCount; //last p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; Buffer.BlockCopy(data, fullPacketsCount * packetDataSize, p.RawData, dataOffset, lastPacketSize); SendPacket(p); } _fragmentId++; return; } //Else just send NetPacket packet = _packetPool.GetWithData(property, data, start, length); SendPacket(packet); }
private void SendInternal( byte[] data, int start, int length, byte channelNumber, DeliveryMethod deliveryMethod, object userData) { if (_connectionState == ConnectionState.ShutdownRequested || _connectionState == ConnectionState.Disconnected) { return; } if (channelNumber >= _channels.Length) { return; } //Select channel PacketProperty property; BaseChannel channel; if (deliveryMethod == DeliveryMethod.Unreliable) { property = PacketProperty.Unreliable; channel = _unreliableChannel; } else { property = PacketProperty.Channeled; channel = CreateChannel((byte)(channelNumber * 4 + (byte)deliveryMethod)); } //Prepare NetDebug.Write("[RS]Packet: " + property); //Check fragmentation int headerSize = NetPacket.GetHeaderSize(property); //Save mtu for multithread int mtu = _mtu; if (length + headerSize > mtu) { //if cannot be fragmented if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered) { throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (_mtu - headerSize) + " bytes"); } int packetFullSize = mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int totalPackets = length / packetDataSize + (length % packetDataSize == 0 ? 0 : 1); NetDebug.Write("FragmentSend:\n" + " MTU: {0}\n" + " headerSize: {1}\n" + " packetFullSize: {2}\n" + " packetDataSize: {3}\n" + " totalPackets: {4}", mtu, headerSize, packetFullSize, packetDataSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); } lock (_sendLock) { for (ushort partIdx = 0; partIdx < totalPackets; partIdx++) { int sendLength = length > packetDataSize ? packetDataSize : length; NetPacket p = _packetPool.GetWithProperty(property, sendLength + NetConstants.FragmentHeaderSize); p.UserData = userData; p.FragmentId = _fragmentId; p.FragmentPart = partIdx; p.FragmentsTotal = (ushort)totalPackets; p.MarkFragmented(); Buffer.BlockCopy(data, partIdx * packetDataSize, p.RawData, NetConstants.FragmentTotalSize, sendLength); channel.AddToQueue(p); length -= sendLength; } _fragmentId++; } return; } //Else just send NetPacket packet = _packetPool.GetWithData(property, data, start, length); packet.UserData = userData; channel.AddToQueue(packet); }
/// <summary> /// Send data to peer /// </summary> /// <param name="data">Data</param> /// <param name="start">Start of data</param> /// <param name="length">Length of data</param> /// <param name="options">Send options (reliable, unreliable, etc.)</param> /// <exception cref="TooBigPacketException"> /// If size exceeds maximum limit:<para/> /// MTU - headerSize bytes for Unreliable<para/> /// Fragment count exceeded ushort.MaxValue<para/> /// </exception> public void Send(byte[] data, int start, int length, DeliveryMethod options) { if (_connectionState == ConnectionState.ShutdownRequested || _connectionState == ConnectionState.Disconnected) { return; } //Prepare PacketProperty property = SendOptionsToProperty(options); int headerSize = NetPacket.GetHeaderSize(property); int mtu = _mtu; //Check fragmentation if (length + headerSize > mtu) { if (options == DeliveryMethod.Sequenced || options == DeliveryMethod.Unreliable) { throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (_mtu - headerSize) + " bytes"); } int packetFullSize = mtu - headerSize; int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize; int fullPacketsCount = length / packetDataSize; int lastPacketSize = length % packetDataSize; int totalPackets = fullPacketsCount + (lastPacketSize == 0 ? 0 : 1); NetUtils.DebugWrite("FragmentSend:\n" + " MTU: {0}\n" + " headerSize: {1}\n" + " packetFullSize: {2}\n" + " packetDataSize: {3}\n" + " fullPacketsCount: {4}\n" + " lastPacketSize: {5}\n" + " totalPackets: {6}", mtu, headerSize, packetFullSize, packetDataSize, fullPacketsCount, lastPacketSize, totalPackets); if (totalPackets > ushort.MaxValue) { throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue); } int dataOffset = headerSize + NetConstants.FragmentHeaderSize; lock (_sendLock) { for (ushort i = 0; i < fullPacketsCount; i++) { NetPacket p = _packetPool.Get(property, packetFullSize); p.FragmentId = _fragmentId; p.FragmentPart = i; p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; Buffer.BlockCopy(data, i * packetDataSize, p.RawData, dataOffset, packetDataSize); SendPacket(p); } if (lastPacketSize > 0) { NetPacket p = _packetPool.Get(property, lastPacketSize + NetConstants.FragmentHeaderSize); p.FragmentId = _fragmentId; p.FragmentPart = (ushort)fullPacketsCount; //last p.FragmentsTotal = (ushort)totalPackets; p.IsFragmented = true; Buffer.BlockCopy(data, fullPacketsCount * packetDataSize, p.RawData, dataOffset, lastPacketSize); SendPacket(p); } _fragmentId++; } return; } //Else just send NetPacket packet = _packetPool.GetWithData(property, data, start, length); SendPacket(packet); }
internal void AddIncomingPacket(NetPacket p) { if (p.IsFragmented) { DebugWrite("Fragment. Id: {0}, Part: {1}, Total: {2}", p.FragmentId, p.FragmentPart, p.FragmentsTotal); //Get needed array from dictionary ushort packetFragId = p.FragmentId; IncomingFragments incomingFragments; if (!_holdedFragments.TryGetValue(packetFragId, out incomingFragments)) { incomingFragments = new IncomingFragments { Fragments = new NetPacket[p.FragmentsTotal] }; _holdedFragments.Add(packetFragId, incomingFragments); } //Cache var fragments = incomingFragments.Fragments; //Fill array fragments[p.FragmentPart] = p; //Increase received fragments count incomingFragments.ReceivedCount++; //Increase total size int dataOffset = p.GetHeaderSize() + NetConstants.FragmentHeaderSize; incomingFragments.TotalSize += p.RawData.Length - dataOffset; //Check for finish if (incomingFragments.ReceivedCount != fragments.Length) return; DebugWrite("Received all fragments!"); NetPacket resultingPacket = GetPacketFromPool(p.Property, incomingFragments.TotalSize); int resultingPacketOffset = resultingPacket.GetHeaderSize(); int firstFragmentSize = fragments[0].RawData.Length - dataOffset; for (int i = 0; i < incomingFragments.ReceivedCount; i++) { //Create resulting big packet int fragmentSize = fragments[i].RawData.Length - dataOffset; Buffer.BlockCopy( fragments[i].RawData, dataOffset, resultingPacket.RawData, resultingPacketOffset + firstFragmentSize * i, fragmentSize); //Free memory Recycle(fragments[i]); fragments[i] = null; } //Send to process _peerListener.ReceiveFromPeer(resultingPacket, _remoteEndPoint); //Clear memory Recycle(resultingPacket); _holdedFragments.Remove(packetFragId); } else //Just simple packet { _peerListener.ReceiveFromPeer(p, _remoteEndPoint); Recycle(p); } }