Inheritance: SlimNet.Network.IRawStream
Exemplo n.º 1
0
		// on user thread
		private NetSendResult SendFragmentedMessage(NetOutgoingMessage msg, IList<NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
		{
			// Note: this group id is PER SENDING/NetPeer; ie. same id is sent to all recipients;
			// this should be ok however; as long as recipients differentiate between same id but different sender
			int group = Interlocked.Increment(ref m_lastUsedFragmentGroup);
			if (group >= NetConstants.MaxFragmentationGroups)
			{
				// @TODO: not thread safe; but in practice probably not an issue
				m_lastUsedFragmentGroup = 1;
				group = 1;
			}
			msg.m_fragmentGroup = group;

			// do not send msg; but set fragmentgroup in case user tries to recycle it immediately

			// create fragmentation specifics
			int totalBytes = msg.LengthBytes;

			// determine minimum mtu for all recipients
			int mtu = GetMTU(recipients);
			int bytesPerChunk = NetFragmentationHelper.GetBestChunkSize(group, totalBytes, mtu);

			int numChunks = totalBytes / bytesPerChunk;
			if (numChunks * bytesPerChunk < totalBytes)
				numChunks++;

			NetSendResult retval = NetSendResult.Sent;

			int bitsPerChunk = bytesPerChunk * 8;
			int bitsLeft = msg.LengthBits;
			for (int i = 0; i < numChunks; i++)
			{
				NetOutgoingMessage chunk = CreateMessage(0);

				chunk.m_bitLength = (bitsLeft > bitsPerChunk ? bitsPerChunk : bitsLeft);
				chunk.m_data = msg.m_data;
				chunk.m_fragmentGroup = group;
				chunk.m_fragmentGroupTotalBits = totalBytes * 8;
				chunk.m_fragmentChunkByteSize = bytesPerChunk;
				chunk.m_fragmentChunkNumber = i;

				NetException.Assert(chunk.m_bitLength != 0);
				NetException.Assert(chunk.GetEncodedSize() < mtu);

				Interlocked.Add(ref chunk.m_recyclingCount, recipients.Count);

				foreach (NetConnection recipient in recipients)
				{
					var res = recipient.EnqueueMessage(chunk, method, sequenceChannel);
					if (res == NetSendResult.Dropped)
						Interlocked.Decrement(ref chunk.m_recyclingCount);
					if ((int)res > (int)retval)
						retval = res; // return "worst" result
				}

				bitsLeft -= bitsPerChunk;
			}

			return retval;
		}
 public void WriteToMessage(NetOutgoingMessage message)
 {
     message.Write(SessionID);
     message.Write(ID);
     message.Write(IsValid);
     message.Write(PlayerIndex);
 }
 internal override NetSendResult Enqueue(NetOutgoingMessage message)
 {
     m_queuedSends.Enqueue(message);
     if (m_queuedSends.Count <= GetAllowedSends())
         return NetSendResult.Sent;
     return NetSendResult.Queued;
 }
Exemplo n.º 4
0
 protected override void WriteData(NetOutgoingMessage Message)
 {
     texture.Write(Message);
     byte[] data = GetBytes(texture.Texture);
     Message.Write((Int32)data.Length);
     Message.Write(data);
 }
Exemplo n.º 5
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;

            int len = NetConstants.UnfragmentedMessageHeaderSize + msg.LengthBytes; // headers + length, faster than calling msg.GetEncodedSize
            if (len <= recipient.m_currentMTU)
            {
                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 Encode(NetOutgoingMessage om)
 {
     om.Write(this.MessageTime);
     om.Write(this.Id);
     om.Write(this.OldPosition);
     om.Write(this.NewPosition);
 }
Exemplo n.º 7
0
 private void SerializeStream(NetOutgoingMessage netOutgoingMessage)
 {
     //send our position to the server
     //this should only be happening on an object that is ours
     _serializer.vector3 = transform.position;
     _serializer.OnSerialize(netOutgoingMessage);
 }
Exemplo n.º 8
0
 public void SendBlockSet(BlockTypes type,Vector3 pos)
 {
     _outmsg = _client.CreateMessage();
     _outmsg.Write((byte)PacketType.PlayerBlockSet);
     _outmsg.Write(pos);
     _outmsg.Write((byte)type);
 }
Exemplo n.º 9
0
 public NetOutgoingMessage Pack(NetOutgoingMessage msg)
 {
     msg.Write((byte)packetType);
     msg.Write(username);
     msg.Write(message);
     return msg;
 }
Exemplo n.º 10
0
        public void SendMessage(NetOutgoingMessage msg, IList<NetConnection> 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;
        }
Exemplo n.º 11
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");

            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"
            }
        }
Exemplo n.º 12
0
 public void SendMovementUpdate()
 {
     _outmsg = _client.CreateMessage();
     _outmsg.Write((byte)PacketType.PlayerMovementUpdate);
     _outmsg.Write(_pbag.Player.Position);
     _client.SendMessage(_outmsg, NetDeliveryMethod.ReliableOrdered);
 }
Exemplo n.º 13
0
        /// <summary>
        /// Converts the packet into an outgoing packet
        /// </summary>
        /// <returns>Returns the specified IPacket as a packet</returns>
        public virtual NetOutgoingMessage ToNetBuffer(ref NetOutgoingMessage netOutgoingMessage)
        {
            //TODO: Find a way to write the packet header given the HashCode of the class name...
            netOutgoingMessage.Write(GlobalPacketMap.PacketCache[GetType()]);

            return null;
        }
Exemplo n.º 14
0
 public void SendMessage(NetOutgoingMessage msg)
 {
     if (InnerClient.Status == NetPeerStatus.Running)
     {
         InnerClient.SendMessage(msg, NetDeliveryMethod.Unreliable);
     }
 }
 public static void Write(NetOutgoingMessage msg, Quaternion data)
 {
     msg.Write(data.x);
     msg.Write(data.y);
     msg.Write(data.z);
     msg.Write(data.w);
 }
Exemplo n.º 16
0
        internal void Write(NetOutgoingMessage Message)
        {
            ChunkCoords.Write(Message);

            Vector3i BlockCoords = ChunkCoords * Size;
            for (int x = 0; x < Size.X; x++) {
                for (int y = 0; y < Size.Y; y++) {
                    for (int z = 0; z < Size.Z; z++) {
                        Vector3i BlockAt = BlockCoords + new Vector3i(x, y, z);

                        if (!Game.World.MapGenerator.Exists(BlockAt / Sector.Size)) {
                            Game.World.MapGenerator.GenerateSector(BlockAt / Sector.Size);
                        }

                        Block Value = Realm.GetBlock(BlockAt);
                        if (Value != null) {
                            Message.Write(true);
                            Value.Write(Message);
                        } else {
                            Message.Write(false);
                        }
                    }
                }
            }
        }
Exemplo n.º 17
0
 public override void Write(NetOutgoingMessage msg)
 {
     msg.Write(Id);
     msg.Write(Cards.Count);
     foreach(string value in Cards)
         msg.Write(value);
 }
Exemplo n.º 18
0
        public override void WriteOutUpdateData(Lidgren.Network.NetOutgoingMessage om)
        {
            base.WriteOutUpdateData(om);


            om.Write(this.elapsedTime);
        }
Exemplo n.º 19
0
 public override void SendMessage(NetOutgoingMessage message)
 {
     for (int i = 0; i < connections.Count; ++i)
     {
         SendMessage(message, connections[i]);
     }
 }
Exemplo n.º 20
0
 public void Write(NetOutgoingMessage packet)
 {
     packet.Write(Slot);
     packet.Write((Byte)Team);
     packet.Write(Callsign);
     packet.Write(Tag);
 }
Exemplo n.º 21
0
 public void Encode(NetOutgoingMessage om)
 {
     om.Write(this.BlockID);
     om.Write(this.X);
     om.Write(this.Y);
     om.Write(this.Z);
 }
Exemplo n.º 22
0
 public void Encode(NetOutgoingMessage om)
 {
     om.Write((int) Value);
        om.Write(Text);
        om.Write(Row);
        om.Write(Col);
 }
Exemplo n.º 23
0
 /// <summary>
 /// write all the serializing objects to the stream
 /// </summary>
 /// <param name="msg"></param>
 /// <param name="towrite"></param>
 public static void WriteParams(ref NetOutgoingMessage msg, INetSerializable[] towrite)
 {
     foreach (var arg in towrite)
     {
         arg.OnSerialize(msg);
     }
 }
Exemplo n.º 24
0
        public static OutgoingMessage CreateOutgoingMessage(int opcode, byte[] data, NetOutgoingMessage packet)
        {
            OutgoingMessage com = CreateOutgoingMessage(opcode, data);
            com.EncodeTo(packet);

            return com;
        }
Exemplo n.º 25
0
 public void WriteType(NetOutgoingMessage Message, AttributeTypeID Type, object Data)
 {
     switch (Type) {
         case AttributeTypeID.Float:
             Message.Write((float)Data);
             break;
         case AttributeTypeID.Int:
             Message.Write((int)Data);
             break;
         case AttributeTypeID.List:
             Console.WriteLine("Engine unable to serialize list objects");
             break;
         case AttributeTypeID.Long:
             Message.Write((long)Data);
             break;
         case AttributeTypeID.Rectangle:
             Message.WriteRectangle((Rectangle)Data);
             break;
         case AttributeTypeID.String:
             Message.Write((string)Data);
             break;
         case AttributeTypeID.Vector2:
             Message.WriteVector2((Vector2)Data);
             break;
         case AttributeTypeID.Bool:
             Message.Write((bool)Data);
             break;
         default:
             Console.WriteLine("AttributeSystem Unrecognised Type In AttributeSystem Type: {0}", Type.ToString());
             break;
     }
 }
Exemplo n.º 26
0
 public void Encode(NetOutgoingMessage om)
 {
     om.Write(this.Id);
     om.Write(this.MessageTime);
     om.Write(this.Health);
     om.Write(this.MaxHealth);
 }
Exemplo n.º 27
0
 public void W(NetOutgoingMessage om)
 {
     om.Write(Uid);
     om.Write(X);
     om.Write(Y);
     om.Write(SpriteId);
 }
Exemplo n.º 28
0
 /// <summary>
 /// write to the message
 /// </summary>
 /// <param name="message">message to write to</param>
 public void OnSerialize(NetOutgoingMessage message)
 {
     message.Write(X);
     message.Write(Y);
     message.Write(Z);
     message.Write(W);
 }
Exemplo n.º 29
0
 public void SendPlayerInWorld()
 {
     _outmsg = _client.CreateMessage();
     _outmsg.Write((byte)PacketType.PlayerInWorld);
     _outmsg.Write(true);
     _client.SendMessage(_outmsg, NetDeliveryMethod.ReliableOrdered);
 }
Exemplo n.º 30
0
 public void Encode(NetOutgoingMessage om)
 {
     om.Write(Shots);
        om.Write(Hits);
        om.Write(Misses);
        om.Write(ShipsKilled);
 }
 public void Encode(NetOutgoingMessage om)
 {
     om.Write(this.MessageTime);
     om.Write(this.Id);
     om.Write(this.EquipmentPosition);
     om.Write(this.InventoryPosition);
 }
Exemplo n.º 32
0
        /// <summary>
        /// serialize to the message
        /// </summary>
        /// <param name="message"></param>
        public void OnSerialize(Lidgren.Network.NetOutgoingMessage message)
        {
            message.Write(dictionary.Count);

            foreach (var kvp in dictionary)
            {
                message.Write(kvp.Key);
                message.Write(kvp.Value);
            }
        }
Exemplo n.º 33
0
        /// <summary>
        /// Serialize the array to the message
        /// </summary>
        /// <param name="message"></param>
        public void OnSerialize(Lidgren.Network.NetOutgoingMessage message)
        {
            if (items == null || items.Length == 0)
            {
                return;
            }

            message.Write(items.Length);
            foreach (var item in items)
            {
                item.OnSerialize(message);
            }
        }
Exemplo n.º 34
0
 /// <summary>
 /// Approves this connection; sending a connection response to the remote host
 /// </summary>
 /// <param name="localHail">The local hail message that will be set as RemoteHailMessage on the remote host</param>
 public void Approve(NetOutgoingMessage localHail)
 {
     m_localHailMessage  = localHail;
     m_handshakeAttempts = 0;
     SendConnectResponse((float)NetTime.Now, false);
 }
Exemplo n.º 35
0
 public void Reset()
 {
     NumSent  = 0;
     LastSent = 0.0;
     Message  = null;
 }
Exemplo n.º 36
0
 public NetReason(NetOutgoingMessage message)
 {
     Message = message ?? throw new ArgumentNullException(nameof(message));
     Text    = null;
 }
Exemplo n.º 37
0
 /// <summary>
 /// Send a message to this remote connection
 /// </summary>
 /// <param name="msg">The message to send</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, NetDeliveryMethod method, int sequenceChannel)
 {
     return(m_peer.SendMessage(msg, this, method, sequenceChannel));
 }
Exemplo n.º 38
0
 /// <summary>
 /// Create a connection to a remote endpoint
 /// </summary>
 public NetConnection Connect(string host, int port, NetOutgoingMessage hailMessage)
 {
     return(Connect(new IPEndPoint(NetUtility.Resolve(host), port), hailMessage));
 }
Exemplo n.º 39
0
        /// <summary>
        /// Create a connection to a remote endpoint
        /// </summary>
        public virtual NetConnection Connect(NetEndPoint remoteEndPoint, NetOutgoingMessage hailMessage)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            lock (m_connections)
            {
                if (m_status == NetPeerStatus.NotRunning)
                {
                    throw new NetException("Must call Start() first");
                }

                if (m_connectionLookup.ContainsKey(remoteEndPoint))
                {
                    throw new NetException("Already connected to that endpoint!");
                }

                NetConnection hs;
                if (m_handshakes.TryGetValue(remoteEndPoint, out hs))
                {
                    // already trying to connect to that endpoint; make another try
                    switch (hs.m_status)
                    {
                    case NetConnectionStatus.InitiatedConnect:
                        // send another connect
                        hs.m_connectRequested = true;
                        break;

                    case NetConnectionStatus.RespondedConnect:
                        // send another response
                        hs.SendConnectResponse(NetTime.Now, false);
                        break;

                    case NetConnectionStatus.None:
                    case NetConnectionStatus.ReceivedInitiation:
                    case NetConnectionStatus.RespondedAwaitingApproval:
                    case NetConnectionStatus.Connected:
                    case NetConnectionStatus.Disconnecting:
                    case NetConnectionStatus.Disconnected:
                    default:
                        // weird
                        LogWarning("Weird situation; Connect() already in progress to remote endpoint; but hs status is " + hs.m_status);
                        break;
                    }
                    return(hs);
                }

                NetConnection conn = new NetConnection(this, remoteEndPoint);
                conn.m_status           = NetConnectionStatus.InitiatedConnect;
                conn.m_localHailMessage = hailMessage;

                // handle on network thread
                conn.m_connectRequested    = true;
                conn.m_connectionInitiator = true;

                m_handshakes.Add(remoteEndPoint, conn);

                return(conn);
            }
        }
Exemplo n.º 40
0
 public static void SendMessage(Lidgren.Network.NetOutgoingMessage msg, List <GamePlayer> players, Lidgren.Network.NetDeliveryMethod deliveryMethod = Lidgren.Network.NetDeliveryMethod.ReliableOrdered)
 {
     GameServer.UsingPeer.SendMessage(msg, players.Select(p => p.User.GetNetConnection()).ToList(), deliveryMethod, 0);
 }
Exemplo n.º 41
0
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double dnow = NetTime.Now;
            float  now  = (float)dnow;

            double delta = dnow - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS) || delta < 0.0)             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = dnow;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndPoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndPoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // update m_executeFlushSendQueue
                if (m_configuration.m_autoFlushSendQueue)
                {
                    m_executeFlushSendQueue = true;
                }

                // do connection heartbeats
                lock (m_connections)
                {
                    foreach (NetConnection conn in m_connections)
                    {
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.Remove(conn);
                            m_connectionLookup.Remove(conn.RemoteEndPoint);
                            break;                             // can't continue iteration here
                        }
                    }
                }
                m_executeFlushSendQueue = false;

                // send unsent unconnected messages
                NetTuple <IPEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;

                    bool connReset;
                    int  len = om.Encode(m_sendBuffer, 0, 0);
                    SendPacket(len, unsent.Item1, 1, out connReset);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }
                }
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(1000, SelectMode.SelectRead))             // wait up to 1 ms for data to arrive
            {
                return;
            }

            do
            {
                int bytesReceived = 0;
                try
                {
                    bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
                }
                catch (SocketException sx)
                {
                    if (sx.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                        // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                        // So, what to do?
                        LogWarning("ConnectionReset");
                        return;
                    }

                    LogWarning(sx.ToString());
                    return;
                }

                if (bytesReceived < NetConstants.HeaderByteSize)
                {
                    return;
                }

                IPEndPoint ipsender = (IPEndPoint)m_senderRemote;

                if (ipsender.Port == 1900)
                {
                    // UPnP response
                    try
                    {
                        string resp = System.Text.Encoding.ASCII.GetString(m_receiveBuffer, 0, bytesReceived);
                        if (resp.Contains("upnp:rootdevice"))
                        {
                            resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                            resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
                            m_upnp.ExtractServiceUrl(resp);
                            return;
                        }
                    }
                    catch { }
                }

                NetConnection sender = null;
                m_connectionLookup.TryGetValue(ipsender, out sender);

                double receiveTime = NetTime.Now;
                //
                // parse packet into messages
                //
                int numMessages = 0;
                int ptr         = 0;
                while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
                {
                    // decode header
                    //  8 bits - NetMessageType
                    //  1 bit  - Fragment?
                    // 15 bits - Sequence number
                    // 16 bits - Payload length in bits

                    numMessages++;

                    NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];

                    byte low  = m_receiveBuffer[ptr++];
                    byte high = m_receiveBuffer[ptr++];

                    bool   isFragment     = ((low & 1) == 1);
                    ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));

                    ushort payloadBitLength  = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
                    int    payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);

                    if (bytesReceived - ptr < payloadByteLength)
                    {
                        LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
                        return;
                    }

                    try
                    {
                        NetException.Assert(tp <NetMessageType.Unused1 || tp> NetMessageType.Unused29);

                        if (tp >= NetMessageType.LibraryError)
                        {
                            if (sender != null)
                            {
                                sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
                            }
                            else
                            {
                                ReceivedUnconnectedLibraryMessage(receiveTime, ipsender, tp, ptr, payloadByteLength);
                            }
                        }
                        else
                        {
                            if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
                            {
                                return;                                 // dropping unconnected message since it's not enabled
                            }
                            NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
                            msg.m_isFragment          = isFragment;
                            msg.m_receiveTime         = receiveTime;
                            msg.m_sequenceNumber      = sequenceNumber;
                            msg.m_receivedMessageType = tp;
                            msg.m_senderConnection    = sender;
                            msg.m_senderEndPoint      = ipsender;
                            msg.m_bitLength           = payloadBitLength;
                            Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
                            if (sender != null)
                            {
                                if (tp == NetMessageType.Unconnected)
                                {
                                    // We're connected; but we can still send unconnected messages to this peer
                                    msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                    ReleaseMessage(msg);
                                }
                                else
                                {
                                    // connected application (non-library) message
                                    sender.ReceivedMessage(msg);
                                }
                            }
                            else
                            {
                                // at this point we know the message type is enabled
                                // unconnected application (non-library) message
                                msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                ReleaseMessage(msg);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
                    }
                    ptr += payloadByteLength;
                }

                m_statistics.PacketReceived(bytesReceived, numMessages);
                if (sender != null)
                {
                    sender.m_statistics.PacketReceived(bytesReceived, numMessages);
                }
            } while (m_socket.Available > 0);
        }
Exemplo n.º 42
0
 /// <summary>
 /// Create a connection to a remote endpoint
 /// </summary>
 public NetConnection Connect(string host, int port, NetOutgoingMessage hailMessage)
 {
     return(Connect(GetNetEndPoint(host, port), hailMessage));
 }
        // remoteWindowStart is remote expected sequence number; everything below this has arrived properly
        // seqNr is the actual nr received
        internal override void ReceiveAcknowledge(double now, int seqNr)
        {
            // late (dupe), on time or early ack?
            int relate = NetUtility.RelativeSequenceNumber(seqNr, m_windowStart);

            if (relate < 0)
            {
                //m_connection.m_peer.LogDebug("Received late/dupe ack for #" + seqNr);
                return;                 // late/duplicate ack
            }

            if (relate == 0)
            {
                //m_connection.m_peer.LogDebug("Received right-on-time ack for #" + seqNr);

                // ack arrived right on time
                NetException.Assert(seqNr == m_windowStart);

                bool resetTimeout;
                m_receivedAcks[m_windowStart] = false;
                DestoreMessage(now, m_windowStart % m_windowSize, out resetTimeout);
                m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;

                // advance window if we already have early acks
                while (m_receivedAcks.Get(m_windowStart))
                {
                    //m_connection.m_peer.LogDebug("Using early ack for #" + m_windowStart + "...");
                    m_receivedAcks[m_windowStart] = false;
                    bool rt;
                    DestoreMessage(now, m_windowStart % m_windowSize, out rt);
                    resetTimeout |= rt;

                    NetException.Assert(m_storedMessages[m_windowStart % m_windowSize].Message == null);                     // should already be destored
                    m_windowStart = (m_windowStart + 1) % NetConstants.NumSequenceNumbers;
                    //m_connection.m_peer.LogDebug("Advancing window to #" + m_windowStart);
                }
                if (resetTimeout)
                {
                    m_connection.ResetTimeout(now);
                }
                return;
            }

            //
            // early ack... (if it has been sent!)
            //
            // If it has been sent either the m_windowStart message was lost
            // ... or the ack for that message was lost
            //

            //m_connection.m_peer.LogDebug("Received early ack for #" + seqNr);

            int sendRelate = NetUtility.RelativeSequenceNumber(seqNr, m_sendStart);

            if (sendRelate <= 0)
            {
                // yes, we've sent this message - it's an early (but valid) ack
                if (m_receivedAcks[seqNr])
                {
                    // we've already destored/been acked for this message
                }
                else
                {
                    m_receivedAcks[seqNr] = true;
                }
            }
            else if (sendRelate > 0)
            {
                // uh... we haven't sent this message yet? Weird, dupe or error...
                NetException.Assert(false, "Got ack for message not yet sent?");
                return;
            }

            // Ok, lets resend all missing acks
            int rnr = seqNr;

            do
            {
                rnr--;
                if (rnr < 0)
                {
                    rnr = NetConstants.NumSequenceNumbers - 1;
                }

                if (m_receivedAcks[rnr])
                {
                    // m_connection.m_peer.LogDebug("Not resending #" + rnr + " (since we got ack)");
                }
                else
                {
                    int slot = rnr % m_windowSize;
                    NetException.Assert(m_storedMessages[slot].Message != null);
                    if (m_storedMessages[slot].NumSent == 1)
                    {
                        // just sent once; resend immediately since we found gap in ack sequence
                        NetOutgoingMessage rmsg = m_storedMessages[slot].Message;
                        //m_connection.m_peer.LogVerbose("Resending #" + rnr + " (" + rmsg + ")");

                        if (now - m_storedMessages[slot].LastSent < (m_resendDelay * 0.35))
                        {
                            // already resent recently
                        }
                        else
                        {
                            m_storedMessages[slot].LastSent = now;
                            m_storedMessages[slot].NumSent++;
                            m_connection.m_statistics.MessageResent(MessageResendReason.HoleInSequence);
                            Interlocked.Increment(ref rmsg.m_recyclingCount);                             // increment this since it's being decremented in QueueSendMessage
                            m_connection.QueueSendMessage(rmsg, rnr);
                        }
                    }
                }
            } while (rnr != m_windowStart);
        }
Exemplo n.º 44
0
        private void ReceivedUnconnectedLibraryMessage(double now, IPEndPoint senderEndPoint, NetMessageType tp, int ptr, int payloadByteLength)
        {
            NetConnection shake;

            if (m_handshakes.TryGetValue(senderEndPoint, out shake))
            {
                shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;
            }

            //
            // Library message from a completely unknown sender; lets just accept Connect
            //
            switch (tp)
            {
            case NetMessageType.Discovery:
                HandleIncomingDiscoveryRequest(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.DiscoveryResponse:
                HandleIncomingDiscoveryResponse(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.NatIntroduction:
                HandleNatIntroduction(ptr);
                return;

            case NetMessageType.NatPunchMessage:
                HandleNatPunch(ptr, senderEndPoint);
                return;

            case NetMessageType.ConnectResponse:

                lock (m_handshakes)
                {
                    foreach (var hs in m_handshakes)
                    {
                        if (hs.Key.Address.Equals(senderEndPoint.Address))
                        {
                            if (hs.Value.m_connectionInitiator)
                            {
                                //
                                // We are currently trying to connection to XX.XX.XX.XX:Y
                                // ... but we just received a ConnectResponse from XX.XX.XX.XX:Z
                                // Lets just assume the router decided to use this port instead
                                //
                                var hsconn = hs.Value;
                                m_connectionLookup.Remove(hs.Key);
                                m_handshakes.Remove(hs.Key);

                                LogDebug("Detected host port change; rerouting connection to " + senderEndPoint);
                                hsconn.MutateEndPoint(senderEndPoint);

                                m_connectionLookup.Add(senderEndPoint, hsconn);
                                m_handshakes.Add(senderEndPoint, hsconn);

                                hsconn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                                return;
                            }
                        }
                    }
                }

                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;

            case NetMessageType.Connect:
                // proceed
                break;

            case NetMessageType.Disconnect:
                // this is probably ok
                LogVerbose("Received Disconnect from unconnected source: " + senderEndPoint);
                return;

            default:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;
            }

            // It's someone wanting to shake hands with us!

            int reservedSlots = m_handshakes.Count + m_connections.Count;

            if (reservedSlots >= m_configuration.m_maximumConnections)
            {
                // server full
                NetOutgoingMessage full = CreateMessage("Server full");
                full.m_messageType = NetMessageType.Disconnect;
                SendLibrary(full, senderEndPoint);
                return;
            }

            // Ok, start handshake!
            NetConnection conn = new NetConnection(this, senderEndPoint);

            conn.m_status = NetConnectionStatus.ReceivedInitiation;
            m_handshakes.Add(senderEndPoint, conn);
            conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);

            return;
        }
        // call this regularely
        internal override void SendQueuedMessages(double now)
        {
            //
            // resends
            //
            m_anyStoredResends = false;
            for (int i = 0; i < m_storedMessages.Length; i++)
            {
                var storedMsg         = m_storedMessages[i];
                NetOutgoingMessage om = storedMsg.Message;
                if (om == null)
                {
                    continue;
                }

                m_anyStoredResends = true;

                double t = storedMsg.LastSent;
                if (t > 0 && (now - t) > m_resendDelay)
                {
                    // deduce sequence number

                    /*
                     * int startSlot = m_windowStart % m_windowSize;
                     * int seqNr = m_windowStart;
                     * while (startSlot != i)
                     * {
                     *      startSlot--;
                     *      if (startSlot < 0)
                     *              startSlot = m_windowSize - 1;
                     *      seqNr--;
                     * }
                     */

                    //m_connection.m_peer.LogVerbose("Resending due to delay #" + m_storedMessages[i].SequenceNumber + " " + om.ToString());
                    m_connection.m_statistics.MessageResent(MessageResendReason.Delay);

                    Interlocked.Increment(ref om.m_recyclingCount);                     // increment this since it's being decremented in QueueSendMessage
                    m_connection.QueueSendMessage(om, storedMsg.SequenceNumber);

                    m_storedMessages[i].LastSent = now;
                    m_storedMessages[i].NumSent++;
                }
            }

            int num = GetAllowedSends();

            if (num < 1)
            {
                return;
            }

            // queued sends
            while (num > 0 && m_queuedSends.Count > 0)
            {
                NetOutgoingMessage om;
                if (m_queuedSends.TryDequeue(out om))
                {
                    ExecuteSend(now, om);
                }
                num--;
                NetException.Assert(num == GetAllowedSends());
            }
        }
Exemplo n.º 46
0
        // on user thread
        private NetSendResult SendFragmentedMessage(NetOutgoingMessage msg, IList <NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
        {
            // Note: this group id is PER SENDING/NetPeer; ie. same id is sent to all recipients;
            // this should be ok however; as long as recipients differentiate between same id but different sender
            int group = Interlocked.Increment(ref m_lastUsedFragmentGroup);

            if (group >= NetConstants.MaxFragmentationGroups)
            {
                // @TODO: not thread safe; but in practice probably not an issue
                m_lastUsedFragmentGroup = 1;
                group = 1;
            }
            msg.m_fragmentGroup = group;

            // do not send msg; but set fragmentgroup in case user tries to recycle it immediately

            // create fragmentation specifics
            int totalBytes = msg.LengthBytes;

            // determine minimum mtu for all recipients
            int mtu           = GetMTU(recipients);
            int bytesPerChunk = NetFragmentationHelper.GetBestChunkSize(group, totalBytes, mtu);

            int numChunks = totalBytes / bytesPerChunk;

            if (numChunks * bytesPerChunk < totalBytes)
            {
                numChunks++;
            }

            NetSendResult retval = NetSendResult.Sent;

            int bitsPerChunk = bytesPerChunk * 8;
            int bitsLeft     = msg.LengthBits;

            for (int i = 0; i < numChunks; i++)
            {
                NetOutgoingMessage chunk = CreateMessage(0);

                chunk.m_bitLength              = (bitsLeft > bitsPerChunk ? bitsPerChunk : bitsLeft);
                chunk.m_buf                    = msg.m_buf;
                chunk.m_fragmentGroup          = group;
                chunk.m_fragmentGroupTotalBits = totalBytes * 8;
                chunk.m_fragmentChunkByteSize  = bytesPerChunk;
                chunk.m_fragmentChunkNumber    = i;

                NetException.Assert(chunk.m_bitLength != 0);
                NetException.Assert(chunk.GetEncodedSize() < mtu);

                Interlocked.Add(ref chunk.m_recyclingCount, recipients.Count);

                foreach (NetConnection recipient in recipients)
                {
                    var res = recipient.EnqueueMessage(chunk, method, sequenceChannel);
                    if (res == NetSendResult.Dropped)
                    {
                        Interlocked.Decrement(ref chunk.m_recyclingCount);
                    }
                    if ((int)res > (int)retval)
                    {
                        retval = res;                         // return "worst" result
                    }
                }

                bitsLeft -= bitsPerChunk;
            }

            return(retval);
        }
Exemplo n.º 47
0
 /// <summary>
 /// Send a message to all connections
 /// </summary>
 /// <param name="msg">The message to send</param>
 /// <param name="method">How to deliver the message</param>
 public void SendToAll(NetOutgoingMessage msg, NetDeliveryMethod method)
 {
     SendMessage(msg, this.Connections, method, 0);
 }
Exemplo n.º 48
0
 /// <summary>
 /// Encrypt an outgoing message in place
 /// </summary>
 public abstract bool Encrypt(NetOutgoingMessage msg);
Exemplo n.º 49
0
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double now   = NetTime.Now;
            double delta = now - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS) || delta < 0.0)             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = now;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndPoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndPoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // update m_executeFlushSendQueue
                if (m_configuration.m_autoFlushSendQueue && m_needFlushSendQueue == true)
                {
                    m_executeFlushSendQueue = true;
                    m_needFlushSendQueue    = false;                  // a race condition to this variable will simply result in a single superfluous call to FlushSendQueue()
                }

                // do connection heartbeats
                lock (m_connections)
                {
                    for (int i = m_connections.Count - 1; i >= 0; i--)
                    {
                        var conn = m_connections[i];
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.RemoveAt(i);
                            m_connectionLookup.Remove(conn.RemoteEndPoint);
                        }
                    }
                }
                m_executeFlushSendQueue = false;

                // send unsent unconnected messages
                NetTuple <NetEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;

                    int len = om.Encode(m_sendBuffer, 0, 0);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }

                    bool connReset;
                    SendPacket(len, unsent.Item1, 1, out connReset);
                }
            }

            if (m_upnp != null)
            {
                m_upnp.CheckForDiscoveryTimeout();
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(1000, SelectMode.SelectRead))             // wait up to 1 ms for data to arrive
            {
                return;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	return;

            // update now
            now = NetTime.Now;

            do
            {
                int bytesReceived = 0;
                try
                {
                    bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
                }
                catch (SocketException sx)
                {
                    switch (sx.SocketErrorCode)
                    {
                    case SocketError.ConnectionReset:
                        // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                        // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                        // So, what to do?
                        LogWarning("ConnectionReset");
                        return;

                    case SocketError.NotConnected:
                        // socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
                        BindSocket(true);
                        return;

                    default:
                        LogWarning("Socket exception: " + sx.ToString());
                        return;
                    }
                }

                if (bytesReceived < NetConstants.HeaderByteSize)
                {
                    return;
                }

                //LogVerbose("Received " + bytesReceived + " bytes");

                var ipsender = (NetEndPoint)m_senderRemote;

                if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
                {
                    // is this an UPnP response?
                    string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived);
                    if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0"))
                    {
                        try
                        {
                            resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
                            resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
                            m_upnp.ExtractServiceUrl(resp);
                            return;
                        }
                        catch (Exception ex)
                        {
                            LogDebug("Failed to parse UPnP response: " + ex.ToString());

                            // don't try to parse this packet further
                            return;
                        }
                    }
                }

                NetConnection sender = null;
                m_connectionLookup.TryGetValue(ipsender, out sender);

                //
                // parse packet into messages
                //
                int numMessages  = 0;
                int numFragments = 0;
                int ptr          = 0;
                while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
                {
                    // decode header
                    //  8 bits - NetMessageType
                    //  1 bit  - Fragment?
                    // 15 bits - Sequence number
                    // 16 bits - Payload length in bits

                    numMessages++;

                    NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];

                    byte low  = m_receiveBuffer[ptr++];
                    byte high = m_receiveBuffer[ptr++];

                    bool   isFragment     = ((low & 1) == 1);
                    ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));

                    if (isFragment)
                    {
                        numFragments++;
                    }

                    ushort payloadBitLength  = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
                    int    payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);

                    if (bytesReceived - ptr < payloadByteLength)
                    {
                        LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
                        return;
                    }

                    if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29)
                    {
                        ThrowOrLog("Unexpected NetMessageType: " + tp);
                        return;
                    }

                    try
                    {
                        if (tp >= NetMessageType.LibraryError)
                        {
                            if (sender != null)
                            {
                                sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
                            }
                            else
                            {
                                ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength);
                            }
                        }
                        else
                        {
                            if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
                            {
                                return;                                 // dropping unconnected message since it's not enabled
                            }
                            NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
                            msg.m_isFragment          = isFragment;
                            msg.m_receiveTime         = now;
                            msg.m_sequenceNumber      = sequenceNumber;
                            msg.m_receivedMessageType = tp;
                            msg.m_senderConnection    = sender;
                            msg.m_senderEndPoint      = ipsender;
                            msg.m_bitLength           = payloadBitLength;

                            Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
                            if (sender != null)
                            {
                                if (tp == NetMessageType.Unconnected)
                                {
                                    // We're connected; but we can still send unconnected messages to this peer
                                    msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                    ReleaseMessage(msg);
                                }
                                else
                                {
                                    // connected application (non-library) message
                                    sender.ReceivedMessage(msg);
                                }
                            }
                            else
                            {
                                // at this point we know the message type is enabled
                                // unconnected application (non-library) message
                                msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
                                ReleaseMessage(msg);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
                    }
                    ptr += payloadByteLength;
                }

                m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
                if (sender != null)
                {
                    sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
                }
            } while (m_socket.Available > 0);
        }
Exemplo n.º 50
0
        /// <summary>
        /// Отправить сообщение для списка соединений.
        /// </summary>
        /// <param name="msg">Сообщение для отправки.</param>
        /// <param name="recipients">Список получателей для отправки.</param>
        /// <param name="method">Как доставить сообщение.</param>
        /// <param name="sequenceChannel">Последовательность каналов внутри метода доставки.</param>
        public void SendMessage(NetOutgoingMessage msg, IList <NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }
            if (recipients == null)
            {
                if (msg.m_isSent == false)
                {
                    Recycle(msg);
                }
                throw new ArgumentNullException("recipients");
            }
            if (recipients.Count < 1)
            {
                if (msg.m_isSent == false)
                {
                    Recycle(msg);
                }
                throw new NetException("recipients must contain at least one item");
            }
            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");
            }
            msg.m_isSent = true;

            int mtu = GetMTU(recipients);

            int len = msg.GetEncodedSize();

            if (len <= mtu)
            {
                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;
        }
Exemplo n.º 51
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>
 public NetSendResult SendMessage(NetOutgoingMessage msg, NetConnection recipient, NetDeliveryMethod method)
 {
     return(SendMessage(msg, recipient, method, 0));
 }
 internal abstract NetSendResult Enqueue(NetOutgoingMessage message);
Exemplo n.º 53
0
 public static void SendMessageToAll(Lidgren.Network.NetOutgoingMessage msg, Lidgren.Network.NetDeliveryMethod deliveryMethod = Lidgren.Network.NetDeliveryMethod.ReliableOrdered)
 {
     GameServer.UsingPeer.SendMessage(msg, GameServer.GetUserConnections(), deliveryMethod, 0);
 }
Exemplo n.º 54
0
        static void Main(string[] args)
        {
            var config = new NetPeerConfiguration("ConquerLeague")
            {
                Port = 47410
            };

            config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            server = new NetServer(config);
            server.Start();

            SessionManager sessionManager = new SessionManager();

            while (true)
            {
                NetIncomingMessage message;
                while ((message = server.ReadMessage()) != null)
                {
                    switch (message.MessageType)
                    {
                    case NetIncomingMessageType.DiscoveryRequest:
                        NetOutgoingMessage response = server.CreateMessage();           // Create a response and write some example data to it
                        response.Write("ConquerLeagueServer");
                        server.SendDiscoveryResponse(response, message.SenderEndPoint); // Send the response to the sender of the request
                        break;

                    case NetIncomingMessageType.Data:
                        var dataLength = message.ReadInt32();
                        var data       = message.ReadBytes(dataLength);
                        sessionManager.ForwardMessageToSession(message.SenderConnection, dataLength, data);
                        break;

                    case NetIncomingMessageType.StatusChanged:
                        Console.WriteLine(message.SenderConnection.Status);
                        switch (message.SenderConnection.Status)
                        {
                        case NetConnectionStatus.Connected:
                            Console.WriteLine("Client " + message.SenderConnection.RemoteEndPoint.ToString() + " connected!");
                            sessionManager.AddPlayerToMatchmaking(message.SenderConnection);
                            break;

                        case NetConnectionStatus.RespondedConnect:
                            Console.WriteLine(message.SenderConnection.Status.ToString());
                            break;

                        default:
                            Console.WriteLine("Unhandled status change with type: " + message.SenderConnection.Status.ToString());
                            break;
                        }

                        break;

                    case NetIncomingMessageType.ConnectionApproval:
                        message.SenderConnection.Approve();
                        break;

                    case NetIncomingMessageType.DebugMessage:
                        Console.WriteLine(message.ReadString());
                        break;

                    case NetIncomingMessageType.WarningMessage:
                        Console.WriteLine("Warning: " + message.ReadString());
                        break;

                    default:
                        Console.WriteLine("unhandled message with type: " + message.MessageType);
                        break;
                    }

                    server.Recycle(message);
                }
            }
        }
Exemplo n.º 55
0
        private void ReceivedUnconnectedLibraryMessage(double now, NetEndPoint senderEndPoint, long connectionId, NetMessageType tp, int ptr, int payloadByteLength)
        {
            NetConnection shake;

            if (m_handshakes.TryGetValue(connectionId, out shake))
            {
                shake.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;
            }

            //
            // Library message from a completely unknown sender; lets just accept Connect
            //
            switch (tp)
            {
            case NetMessageType.Discovery:
                HandleIncomingDiscoveryRequest(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.DiscoveryResponse:
                HandleIncomingDiscoveryResponse(now, senderEndPoint, ptr, payloadByteLength);
                return;

            case NetMessageType.NatIntroduction:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatIntroduction(ptr);
                }
                return;

            case NetMessageType.NatPunchMessage:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunch(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.NatIntroductionConfirmRequest:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunchConfirmRequest(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.NatIntroductionConfirmed:
                if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
                {
                    HandleNatPunchConfirmed(ptr, senderEndPoint);
                }
                return;

            case NetMessageType.ConnectResponse:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;

            case NetMessageType.Connect:
                if (m_configuration.AcceptIncomingConnections == false)
                {
                    LogWarning("Received Connect, but we're not accepting incoming connections!");
                    return;
                }
                // handle connect
                // It's someone wanting to shake hands with us!

                int reservedSlots = m_handshakes.Count + m_connections.Count;
                if (reservedSlots >= m_configuration.m_maximumConnections)
                {
                    // server full
                    NetOutgoingMessage full = CreateMessage("Server full");
                    full.m_messageType = NetMessageType.Disconnect;
                    SendLibrary(connectionId, full, senderEndPoint);
                    return;
                }

                if (connectionId == 0 || m_handshakes.ContainsKey(connectionId) || m_connectionLookup.ContainsKey(connectionId))
                {
                    // duplicate connection id
                    NetOutgoingMessage full = CreateMessage("Duplicate connection id");
                    full.m_messageType = NetMessageType.Disconnect;
                    SendLibrary(connectionId, full, senderEndPoint);
                    return;
                }

                // Ok, start handshake!
                NetConnection conn = new NetConnection(this, senderEndPoint, connectionId);
                conn.m_status = NetConnectionStatus.ReceivedInitiation;
                m_handshakes.Add(connectionId, conn);
                conn.ReceivedHandshake(now, tp, ptr, payloadByteLength);
                return;

            case NetMessageType.Disconnect:
                // this is probably ok
                LogVerbose("Received Disconnect from unconnected source: " + senderEndPoint);
                return;

            default:
                LogWarning("Received unhandled library message " + tp + " from " + senderEndPoint);
                return;
            }
        }
Exemplo n.º 56
0
 /// <summary>
 /// Create a connection to a remote endpoint.
 /// </summary>
 public NetConnection Connect(ReadOnlySpan <char> host, int port, NetOutgoingMessage hailMessage)
 {
     return(Connect(new IPEndPoint(NetUtility.Resolve(host), port), hailMessage));
 }
        private void Heartbeat()
        {
            VerifyNetworkThread();

            double now   = NetTime.Now;
            double delta = now - m_lastHeartbeat;

            int maxCHBpS = 1250 - m_connections.Count;

            if (maxCHBpS < 250)
            {
                maxCHBpS = 250;
            }
            if (delta > (1.0 / (double)maxCHBpS) || delta < 0.0)             // max connection heartbeats/second max
            {
                m_frameCounter++;
                m_lastHeartbeat = now;

                // do handshake heartbeats
                if ((m_frameCounter % 3) == 0)
                {
                    foreach (var kvp in m_handshakes)
                    {
                        NetConnection conn = kvp.Value as NetConnection;
#if DEBUG
                        // sanity check
                        if (kvp.Key != kvp.Key)
                        {
                            LogWarning("Sanity fail! Connection in handshake list under wrong key!");
                        }
#endif
                        conn.UnconnectedHeartbeat(now);
                        if (conn.m_status == NetConnectionStatus.Connected || conn.m_status == NetConnectionStatus.Disconnected)
                        {
#if DEBUG
                            // sanity check
                            if (conn.m_status == NetConnectionStatus.Disconnected && m_handshakes.ContainsKey(conn.RemoteEndPoint))
                            {
                                LogWarning("Sanity fail! Handshakes list contained disconnected connection!");
                                m_handshakes.Remove(conn.RemoteEndPoint);
                            }
#endif
                            break;                             // collection has been modified
                        }
                    }
                }

#if DEBUG
                SendDelayedPackets();
#endif

                // update m_executeFlushSendQueue
                if (m_configuration.m_autoFlushSendQueue && m_needFlushSendQueue == true)
                {
                    m_executeFlushSendQueue = true;
                    m_needFlushSendQueue    = false;                  // a race condition to this variable will simply result in a single superfluous call to FlushSendQueue()
                }

                // do connection heartbeats
                lock (m_connections)
                {
                    for (int i = m_connections.Count - 1; i >= 0; i--)
                    {
                        var conn = m_connections[i];
                        conn.Heartbeat(now, m_frameCounter);
                        if (conn.m_status == NetConnectionStatus.Disconnected)
                        {
                            //
                            // remove connection
                            //
                            m_connections.RemoveAt(i);
                            m_connectionLookup.Remove(conn.RemoteEndPoint);
                        }
                    }
                }
                m_executeFlushSendQueue = false;

                // send unsent unconnected messages
                NetTuple <NetEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;

                    int len = om.Encode(m_sendBuffer, 0, 0);

                    Interlocked.Decrement(ref om.m_recyclingCount);
                    if (om.m_recyclingCount <= 0)
                    {
                        Recycle(om);
                    }

                    bool connReset;
                    SendPacket(len, unsent.Item1, 1, out connReset);
                }
            }

            if (m_upnp != null)
            {
                m_upnp.CheckForDiscoveryTimeout();
            }

            //
            // read from socket
            //
            if (m_socket == null)
            {
                return;
            }

            if (!m_socket.Poll(1000, SelectMode.SelectRead))             // wait up to 1 ms for data to arrive
            {
                return;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	return;

            // update now
            now = NetTime.Now;

            try
            {
                do
                {
                    ReceiveSocketData(now);
                } while (m_socket.Available > 0);
            }
            catch (SocketException sx)
            {
                switch (sx.SocketErrorCode)
                {
                case SocketError.ConnectionReset:
                    // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
                    // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
                    // So, what to do?
                    LogWarning("ConnectionReset");
                    return;

                case SocketError.NotConnected:
                    // socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
                    BindSocket(true);
                    return;

                default:
                    LogWarning("Socket exception: " + sx.ToString());
                    return;
                }
            }
        }