using System; using System.Collections.Generic; using System.Threading; using System.Net; namespace Lidgren.Network { public partial class NetPeer { /// /// Send a message to a specific connection /// /// The message to send /// The recipient connection /// How to deliver the message public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method) { return SendMessage(msg, recipient, method, 0); } /// /// Send a message to a specific connection /// /// The message to send /// The recipient connection /// How to deliver the message /// Sequence channel within the delivery method 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"); 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"); int len = msg.LengthBytes; if (len <= m_configuration.MaximumTransmissionUnit) { Interlocked.Increment(ref msg.m_recyclingCount); return recipient.EnqueueMessage(msg, method, sequenceChannel); } else { // message must be fragmented! SendFragmentedMessage(msg, new NetConnection[] { recipient }, method, sequenceChannel); return NetSendResult.Queued; // could be different for each connection; Queued is "most true" } } public void SendMessage(NetOutgoingMessage msg, IList recipients, NetDeliveryMethod method, int sequenceChannel) { if (msg == null) throw new ArgumentNullException("msg"); if (recipients == null) throw new ArgumentNullException("recipients"); if (method == NetDeliveryMethod.Unreliable || method == NetDeliveryMethod.ReliableUnordered) NetException.Assert(sequenceChannel == 0, "Delivery method " + method + " cannot use sequence channels other than 0!"); if (msg.m_isSent) throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently"); int len = msg.LengthBytes; if (len <= m_configuration.MaximumTransmissionUnit) { Interlocked.Add(ref msg.m_recyclingCount, recipients.Count); foreach (NetConnection conn in recipients) { if (conn == null) { Interlocked.Decrement(ref msg.m_recyclingCount); continue; } NetSendResult res = conn.EnqueueMessage(msg, method, sequenceChannel); if (res == NetSendResult.Dropped) Interlocked.Decrement(ref msg.m_recyclingCount); } } else { // message must be fragmented! SendFragmentedMessage(msg, recipients, method, sequenceChannel); } return; } /// /// Send a message to an unconnected host /// public void SendUnconnectedMessage(NetOutgoingMessage msg, string host, int port) { if (msg == null) throw new ArgumentNullException("msg"); if (host == null) throw new ArgumentNullException("host"); if (msg.m_isSent) throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently"); if (msg.LengthBytes > m_configuration.MaximumTransmissionUnit) throw new NetException("Unconnected messages too long! Must be shorter than NetConfiguration.MaximumTransmissionUnit (currently " + m_configuration.MaximumTransmissionUnit + ")"); IPAddress adr = NetUtility.Resolve(host); if (adr == null) throw new NetException("Failed to resolve " + host); msg.m_messageType = NetMessageType.Unconnected; Interlocked.Increment(ref msg.m_recyclingCount); m_unsentUnconnectedMessages.Enqueue(new NetTuple(new IPEndPoint(adr, port), msg)); } /// /// Send a message to an unconnected host /// public void SendUnconnectedMessage(NetOutgoingMessage msg, IPEndPoint recipient) { if (msg == null) throw new ArgumentNullException("msg"); if (recipient == null) throw new ArgumentNullException("recipient"); if (msg.m_isSent) throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently"); if (msg.LengthBytes > m_configuration.MaximumTransmissionUnit) throw new NetException("Unconnected messages too long! Must be shorter than NetConfiguration.MaximumTransmissionUnit (currently " + m_configuration.MaximumTransmissionUnit + ")"); msg.m_messageType = NetMessageType.Unconnected; Interlocked.Increment(ref msg.m_recyclingCount); m_unsentUnconnectedMessages.Enqueue(new NetTuple(recipient, msg)); } /// /// Send a message to an unconnected host /// public void SendUnconnectedMessage(NetOutgoingMessage msg, IList recipients) { if (msg == null) throw new ArgumentNullException("msg"); if (recipients == null) throw new ArgumentNullException("recipients"); if (msg.m_isSent) throw new NetException("This message has already been sent! Use NetPeer.SendMessage() to send to multiple recipients efficiently"); if (msg.LengthBytes > m_configuration.MaximumTransmissionUnit) throw new NetException("Unconnected messages too long! Must be shorter than NetConfiguration.MaximumTransmissionUnit (currently " + m_configuration.MaximumTransmissionUnit + ")"); msg.m_messageType = NetMessageType.Unconnected; Interlocked.Add(ref msg.m_recyclingCount, recipients.Count); foreach(IPEndPoint ep in recipients) m_unsentUnconnectedMessages.Enqueue(new NetTuple(ep, msg)); } } }