Ejemplo n.º 1
0
        /// <summary>
        /// Send a message to a specific connection
        /// </summary>
        /// <param name="msg">The message to send</param>
        /// <param name="recipient">The recipient connection</param>
        /// <param name="method">How to deliver the message</param>
        /// <param name="sequenceChannel">Sequence channel within the delivery method</param>
        public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method, int sequenceChannel)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }
            if (recipient == null)
            {
                throw new ArgumentNullException("recipient");
            }
            if (sequenceChannel >= NetConstants.NetChannelsPerDeliveryMethod)
            {
                throw new ArgumentOutOfRangeException("sequenceChannel");
            }

            NetException.Assert(
                ((method != NetDeliveryMethod.Unreliable && method != NetDeliveryMethod.ReliableUnordered) ||
                 ((method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered) && sequenceChannel == 0)),
                "Delivery method " + method + " cannot use sequence channels other than 0!"
                );

            NetException.Assert(method != NetDeliveryMethod.Unknown, "Bad delivery method!");

            if (msg.m_isSent)
            {
                throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently");
            }
            msg.m_isSent = true;

            bool suppressFragmentation = (method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.UnreliableSequenced) && m_configuration.UnreliableSizeBehaviour != NetUnreliableSizeBehaviour.NormalFragmentation;

            int len = NetConstants.UnfragmentedMessageHeaderSize + msg.LengthBytes;             // headers + length, faster than calling msg.GetEncodedSize

            if (len <= recipient.m_currentMTU || suppressFragmentation)
            {
                Interlocked.Increment(ref msg.m_recyclingCount);
                return(recipient.EnqueueMessage(msg, method, sequenceChannel));
            }
            else
            {
                // message must be fragmented!
                if (recipient.m_status != NetConnectionStatus.Connected)
                {
                    return(NetSendResult.FailedNotConnected);
                }
                // return SendFragmentedMessage(msg, new NetConnection[] { recipient }, method, sequenceChannel);
                var tmp = ConnectionListPool.Rent();
                tmp.Add(recipient);
                var result = SendFragmentedMessage(msg, tmp, method, sequenceChannel);
                ConnectionListPool.Return(tmp);
                return(result);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Gets a copy of the list of connections
        /// </summary>
        public List <NetConnection> GetConnections()
        {
            var list = ConnectionListPool.Rent();

            lock (m_connections) {
                foreach (var conn in m_connections)
                {
                    list.Add(conn);
                }
            }

            return(list);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Send a message to all connections except one
        /// </summary>
        /// <param name="msg">The message to send</param>
        /// <param name="method">How to deliver the message</param>
        /// <param name="except">Don't send to this particular connection</param>
        /// <param name="sequenceChannel">Which sequence channel to use for the message</param>
        public void SendToAll(NetOutgoingMessage msg, NetConnection except, NetDeliveryMethod method, int sequenceChannel)
        {
            // Modifying m_connections will modify the list of the connections of the NetPeer. Do only reads here
            var all = m_connections;

            if (all.Count <= 0)
            {
                if (msg.m_isSent == false)
                {
                    Recycle(msg);
                }
                return;
            }

            if (except == null)
            {
                SendMessage(msg, all, method, sequenceChannel);
                return;
            }


            var recipients = ConnectionListPool.Rent();

            foreach (var conn in all)
            {
                if (conn != except)
                {
                    recipients.Add(conn);
                }
            }

            if (recipients.Count > 0)
            {
                SendMessage(msg, recipients, method, sequenceChannel);
            }
            ConnectionListPool.Return(recipients);
        }
Ejemplo n.º 4
0
        private void ExecutePeerShutdown()
        {
            VerifyNetworkThread();

            LogDebug("Shutting down...");

            // disconnect and make one final heartbeat
            var list = ConnectionListPool.Rent();

            lock (m_connections)
            {
                foreach (var conn in m_connections)
                {
                    if (conn != null)
                    {
                        list.Add(conn);
                    }
                }
            }

            lock (m_handshakes)
            {
                foreach (var hs in m_handshakes.Values)
                {
                    if (hs != null && list.Contains(hs) == false)
                    {
                        list.Add(hs);
                    }
                }
            }

            // shut down connections
            foreach (NetConnection conn in list)
            {
                conn.Shutdown(m_shutdownReason);
            }

            ConnectionListPool.Return(list);

            FlushDelayedPackets();

            // one final heartbeat, will send stuff and do disconnect
            Heartbeat();

            NetUtility.Sleep(10);

            lock (m_initializeLock)
            {
                try
                {
                    if (m_socket != null)
                    {
                        try
                        {
                            m_socket.Shutdown(SocketShutdown.Receive);
                        }
                        catch (Exception ex)
                        {
                            LogDebug("Socket.Shutdown exception: " + ex.ToString());
                        }

                        try
                        {
                            m_socket.Close(2);                             // 2 seconds timeout
                        }
                        catch (Exception ex)
                        {
                            LogDebug("Socket.Close exception: " + ex.ToString());
                        }
                    }
                }
                finally
                {
                    m_socket = null;
                    m_status = NetPeerStatus.NotRunning;
                    LogDebug("Shutdown complete");

                    // wake up any threads waiting for server shutdown
                    if (m_messageReceivedEvent != null)
                    {
                        m_messageReceivedEvent.Set();
                    }
                }

                m_lastSocketBind = float.MinValue;
                m_receiveBuffer  = null;
                m_sendBuffer     = null;
                m_unsentUnconnectedMessages.Clear();
                m_connections.Clear();
                m_connectionLookup.Clear();
                m_handshakes.Clear();
            }

            return;
        }