Ejemplo n.º 1
0
        /// <summary>
        /// Sets timeouts for a response from the remote computer acknowledging its receipt of a reliable packet.
        /// When the timeouts are exceeded, a disconnect event occurs.
        /// </summary>
        /// <param name="retryLimit">
        ///     The number of retries to make before considering the minimum timeout time.
        ///     The default value is 5.
        /// </param>
        /// <param name="retryMinimumTime">
        ///     The minimum time in milliseconds to allow for retrying, or 0 to use the default (5000).
        /// </param>
        /// <param name="maximumTime">
        ///     The maximum time in milliseconds to wait regardless of the number of retries, or 0 to use the default (30000).
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     <paramref name="retryLimit"/> is negative or greater than 20,
        ///     <paramref name="retryMinimumTime"/> is negative, and/or
        ///     <paramref name="maximumTime"/> is negative.
        ///  </exception>
        /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
        /// <exception cref="NotSupportedException">This method requires ENet 1.3.4 or newer.</exception>
        public void SetTimeouts(int retryLimit, int retryMinimumTime, int maximumTime)
        {
            CheckInitialized();
            if (retryLimit < 0 || retryLimit > 20)
            {
                throw new ArgumentOutOfRangeException("retryLimit");
            }
            if (retryMinimumTime < 0)
            {
                throw new ArgumentOutOfRangeException("retryMinimumTime");
            }
            if (maximumTime < 0)
            {
                throw new ArgumentOutOfRangeException("maximumTime");
            }

            try
            {
                ENetApi.enet_peer_timeout(NativeData, 1U << retryLimit, (uint)retryMinimumTime, (uint)maximumTime);
            }
            catch (EntryPointNotFoundException e)
            {
                throw new NotSupportedException("This method requires ENet 1.3.4 or newer.", e);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Initialize a host that will accept connections on a particular address, or not accept connections.
        /// </summary>
        /// <param name="address">The address to listen on, or null to not accept connections.</param>
        /// <param name="peerLimit">The maximum number of peers for this host.</param>
        /// <param name="channelLimit">The maximum number of channels, or 0 to use the maximum possible (255).</param>
        /// <param name="incomingBandwidth">The maximum incoming rate of transfer, or 0 for no limit.</param>
        /// <param name="outgoingBandwidth">The maximum outgoing rate of transfer, or 0 for no limit.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     <paramref name="peerLimit"/> is less than 0 or greater than 4095,
        ///     <paramref name="channelLimit"/> is less than 0 or greater than 255,
        ///     <paramref name="incomingBandwidth"/> is less than 0, and/or
        ///     <paramref name="outgoingBandwidth"/> is less than 0.
        /// </exception>
        /// <exception cref="InvalidOperationException">The host is already initialized.</exception>
        /// <exception cref="ENetException">Failed to initialize the host.</exception>
        public void Initialize(IPEndPoint address, int peerLimit,
                               int channelLimit = 0, int incomingBandwidth = 0, int outgoingBandwidth = 0)
        {
            if (NativeData != null)
            {
                throw new InvalidOperationException("Already initialized.");
            }
            if (peerLimit < 0 || peerLimit > ENetApi.ENET_PROTOCOL_MAXIMUM_PEER_ID)
            {
                throw new ArgumentOutOfRangeException("peerLimit");
            }
            CheckChannelLimit(channelLimit);
            CheckBandwidthLimit(incomingBandwidth, outgoingBandwidth);

            if (address != null)
            {
                ENetAddress nativeAddress = (ENetAddress)address;
                NativeData = ENetApi.enet_host_create(ref nativeAddress, (IntPtr)peerLimit,
                                                      (IntPtr)channelLimit, (uint)incomingBandwidth, (uint)outgoingBandwidth);
            }
            else
            {
                NativeData = ENetApi.enet_host_create(null, (IntPtr)peerLimit,
                                                      (IntPtr)channelLimit, (uint)incomingBandwidth, (uint)outgoingBandwidth);
            }
            if (NativeData == null)
            {
                throw new ENetException("Host creation call failed.");
            }
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Destroys the host.
 /// </summary>
 public void Dispose()
 {
     if (NativeData != null)
     {
         ENetApi.enet_host_destroy(NativeData);
         NativeData = null;
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Enqueues a packet for sending.
        /// </summary>
        /// <param name="channelID">The ID of the channel to send on.</param>
        /// <param name="packet">The packet to send.</param>
        /// <returns>True if the packet was enqueued successfully, or false if an error occured.</returns>
        /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
        /// <exception cref="ENetException">An error occured.</exception>
        public void Send(byte channelID, Packet packet)
        {
            CheckInitialized(); packet.CheckInitialized();
            int ret = ENetApi.enet_peer_send(NativeData, channelID, packet.NativeData);

            if (ret < 0)
            {
                throw new ENetException("An error occured sending to the peer.");
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Dequeue a received packet.
 /// </summary>
 /// <param name="channelID">The ID of the channel the packet was sent on.</param>
 /// <param name="packet">The received packet.</param>
 /// <returns>True if a packet was dequeued, or false if there are no more packets.</returns>
 /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
 public bool Receive(out byte channelID, out Packet packet)
 {
     CheckInitialized(); ENetPacket *nativePacket;
     nativePacket = ENetApi.enet_peer_receive(NativeData, out channelID);
     if (nativePacket == null)
     {
         packet = new Packet(); return(false);
     }
     packet = new Packet(nativePacket); return(true);
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Enables compression using the range encoder.
        /// </summary>
        /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
        /// <exception cref="ENetException">Failed to create range encoder. This is likely due to low memory.</exception>
        public void CompressWithRangeEncoder()
        {
            CheckInitialized();
            int ret = ENetApi.enet_host_compress_with_range_encoder(NativeData);

            if (ret < 0)
            {
                throw new ENetException("Failed to create range encoder.");
            }
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Destroys the ENet packet.
 /// </summary>
 public void Dispose()
 {
     if (NativeData != null)
     {
         if (NativeData->referenceCount == IntPtr.Zero)
         {
             ENetApi.enet_packet_destroy(NativeData);
         }
         NativeData = null;
     }
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Broadcast a packet to all peers.
        /// </summary>
        /// <param name="channelID">The ID of the channel</param>
        /// <param name="packet">The packet to send.</param>
        /// <remarks>ENet takes ownership of the packet. Do not call methods on it afterwards.</remarks>
        /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
        public void Broadcast(byte channelID, ref Packet packet)
        {
            CheckInitialized(); packet.CheckInitialized();

            bool clear = packet.ReferenceCount == 0;

            ENetApi.enet_host_broadcast(NativeData, channelID, packet.NativeData);
            if (clear)
            {
                packet.NativeData = null;
            }                                        // Broadcast may automatically free in this case.
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Resizes the packet.
 /// </summary>
 /// <param name="length">The new packet length.</param>
 /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is negative.</exception>
 /// <exception cref="InvalidOperationException">The packet is not initialized.</exception>
 public void Resize(int length)
 {
     if (length < 0)
     {
         throw new ArgumentOutOfRangeException("length");
     }
     CheckInitialized(); int ret = ENetApi.enet_packet_resize(NativeData, (IntPtr)length);
     if (ret < 0)
     {
         throw new OutOfMemoryException("Packet resizing failed.");
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Initializes a new packet from data, of the given length, and with the given flags.
        /// </summary>
        /// <param name="data">A pointer to the first byte of data.</param>
        /// <param name="length">The length of the data.</param>
        /// <param name="flags">The flags the packet will use.</param>
        /// <exception cref="InvalidOperationException">The packet is already initialized.</exception>
        /// <exception cref="ENetException">Packet creation failed.</exception>
        public void Initialize(IntPtr data, int length, PacketFlags flags)
        {
            if (NativeData != null)
            {
                throw new InvalidOperationException("Already initialized.");
            }

            NativeData = ENetApi.enet_packet_create(data, (IntPtr)length, flags);
            if (NativeData == null)
            {
                throw new ENetException("Packet creation call failed.");
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Checks for queued events.
        /// </summary>
        /// <param name="event">The dequeued event.</param>
        /// <returns>True if an event was dequeued, otherwise false.</returns>
        /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
        /// <exception cref="ENetException">An error occured while checking events.</exception>
        public bool CheckEvents(out Event @event)
        {
            CheckInitialized(); ENetEvent nativeEvent;
            int ret = ENetApi.enet_host_check_events(NativeData, out nativeEvent);

            if (ret < 0)
            {
                throw new ENetException("Error while checking for events.");
            }
            if (ret == 0)
            {
                @event = new Event(); return(false);
            }
            @event = new Event(nativeEvent); return(true);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Sets the interval between pings.
        /// ENet will automatically send pings when it hasn't received anything from the remote computer.
        /// </summary>
        /// <param name="interval">
        ///     The interval in milliseconds between pings, or 0 to use the default (500).
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="interval"/> is negative.</exception>
        /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
        /// <exception cref="NotSupportedException">This method requires ENet 1.3.4 or newer.</exception>
        public void SetPingInterval(int interval)
        {
            CheckInitialized();
            if (interval < 0)
            {
                throw new ArgumentOutOfRangeException("interval");
            }

            try
            {
                ENetApi.enet_peer_ping_interval(NativeData, (uint)interval);
            }
            catch (EntryPointNotFoundException e)
            {
                throw new NotSupportedException("This method requires ENet 1.3.4 or newer.", e);
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Configures throttling. ENet measures lag over an interval, and alters its throttle parameter
 /// based on individual packet round-trip times versus the mean. This parameter controls the probability
 /// ENet will drop an unreliable packet. If a packet has a smaller round-trip time than average, the parameter
 /// is increased by the acceleration term, causing less packets to be dropped. If a packet has a larger
 /// round-trip time than average, the parameter is decreased by the deceleration term, causing more packets
 /// to be dropped.
 /// </summary>
 /// <param name="interval">The interval in milliseconds over which to measure. The default is 5000.</param>
 /// <param name="acceleration">Acceleration rate. The default value is 2, and the limit is 32.</param>
 /// <param name="deceleration">Deceleration rate. The default value is 2, and the limit is 32.</param>
 /// <exception cref="ArgumentOutOfRangeException">
 ///     <paramref name="interval"/> is negative,
 ///     <paramref name="acceleration"/> is less than 0 or greater than 32, and/or
 ///     <paramref name="deceleration"/> is less than 0 or greater than 32.
 /// </exception>
 /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
 public void ConfigureThrottle(int interval, int acceleration, int deceleration)
 {
     CheckInitialized();
     if (interval < 0)
     {
         throw new ArgumentOutOfRangeException("interval");
     }
     if (acceleration < 0 || acceleration > 32)
     {
         throw new ArgumentOutOfRangeException("acceleration");
     }
     if (deceleration < 0 || deceleration > 32)
     {
         throw new ArgumentOutOfRangeException("deceleration");
     }
     ENetApi.enet_peer_throttle_configure(NativeData, (uint)interval, (uint)acceleration, (uint)deceleration);
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Connects to a remote computer at the given address.
        /// </summary>
        /// <param name="address">The address to connect to.</param>
        /// <param name="data">Data to send along with the connect packet.</param>
        /// <param name="channelLimit">The maximum number of channels, or 0 to use the maximum possible (255).</param>
        /// <returns>
        ///     The new peer. This method does not block: the connection will be established
        ///     when you receive a <see cref="EventType.Connect"/> event.
        /// </returns>
        /// <exception cref="ArgumentNullException"><paramref name="address"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="address"/> is not IPv4.</exception>
        /// <exception cref="ArgumentOutOfRangeException">
        ///     <paramref name="address"/>'s port is less than 0 or greater than 65535, and/or
        ///     <paramref name="channelLimit"/> is less than 0 or greater than 255.
        /// </exception>
        /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
        /// <exception cref="ENetException">An error occured.</exception>
        public Peer Connect(IPEndPoint address, int data, int channelLimit = 0)
        {
            CheckInitialized(); ENetAddress nativeAddress = (ENetAddress)address;
            CheckChannelLimit(channelLimit);

            // For consistency with Connect() and SetChannelLimit(),
            if (channelLimit == 0)
            {
                channelLimit = (int)ENetApi.ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
            }

            Peer peer = new Peer(ENetApi.enet_host_connect(NativeData, ref nativeAddress, (IntPtr)channelLimit, (uint)data));

            if (peer.NativeData == null)
            {
                throw new ENetException("Host connect failed.");
            }
            return(peer);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Sends queued outgoing packets, receives incoming packets, and handles connection events.
        /// </summary>
        /// <param name="timeout">Timeout in milliseconds to wait for an event. For polling, use 0.</param>
        /// <param name="event">The event.</param>
        /// <returns>True if an event occured, otherwise false.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="timeout"/> is negative.</exception>
        /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
        /// <exception cref="ENetException">An error occured.</exception>
        public bool Service(int timeout, out Event @event)
        {
            if (timeout < 0)
            {
                throw new ArgumentOutOfRangeException("timeout");
            }
            CheckInitialized(); ENetEvent nativeEvent = new ENetEvent();

            // As of 1.3.6, ENet is not signal safe, and Mono uses signals for garbage collection.
            //
            // So, there's really nothing better we can do than retry. Luckily the cases that return -1
            // are cases that return immediately or this could cause lockups.
            //
            // The entire situation is still very dicey with MonoDevelop.
            // A proper fix really has to be done in the ENet native library.
            // If you want to eliminate this entirely and don't care about these spurious
            // failures of enet_host_service, try/catch the ENetException and just ignore it.
            // That's essentially what I am doing here, except with an upper limit so real errors
            // can get through...
            int ret = -1;

            for (int nretries = 0; nretries < 1000 && ret == -1; nretries++)
            {
                ret = ENetApi.enet_host_service(NativeData, out nativeEvent, (uint)timeout);
            }

            if (ret < 0)
            {
                throw new ENetException(string.Format("Service failed (native data {0}).", (IntPtr)NativeData));
            }
            if (ret == 0)
            {
                @event = new Event(); return(false);
            }
            @event = new Event(nativeEvent); return(true);
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Sends queued packets immediately. Normally they are sent when you call <see cref="Service(int, out Event)"/>.
 /// </summary>
 /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
 public void Flush()
 {
     CheckInitialized();
     ENetApi.enet_host_flush(NativeData);
 }
Ejemplo n.º 17
0
 /// <summary>
 /// Immediately disconnects from the remote computer.
 /// A disconnect packet is sent unreliably. No event occurs.
 /// </summary>
 /// <param name="data">Data to send along with the disconnect packet.</param>
 /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
 public void DisconnectNow(int data)
 {
     CheckInitialized(); ENetApi.enet_peer_disconnect_now(NativeData, (uint)data);
 }
Ejemplo n.º 18
0
 /// <summary>
 /// Disables compression.
 /// </summary>
 /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
 public void DoNotCompress()
 {
     CheckInitialized();
     ENetApi.enet_host_compress(NativeData, null);
 }
Ejemplo n.º 19
0
 /// <summary>
 /// Sends a ping to the remote computer.
 /// </summary>
 /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
 public void Ping()
 {
     CheckInitialized(); ENetApi.enet_peer_ping(NativeData);
 }
Ejemplo n.º 20
0
 /// <summary>
 /// Resets the connection to the remote computer.
 /// No disconnect packets are sent, and no event occurs.
 /// </summary>
 /// <exception cref="InvalidOperationException">The peer is not initialized.</exception>
 public void Reset()
 {
     CheckInitialized(); ENetApi.enet_peer_reset(NativeData);
 }
Ejemplo n.º 21
0
 /// <summary>
 /// Set the bandwidth limit.
 /// </summary>
 /// <param name="incomingBandwidth">The maximum incoming rate of transfer, or 0 for no limit.</param>
 /// <param name="outgoingBandwidth">The maximum outgoing rate of transfer, or 0 for no limit.</param>
 /// <exception cref="ArgumentOutOfRangeException">
 ///     <paramref name="incomingBandwidth"/> is less than 0, and/or
 ///     <paramref name="outgoingBandwidth"/> is less than 0.
 /// </exception>
 /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
 public void SetBandwidthLimit(int incomingBandwidth, int outgoingBandwidth)
 {
     CheckInitialized(); CheckBandwidthLimit(incomingBandwidth, outgoingBandwidth);
     ENetApi.enet_host_bandwidth_limit(NativeData, (uint)incomingBandwidth, (uint)outgoingBandwidth);
 }
Ejemplo n.º 22
0
 /// <summary>
 /// Set the channel limit.
 /// </summary>
 /// <param name="channelLimit">The maximum number of channels, or 0 to use the maximum possible (255).</param>
 /// <exception cref="InvalidOperationException">The host is not initialized.</exception>
 public void SetChannelLimit(int channelLimit)
 {
     CheckChannelLimit(channelLimit); CheckInitialized();
     ENetApi.enet_host_channel_limit(NativeData, (IntPtr)channelLimit);
 }
Ejemplo n.º 23
0
 /// <summary>
 /// Throws an exception if the ENet native library cannot be loaded.
 /// ENet is now automatically initialized, so it is no longer strictly
 /// necessary to call this function.
 /// </summary>
 /// <exception cref="ENetException">The native library cannot be loaded.</exception>
 public static void Initialize()
 {
     ENetApi.enet_time_get();
 }