public void Dispose() { if (Pointer == IntPtr.Zero) { return; } try { StopServiceThread(); } catch { } if (Compressor != null) { Compressor.Dispose(); Compressor = null; } if (Checksum != null) { Checksum.Dispose(); Checksum = null; } if (Interceptor != null) { Interceptor.Dispose(); Interceptor = null; } m_Peers.ForEach(p => p.FreeHandle()); LibENet.HostDestroy(Pointer); Pointer = IntPtr.Zero; }
public static void Startup(ENetAllocator allocator = null) { if (Started) { return; } Started = true; Allocator = (allocator == null) ? new ENetManagedAllocator() : allocator; LibENet.Load(); Native.ENetCallbacks callbacks = new Native.ENetCallbacks(); callbacks.Malloc = Marshal.GetFunctionPointerForDelegate(MemAllocDelegate); callbacks.Free = Marshal.GetFunctionPointerForDelegate(MemFreeDelegate); callbacks.NoMemory = Marshal.GetFunctionPointerForDelegate(NoMemoryDelegate); var linkedVer = LibENet.LinkedVersion(); if (LibENet.InitializeWithCallbacks(linkedVer, &callbacks) != 0) { throw new Exception("ENet library initialization failed."); } LinkedVersion = new Version((int)(((linkedVer) >> 16) & 0xFF), (int)(((linkedVer) >> 8) & 0xFF), (int)((linkedVer) & 0xFF)); }
/// <summary> /// Instantiates <see cref="ENetHost"/> by creating native ENet host /// </summary> /// <param name="address">The address at which other peers may connect to this host. If null, then no peers may connect to the host.</param> /// <param name="peers">Maximum number of peers</param> /// <param name="channels">Maximum number of channels (0 = <see cref="MaximumPeers"/>)</param> /// <param name="incomingBandwidth">Maximum incoming bandwidth (0 = unlimited)</param> /// <param name="outgoingBandwidth">Maximum outgoing bandwidth (0 = unlimited)</param> public ENetHost(IPEndPoint?address, int peers, byte channels, long incomingBandwidth = 0, long outgoingBandwidth = 0) { if (incomingBandwidth < uint.MinValue || incomingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(incomingBandwidth)); } if (outgoingBandwidth < uint.MinValue || outgoingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException(nameof(outgoingBandwidth)); } if (peers < 0 || peers > MaximumPeers) { throw new ArgumentOutOfRangeException(nameof(peers)); } var nativeAddress = NativeENetAddress.FromIPEndPoint(address ?? new IPEndPoint(IPAddress.Any, 0)); m_Pointer = LibENet.HostCreate(&nativeAddress, (UIntPtr)peers, (UIntPtr)channels, (uint)incomingBandwidth, (uint)outgoingBandwidth); if (m_Pointer == IntPtr.Zero) { ThrowHelper.ThrowENetCreateHostFailed(); }
public ENetPacket(Span <byte> data, ENetPacketFlags flags) { fixed(byte *p = data) { m_Native = LibENet.PacketCreate(new IntPtr(p), unchecked ((UIntPtr)data.Length), flags); } }
public void DoNotCompress() { CheckDispose(); LibENet.HostCompress(Pointer, (Native.ENetCompressor *)IntPtr.Zero); Compressor = null; }
public ENetPacket(int dataLength, ENetPacketFlags flags) { if (dataLength < 0) { throw new ArgumentOutOfRangeException(nameof(dataLength)); } m_Native = LibENet.PacketCreate(IntPtr.Zero, unchecked ((UIntPtr)dataLength), flags); }
/// <summary> /// Initializes ENet with given startup options. /// </summary> /// <param name="startupOptions">The startup options.</param> public static void Startup(ENetStartupOptions startupOptions) { ThrowHelper.ThrowIfArgumentNull(startupOptions, nameof(startupOptions)); startupOptions.CheckValues(); var allocator = startupOptions.Allocator; if (Started) { return; } Started = true; if (startupOptions.ModulePath != null) { LibENet.Load(startupOptions.ModulePath); } else if (startupOptions.ModuleHandle != IntPtr.Zero) { LibENet.Load(startupOptions.ModuleHandle); } else { // load from native dependencies. LibENet.Load(); } var linkedVer = LibENet.LinkedVersion(); s_LinkedVersion = new Version((int)(((linkedVer) >> 16) & 0xFF), (int)(((linkedVer) >> 8) & 0xFF), (int)((linkedVer) & 0xFF)); if (allocator == null) { if (LibENet.Initialize() != 0) { ThrowHelper.ThrowENetInitializationFailed(); } } else { s_Allocator = allocator; NativeENetCallbacks callbacks = new NativeENetCallbacks { Malloc = Marshal.GetFunctionPointerForDelegate(s_MemAllocDelegate), Free = Marshal.GetFunctionPointerForDelegate(s_MemFreeDelegate), NoMemory = Marshal.GetFunctionPointerForDelegate(s_NoMemoryDelegate) }; if (LibENet.InitializeWithCallbacks(linkedVer, &callbacks) != 0) { ThrowHelper.ThrowENetInitializationFailed(); } } }
public ENetEvent CheckEvents() { CheckDispose(); var native = new Native.ENetEvent(); LibENet.HostCheckEvents(Pointer, &native); return(NativeToManagedEvent(ref native)); }
public void CompressWithRangeCoder() { CheckDispose(); if (LibENet.HostCompressWithRangeCoder(Pointer) != 0) { throw new Exception("Failed to set compressor to RangeCoder."); } Compressor = null; }
// id must be in sync with interop_helpers.c static int getOffset(uint id) { var offset = LibENet.InteropHelperSizeOrOffset(id); if (offset == new IntPtr(-1)) { throw new ENetException("Size-or-Offset identifier mismatch."); } return(offset.ToInt32()); }
public void Broadcast(byte[] buffer, byte channel, ENetPacketFlags flags) { CheckDispose(); Native.ENetPacket *packet; fixed(byte *p = buffer) { packet = LibENet.PacketCreate((IntPtr)p, (UIntPtr)buffer.Length, flags & ~ENetPacketFlags.NoAllocate); } LibENet.HostBroadcast(Pointer, channel, packet); }
public void ChecksumWithCRC32() { CheckDispose(); if (Checksum != null) { Checksum.Dispose(); Checksum = null; } *m_pChecksumCallback = LibENet.GetProc("enet_crc32"); }
/// <summary> /// Queues a packet to be sent. /// </summary> /// <param name="channelId">Destination channel Id</param> /// <param name="packet">Packet to be queued</param> /// <remarks> /// This method will destroy the packet if its <see cref="ENetPacket.ReferenceCount"/> is zero /// </remarks> public void Send(byte channelId, ENetPacket packet) { ThrowIfNull(); if (packet.IsNull) { throw new ArgumentNullException(nameof(packet)); } if (LibENet.PeerSend(m_Native, channelId, packet.GetNativePointer()) < 0) { ThrowHelper.ThrowENetPeerSendFailed(); } }
/// <summary> /// Resizes packet data length /// </summary> /// <param name="dataLength">New data length</param> /// <remarks> /// <see cref="Data"/> becomes invalid after calling this method. /// </remarks> public void Resize(int dataLength) { if (dataLength < 0) { throw new ArgumentOutOfRangeException(nameof(dataLength)); } ThrowIfNull(); if (LibENet.PacketResize(m_Native, unchecked ((UIntPtr)dataLength)) < 0) { ThrowHelper.ThrowENetPacketResizeFailed(); } }
public void Send(byte[] buffer, byte channel, ENetPacketFlags flags) { Native.ENetPacket *packet; fixed(byte *p = buffer) { packet = LibENet.PacketCreate((IntPtr)p, (UIntPtr)buffer.Length, flags & ~ENetPacketFlags.NoAllocate); } if (LibENet.PeerSend(Unsafe, channel, packet) < 0) { throw new Exception("Failed to send packet to peer."); } }
private ENetEvent NativeToManagedEvent(ref Native.ENetEvent native) { switch (native.Type) { case ENetEventType.None: return(null); case ENetEventType.Connect: var connect = new ENetConnectEventArgs(); if (native.Peer->Data == IntPtr.Zero) { connect.Peer = new ENetPeer(this, native.Peer); } else { connect.Peer = ENetPeer.FromPtr(native.Peer->Data); } connect.Peer.RemoteEndPoint = native.Peer->Address.ToEndPoint(); connect.Data = native.Data; return(connect); case ENetEventType.Disconnect: if (native.Peer->Data == IntPtr.Zero) { throw new NullReferenceException("Peer->Data"); } var disconnect = new ENetDisconnectEventArgs(); disconnect.Peer = ENetPeer.FromPtr(native.Peer->Data); disconnect.Data = native.Data; disconnect.Peer.FreeHandle(); return(disconnect); case ENetEventType.Receive: if (native.Peer->Data == IntPtr.Zero) { throw new NullReferenceException("Peer->Data"); } var receive = new ENetReceiveEventArgs(); receive.Peer = ENetPeer.FromPtr(native.Peer->Data); receive.Packet = new ENetPacket(native.Packet, native.ChannelID); LibENet.PacketDestroy(native.Packet); return(receive); default: throw new NotImplementedException(native.Type.ToString()); } }
public bool Receive(out ENetPacket packet) { byte channel = 0; Native.ENetPacket *native = LibENet.PeerReceive(Unsafe, &channel); if (((IntPtr)native) == IntPtr.Zero) { packet = null; return(false); } packet = new ENetPacket(native, channel); LibENet.PacketDestroy(native); return(true); }
public void BandwidthLimit(long incomingBandwidth, long outgoingBandwidth) { CheckDispose(); if (incomingBandwidth < uint.MinValue || incomingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException("incomingBandwidth"); } if (outgoingBandwidth < uint.MinValue || outgoingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException("outgoingBandwidth"); } LibENet.HostBandwidthLimit(Pointer, (uint)incomingBandwidth, (uint)outgoingBandwidth); }
/// <summary> /// Queues a packet to be sent. /// </summary> /// <param name="channelId">Destination channel Id</param> /// <param name="buffer">Buffer containing packet data</param> /// <param name="flags">Packet flags</param> /// <remarks> /// <see cref="ENetPacketFlags.NoAllocate"/> will be ignored. /// </remarks> public void Send(byte channelId, ReadOnlySpan <byte> buffer, ENetPacketFlags flags) { ThrowIfNull(); NativeENetPacket *packet; fixed(byte *p = buffer) { packet = LibENet.PacketCreate((IntPtr)p, unchecked ((UIntPtr)buffer.Length), flags & ~ENetPacketFlags.NoAllocate); } if (LibENet.PeerSend(m_Native, channelId, packet) < 0) { ThrowHelper.ThrowENetPeerSendFailed(); } }
/// <summary> /// Shutdowns and unloads ENet's library /// </summary> /// <param name="delete">Specifies whether the ENet dynamic library should be removed or not from disk.</param> /// <remarks> /// Any interaction with ENet managed wrapper instances like <see cref="ENetHost"/> should be avoided /// after calling this method. <br/> /// Parameter <paramref name="delete"/> is only considered when the library is loaded from the resources. /// </remarks> public static void Shutdown(bool delete = true) { if (!Started) { return; } Started = false; LibENet.Unload(); if (delete) { LibENet.TryDelete(); } s_Allocator?.Dispose(); s_Allocator = null; }
public void CompressWith(ENetCompressor compressor) { CheckDispose(); if (compressor.Host != null && compressor.Host != this) { throw new Exception("Compressor is already in use by another host."); } compressor.Host = this; Native.ENetCompressor native = new Native.ENetCompressor(); native.Context = compressor.AllocHandle(); native.Compress = Marshal.GetFunctionPointerForDelegate(ENetCompressor.CompressDelegate); native.Decompress = Marshal.GetFunctionPointerForDelegate(ENetCompressor.DecompressDelegate); native.Destroy = Marshal.GetFunctionPointerForDelegate(ENetCompressor.DestroyDelegate); LibENet.HostCompress(Pointer, &native); Compressor = compressor; }
public ENetPeer Connect(IPEndPoint endPoint, byte channels, uint data) { CheckDispose(); if (channels < 1) { throw new ArgumentOutOfRangeException("channels"); } Native.ENetAddress address = Native.ENetAddress.FromEndPoint(endPoint); var native = LibENet.HostConnect(Pointer, &address, (UIntPtr)channels, data); if (((IntPtr)native) == IntPtr.Zero) { throw new Exception("Failed to initiate connection."); } return(new ENetPeer(this, native)); }
public void Multicast(byte[] buffer, byte channel, ENetPacketFlags flags, IEnumerable <ENetPeer> peers, ENetPeer except) { CheckDispose(); Native.ENetPacket *packet; fixed(byte *p = buffer) { packet = LibENet.PacketCreate((IntPtr)p, (UIntPtr)buffer.Length, flags & ~ENetPacketFlags.NoAllocate); } foreach (var peer in peers) { if (peer == null) { throw new NullReferenceException(); } if (peer.Host != this) { throw new ENetMulticastException("Speicfied peer is not of this host.", peer); } if (peer == except) { continue; } if (peer.Unsafe->State != ENetPeerState.Connected) { continue; } if (LibENet.PeerSend(peer.Unsafe, channel, packet) != 0) { throw new ENetMulticastException("Failed to send packet to speicfied peer.", peer); } } if (packet->ReferenceCount.ToUInt32() == 0) { LibENet.PacketDestroy(packet); } }
/// <summary> /// Attempts to dequeue any incoming queued packet. /// </summary> /// <param name="packet">Received packet if return value is true</param> /// <param name="channelId">Receiver channel if return value is true</param> /// <returns>Return true if packet received otherwise false</returns> public bool TryReceive(out ENetPacket packet, out byte channelId) { ThrowIfNull(); byte chnl = 0; var resultPacket = LibENet.PeerReceive(m_Native, &chnl); if (resultPacket == null) { channelId = 0; packet = default; return(false); } else { channelId = chnl; packet = new ENetPacket(resultPacket); return(true); } }
public ENetHost(IPEndPoint address, int peers, byte channels, long incomingBandwidth, long outgoingBandwidth) { if (incomingBandwidth < uint.MinValue || incomingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException("incomingBandwidth"); } if (outgoingBandwidth < uint.MinValue || outgoingBandwidth > uint.MaxValue) { throw new ArgumentOutOfRangeException("outgoingBandwidth"); } if (peers < uint.MinValue || peers > LibENet.ENET_PROTOCOL_MAXIMUM_PEER_ID) { throw new ArgumentOutOfRangeException(string.Format("Maximum peers count is {0}", LibENet.ENET_PROTOCOL_MAXIMUM_PEER_ID)); } var enetAddress = Native.ENetAddress.FromEndPoint(address); Pointer = LibENet.HostCreate(&enetAddress, (UIntPtr)peers, (UIntPtr)channels, (uint)incomingBandwidth, (uint)outgoingBandwidth); if (Pointer == IntPtr.Zero) { throw new Exception("Failed to create ENet host."); } m_pInterceptCallback = (IntPtr *)IntPtr.Add(Pointer, Native.ENetHostOffset.InterceptOffset); m_pChecksumCallback = (IntPtr *)IntPtr.Add(Pointer, Native.ENetHostOffset.ChecksumOffset); m_pTotalSentData = (uint *)IntPtr.Add(Pointer, Native.ENetHostOffset.TotalSentDataOffset); m_pTotalSentPackets = (uint *)IntPtr.Add(Pointer, Native.ENetHostOffset.TotalSentPacketsOffset); m_pTotalReceivedData = (uint *)IntPtr.Add(Pointer, Native.ENetHostOffset.TotalReceivedDataOffset); m_pTotalReceivedPackets = (uint *)IntPtr.Add(Pointer, Native.ENetHostOffset.TotalReceivedPacketsOffset); m_pReceivedAddress = (Native.ENetAddress *)IntPtr.Add(Pointer, Native.ENetHostOffset.ReceivedAddressOffset); m_pReceivedData = (IntPtr *)IntPtr.Add(Pointer, Native.ENetHostOffset.ReceivedDataOffset); m_pReceivedDataLength = (UIntPtr *)IntPtr.Add(Pointer, Native.ENetHostOffset.ReceivedDataLengthOffset); m_pConnectedPeers = (UIntPtr *)IntPtr.Add(Pointer, Native.ENetHostOffset.ConnectedPeersOffset); ChecksumDelegate = new Native.ENetChecksumCallback(ChecksumCallback); m_InterceptDelegate = new Native.ENetInterceptCallback(InterceptCallback); }
public bool Service(out ENetEvent e, uint timeout) { CheckDispose(); var native = new Native.ENetEvent(); int result; result = LibENet.HostService(Pointer, &native, timeout); if (result < 0) { throw new Exception("Service failure."); } if (result == 0) { e = new ENetNoneEventArgs(); } else { e = NativeToManagedEvent(ref native); } return(true); }
/// <summary> /// Destroys packet without considering references count /// </summary> public void Destroy() { ThrowIfNull(); LibENet.PacketDestroy(m_Native); }
public void Timeout(uint timeoutLimit, uint timeoutMinimum, uint timeoutMaximum) => LibENet.PeerTimeout(Unsafe, timeoutLimit, timeoutMinimum, timeoutMaximum);
public void ThrottleConfigure(uint interval, uint acceleration, uint deceleration) => LibENet.PeerThrottleConfigure(Unsafe, interval, acceleration, deceleration);
public void PingInterval(uint pingInterval) => LibENet.PeerPingInterval(Unsafe, pingInterval);