Exemplo n.º 1
0
        /// <summary>
        /// Send a message to all connections except one
        /// </summary>
        /// <param name="message">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 message, NetConnection?except, NetDeliveryMethod method, int sequenceChannel)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var all = NetConnectionListPool.GetConnections(this);

            if (all == null)
            {
                if (!message._isSent)
                {
                    Recycle(message);
                }
                return;
            }

            try
            {
                if (except != null)
                {
                    all.Remove(except);
                }

                SendMessage(message, all, method, sequenceChannel);
            }
            finally
            {
                NetConnectionListPool.Return(all);
            }
        }
        /// <summary>
        /// Streams a message to a list of connections.
        /// </summary>
        /// <param name="message">The message to stream.</param>
        /// <param name="recipients">The list of recipients to send to.</param>
        /// <param name="sequenceChannel">Sequence channel within <see cref="NetDeliveryMethod.ReliableOrdered"/>.</param>
        public async ValueTask <NetSendResult> StreamMessageAsync(
            PipeReader message,
            IEnumerable <NetConnection?> recipients,
            int sequenceChannel,
            CancellationToken cancellationToken = default)
        {
            List <NetConnection> recipientList = NetConnectionListPool.Rent(recipients);

            try
            {
                if (recipientList.Count == 0)
                {
                    return(NetSendResult.NoRecipients);
                }

                if (recipientList.Count > 1)
                {
                    throw new NotImplementedException("The method can only send to one recipient at the time.");
                }

                return(await SendFragmentedMessageAsync(message, recipientList[0], sequenceChannel, cancellationToken));
            }
            finally
            {
                NetConnectionListPool.Return(recipientList);
            }
        }
        /// <summary>
        /// Send a message to a specific connection.
        /// </summary>
        /// <param name="message">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 message, NetConnection recipient, NetDeliveryMethod method, int sequenceChannel)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (recipient == null)
            {
                throw new ArgumentNullException(nameof(recipient));
            }

            NetConstants.AssertValidDeliveryChannel(
                method, sequenceChannel, nameof(method), nameof(sequenceChannel));

            message.AssertNotSent(nameof(message));
            message._isSent = true;

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

            if (suppressFragmentation || message.GetEncodedSize() <= recipient.CurrentMTU)
            {
                Interlocked.Increment(ref message._recyclingCount);
                return(recipient.EnqueueMessage(message, method, sequenceChannel).Result);
            }
            else
            {
                // message must be fragmented!
                if (recipient.Status != NetConnectionStatus.Connected)
                {
                    return(NetSendResult.FailedNotConnected);
                }

                List <NetConnection> recipients = NetConnectionListPool.Rent(1);
                try
                {
                    recipients.Add(recipient);
                    return(SendFragmentedMessage(message, recipients, method, sequenceChannel));
                }
                finally
                {
                    NetConnectionListPool.Return(recipients);
                }
            }
        }