/// <summary> /// Send a message to a list of connections. /// </summary> /// <param name="message">The message to send</param> /// <param name="recipients">The list of recipients to send to</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, IEnumerable <NetConnection?> recipients, NetDeliveryMethod method, int sequenceChannel) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (recipients == null) { throw new ArgumentNullException(nameof(recipients)); } NetConstants.AssertValidDeliveryChannel( method, sequenceChannel, nameof(method), nameof(sequenceChannel)); message.AssertNotSent(nameof(message)); message._isSent = true; int mtu = GetMTU(recipients, out int recipientCount); if (recipientCount == 0) { Recycle(message); return(NetSendResult.NoRecipients); } int length = message.GetEncodedSize(); if (length <= mtu) { Interlocked.Add(ref message._recyclingCount, recipientCount); var retval = NetSendResult.Sent; foreach (NetConnection?conn in recipients.AsListEnumerator()) { if (conn == null) { continue; } NetSendResult result = conn.EnqueueMessage(message, method, sequenceChannel).Result; if (result > retval) { retval = result; // return "worst" result } } return(retval); } else { // message must be fragmented! return(SendFragmentedMessage(message, recipients, method, sequenceChannel)); } }
/// <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); } } }