internal override void ReceiveMessage(NetIncomingMessage msg)
		{
			// ack no matter what
			m_connection.QueueAck(msg.m_receivedMessageType, msg.m_sequenceNumber);

			m_peer.ReleaseMessage(msg);
		}
        public override void OnCalled(Message msg, NetIncomingMessage netMsg = null)
        {
            MessagePlayerHookReleased message = msg as MessagePlayerHookReleased;

            var player = MultiplayerManager.instance.m_players.FirstOrDefault(x => x.ID == message.playerId);
            player.PlayerGameObject.GetComponent<PlayerRemote>().OnPlayerHookReleased();
        }
Exemple #3
0
        //This is called very first when a client connects to the server, but before OnPlayerConnected
        private static void ApproveConnection(NetIncomingMessage netIncomingMessage)
        {
            netIncomingMessage.SenderConnection.Approve();

            //Other things you can do: spawn a separate thread that eventually decides if a connection should be approved or not,
            //then approve the connection in the gameupdate loop
        }
Exemple #4
0
 public Rock(NetIncomingMessage Message)
     : base()
 {
     Texture = GameClient.ContentManager.Load<Texture2D>("RockFull");
     ID = Message.ReadInt64();
     BoundingBox = Message.ReadRectangle();
 }
 public void Decode(NetIncomingMessage im)
 {
     this.MessageTime = im.ReadDouble();
     this.Id = im.ReadInt32();
     this.OldPosition = im.ReadInt32();
     this.NewPosition = im.ReadInt32();
 }
Exemple #6
0
 public void Decode(NetIncomingMessage im)
 {
     this.BlockID = im.ReadByte();
     this.X = im.ReadInt16();
     this.Y = im.ReadInt16();
     this.Z = im.ReadByte();
 }
Exemple #7
0
 public static Packet decode(ref NetIncomingMessage msg)
 {
     Packet p = new Packet (0);
     p.type = msg.ReadByte ();
     p.clientId = msg.ReadInt32 ();
     return p;
 }
 public override void Init(NetIncomingMessage msg, params float[] p_afInitFloats)
 {
     this.rcShadow = new StaticRenderComponent(CAS.RegionContent.Load<Texture2D>("Sprites/Monster/Winterland/Frostling Scoundrel/Shadow"), this.xTransform);
     Program.game.xRenderMaster.RegisterShadowLayer(this.rcShadow, 60);
     this.fVelocity = p_afInitFloats[0];
     this.v2Direction = new Vector2(p_afInitFloats[1], p_afInitFloats[2]);
 }
 public ClientDisconnectedTransferableData(NetIncomingMessage message)
 {
     SessionID = message.ReadInt64();
     ID = message.ReadInt32();
     IsValid = message.ReadBoolean();
     PlayerIndex = message.ReadInt16();
 }
 public void Run(ManagerLogger managerLogger, Server server, NetIncomingMessage inc, PlayerAndConnection playerAndConnection, GameRoom gameRoom)
 {
     managerLogger.AddLogMessage("server", "New connection...");
     var data = inc.ReadByte();
     if (data == (byte)PacketType.Login)
     {
         managerLogger.AddLogMessage("server", "..connection accpeted.");
         playerAndConnection = CreatePlayer(inc, gameRoom.Players, gameRoom.ManagerCamera);
         inc.SenderConnection.Approve();
         var outmsg = server.NetServer.CreateMessage();
         outmsg.Write((byte)PacketType.Login);
         outmsg.Write(true);
         outmsg.Write(gameRoom.Players.Count);
         for (int n = 0; n < gameRoom.Players.Count; n++)
         {
             var p = gameRoom.Players[n];
             outmsg.Write(p.Player.Username);
             outmsg.WriteAllProperties(p.Player.Position);
         }
         server.NetServer.SendMessage(outmsg, inc.SenderConnection, NetDeliveryMethod.ReliableOrdered, 0);
         var command = new PlayerPositionCommand();
         command.Run(managerLogger, server,inc,playerAndConnection,gameRoom);
         server.SendNewPlayerEvent(playerAndConnection.Player.Username, gameRoom.GameRoomId);
     }
     else
     {
         inc.SenderConnection.Deny("Didn't send correct information.");
     }
 }
		internal void ReleaseMessage(NetIncomingMessage msg)
		{
			NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);

			if (msg.m_isFragment)
			{
				HandleReleasedFragment(msg);
				return;
			}

			m_releasedIncomingMessages.Enqueue(msg);

			if (m_messageReceivedEvent != null)
				m_messageReceivedEvent.Set();

			if (m_receiveCallbacks != null)
			{
				foreach (var tuple in m_receiveCallbacks)
				{
					try
					{
						tuple.Item1.Post(tuple.Item2, this);
					}
					catch (Exception ex)
					{
						LogWarning("Receive callback exception:" + ex);
					}
				}
			}
		}
Exemple #12
0
 public void Decode(NetIncomingMessage im)
 {
     this.ID = im.ReadByte();
     this.Message = im.ReadString();
     if (Message.Length > Networking.Messages.ChatMessage.MaxLength)
         Message= Message.Truncate(Networking.Messages.ChatMessage.MaxLength);
 }
Exemple #13
0
 // Constructor
 public ConnectionRequestEventArgs(NetIncomingMessage msg, string note, string username, string password)
 {
     this.msg = msg;
     this.username = username;
     this.password = password;
     this.note = note;
 }
 public override void ReadPayload(NetIncomingMessage message)
 {
     base.ReadPayload(message);
     Image = message.ReadBytes(message.ReadInt32());
     Number = message.ReadUInt32();
     SendIndex = message.ReadInt32();
 }
 public static new Packet FromNetBuffer(NetIncomingMessage incomingMessage)
 {
     var id = incomingMessage.ReadInt32();
     var type = (ContentType)incomingMessage.ReadByte();
     var packet = new ContentReleasePacket(type, id);
     return packet;
 }
Exemple #16
0
        public static void ToOtherPlayers(NetIncomingMessage im, OtherPlayer[] d)
        {
            bool alive = im.ReadBoolean();
            float xp = im.ReadFloat();
            float yp = im.ReadFloat();
            float zp = im.ReadFloat();
            Int32 id = im.ReadInt32();
            float xr = im.ReadFloat();
            float yr = im.ReadFloat();
            Int16 model = im.ReadInt16();
            if (d[id] == null)
            {
                d[id] = new OtherPlayer(xp, yp, zp, id, model, xr, yr);
            }
            d[id].model = model;
            d[id].xr = xr;
            d[id].yr = yr;

            if (!alive)
            {
                d[id].ChangeLifeStatus(false);
            }
            d[id].position = new Vector3(xp, yp, zp);
            d[id].boundingSphere.Center = new Vector3(d[id].position.X, d[id].position.Y + Constants.HEADMAX/2, d[id].position.Z);
        }
 public override void Read(NetIncomingMessage msg)
 {
     Id = msg.ReadUInt16();
     int count = msg.ReadInt32();
     for(int i = 0; i < count; ++i)
         Cards.Add(msg.ReadString());
 }
 public void Decode(NetIncomingMessage im)
 {
     this.MessageTime = im.ReadDouble();
     this.Id = im.ReadInt32();
     this.EquipmentPosition = im.ReadInt32();
     this.InventoryPosition = im.ReadInt32();
 }
		internal override void ReceiveMessage(NetIncomingMessage message)
		{
			int relate = NetUtility.RelativeSequenceNumber(message.m_sequenceNumber, m_windowStart);

			// ack no matter what
			m_connection.QueueAck(message.m_receivedMessageType, message.m_sequenceNumber);

			if (relate == 0)
			{
				// Log("Received message #" + message.SequenceNumber + " right on time");

				//
				// excellent, right on time
				//
				//m_peer.LogVerbose("Received RIGHT-ON-TIME " + message);

				AdvanceWindow();
				m_peer.ReleaseMessage(message);

				// release withheld messages
				int nextSeqNr = (message.m_sequenceNumber + 1) % NetConstants.NumSequenceNumbers;

				while (m_earlyReceived[nextSeqNr % m_windowSize])
				{
					message = m_withheldMessages[nextSeqNr % m_windowSize];
					NetException.Assert(message != null);

					// remove it from withheld messages
					m_withheldMessages[nextSeqNr % m_windowSize] = null;

					m_peer.LogVerbose("Releasing withheld message #" + message);

					m_peer.ReleaseMessage(message);

					AdvanceWindow();
					nextSeqNr++;
				}

				return;
			}

			if (relate < 0)
			{
				m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING DUPLICATE");
				// duplicate
				return;
			}

			// relate > 0 = early message
			if (relate > m_windowSize)
			{
				// too early message!
				m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart);
				return;
			}

			m_earlyReceived.Set(message.m_sequenceNumber % m_windowSize, true);
			m_peer.LogVerbose("Received " + message + " WITHHOLDING, waiting for " + m_windowStart);
			m_withheldMessages[message.m_sequenceNumber % m_windowSize] = message;
		}
 public void Decode(NetIncomingMessage im)
 {
     Shots = im.ReadInt32();
        Hits = im.ReadInt32();
        Misses = im.ReadInt32();
        ShipsKilled = im.ReadInt32();
 }
		internal override void ReceiveMessage(NetIncomingMessage msg)
		{
			if (m_doFlowControl)
				m_connection.QueueAck(msg.m_receivedMessageType, msg.m_sequenceNumber);

			m_peer.ReleaseMessage(msg);
		}
Exemple #22
0
 /// <summary>
 /// read the message
 /// </summary>
 /// <param name="message">message to read from</param>
 public void OnDeserialize(NetIncomingMessage message)
 {
     X = message.ReadFloat();
     Y = message.ReadFloat();
     Z = message.ReadFloat();
     W = message.ReadFloat();
 }
		private void InitializeNetwork()
		{
			lock (m_initializeLock)
			{
				m_configuration.Lock();

				if (m_status == NetPeerStatus.Running)
					return;

				InitializePools();

				m_releasedIncomingMessages.Clear();
				m_unsentUnconnectedMessages.Clear();
				m_handshakes.Clear();

				// bind to socket
				IPEndPoint iep = null;

				iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port);
				EndPoint ep = (EndPoint)iep;

				m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
				m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize;
				m_socket.SendBufferSize = m_configuration.SendBufferSize;
				m_socket.Blocking = false;
				m_socket.Bind(ep);

				IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint;
				LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound);
				m_listenPort = boundEp.Port;

				m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize];
				m_sendBuffer = new byte[m_configuration.SendBufferSize];
				m_readHelperMessage = new NetIncomingMessage(NetIncomingMessageType.Error);
				m_readHelperMessage.m_data = m_receiveBuffer;

				byte[] macBytes = new byte[8];
				NetRandom.Instance.NextBytes(macBytes);

#if IS_MAC_AVAILABLE
			System.Net.NetworkInformation.PhysicalAddress pa = NetUtility.GetMacAddress();
			if (pa != null)
			{
				macBytes = pa.GetAddressBytes();
				LogVerbose("Mac address is " + NetUtility.ToHexString(macBytes));
			}
			else
			{
				LogWarning("Failed to get Mac address");
			}
#endif
				byte[] epBytes = BitConverter.GetBytes(boundEp.GetHashCode());
				byte[] combined = new byte[epBytes.Length + macBytes.Length];
				Array.Copy(epBytes, 0, combined, 0, epBytes.Length);
				Array.Copy(macBytes, 0, combined, epBytes.Length, macBytes.Length);
				m_uniqueIdentifier = BitConverter.ToInt64(SHA1.Create().ComputeHash(combined), 0);

				m_status = NetPeerStatus.Running;
			}
		}
        /// <summary>
        /// Alerts the packet service about possible packets that need processing
        /// </summary>
        /// <param name="packetID">The type of packet that is expected</param>
        /// <param name="incomingMessage">The data contained within the packet</param>
        public void ProcessPacket(int packetID, NetIncomingMessage incomingMessage)
        {
            //TODO: Type.InvokeMember(...) is an expensive call. Do monitor this if at all possible.
            //It'll likely be fine, and it adds great design addition. No nasty switches. Send and forget.

            if (!_cache.ContainsKey(packetID))
                throw new Exception("The given packet type is missing! Was it marked properly and given an attribute?");

            //Take our incoming message and type
            var type = _cache[packetID];

            var val = new object[1];
            val[0] = incomingMessage;

            //Take the given type in the context and create our packet from it

            // Try and fetch the packet, otherwise abort it

            var returnValue =
                (Packet)type.InvokeMember("FromNetBuffer", BindingFlags.InvokeMethod, null, type, val);
            returnValue.Sender = incomingMessage.SenderConnection;

            //Automated packet service
            _packetService.ProcessReceivedPacket(returnValue);

            //Logger.Instance.Log(Level.Warn, "A packet that had a malformed payload was attempt to be sent. Ignoring for now.");
        }
 public void Decode(NetIncomingMessage im)
 {
     this.Value = (ResultOfAttack) im.ReadInt32();
        this.Text = im.ReadString();
        this.Row = im.ReadInt32();
        this.Col = im.ReadInt32();
 }
Exemple #26
0
 private void ReadData(AttributeTypeID Type, NetIncomingMessage Message)
 {
     switch(Type) {
         case AttributeTypeID.Float:
             Data = Message.ReadFloat();
             break;
         case AttributeTypeID.Int:
             Data = Message.ReadInt32();
             break;
         case AttributeTypeID.List:
             Console.WriteLine("AttributeSystem: List<> Type not supported on network sync");
             break;
         case AttributeTypeID.Long:
             Data = Message.ReadInt64();
             break;
         case AttributeTypeID.Rectangle:
             Data = Message.ReadRectangle();
             break;
         case AttributeTypeID.String:
             Data = Message.ReadString();
             break;
         case AttributeTypeID.Vector2:
             Data = Message.ReadVector2();
             break;
         case AttributeTypeID.Bool:
             Data = Message.ReadBoolean();
             break;
         default:
             Console.WriteLine("Invalid Attribute Type: {0}", Type.ToString());
             break;
     }
 }
Exemple #27
0
        /// <summary>
        /// Writes a <see cref="NetIncomingMessage"/> buffer into the BitStream.
        /// </summary>
        /// <param name="source">The <see cref="NetIncomingMessage"/> who's contents will be copied to this BitStream.</param>
        public void Write(NetIncomingMessage source)
        {
#if DEBUG
            var startBSPos = PositionBits;
            var startMsgPos = (int)source.Position;
#endif

            // Read full 32-bit integers
            while (source.LengthBits - source.Position >= _bitsInt)
            {
                var v = source.ReadUInt32();
                Write(v);
            }

            // Read full 8-bit integers
            while (source.LengthBits - source.Position >= _bitsByte)
            {
                var v = source.ReadByte();
                Write(v);
            }

            // Read the remaining bits
            while (source.LengthBits > source.Position)
            {
                var v = source.ReadBoolean();
                Write(v);
            }

            Debug.Assert(source.Position == source.LengthBits);

#if DEBUG
            Debug.Assert(PositionBits - startBSPos == source.LengthBits - startMsgPos);
#endif
        }
 public void Decode(NetIncomingMessage im)
 {
     this.Username = im.ReadString();
     this.ID = im.ReadByte();
     this.Me = im.ReadBoolean();
     this.Color = new Color(im.ReadByte(), im.ReadByte(), im.ReadByte());
 }
 public override void ReadPayload(NetIncomingMessage message)
 {
     base.ReadPayload(message);
     Region = new Rectangle(message.ReadInt32(), message.ReadInt32(), message.ReadInt32(), message.ReadInt32());
     Number = message.ReadUInt32();
     FinalLength = message.ReadInt32();
 }
 public override void Init(NetIncomingMessage msg, params float[] p_afInitFloats)
 {
     this.fStartRotation = p_afInitFloats[2];
     this.localRand = new Random((int)p_afInitFloats[3]);
     this.iStartup = (int)p_afInitFloats[4];
     this.SetOwner(new Vector2(p_afInitFloats[0], p_afInitFloats[1]));
 }
Exemple #31
0
        public override void ReadInUpdateData(Lidgren.Network.NetIncomingMessage im)
        {
            base.ReadInUpdateData(im);

            elapsedTime = im.ReadFloat();

            updateMenu();
        }
Exemple #32
0
        /// <summary>
        /// Deserialize the array from the message
        /// </summary>
        /// <param name="message"></param>
        public void OnDeserialize(Lidgren.Network.NetIncomingMessage message)
        {
            var length = message.ReadInt32();

            items = new T[length];

            for (int i = 0; i < length; i++)
            {
                var t = new T();
                t.OnDeserialize(message);
                items[i] = t;
            }
        }
Exemple #33
0
        /// <summary>
        /// deserialize from the message
        /// </summary>
        /// <param name="message"></param>
        public void OnDeserialize(Lidgren.Network.NetIncomingMessage message)
        {
            var size = message.ReadInt32();

            dictionary = new Dictionary <T, U>(size);

            for (int i = 0; i < size; ++i)
            {
                var key   = message.Read <T>();
                var value = message.Read <U>();

                dictionary[key] = value;
            }
        }
Exemple #34
0
        private void InitializeNetwork()
        {
            lock (m_initializeLock)
            {
                m_configuration.Lock();

                if (m_status == NetPeerStatus.Running)
                {
                    return;
                }

                if (m_configuration.m_enableUPnP)
                {
                    m_upnp = new NetUPnP(this);
                }

                InitializePools();

                m_releasedIncomingMessages.Clear();
                m_unsentUnconnectedMessages.Clear();
                m_handshakes.Clear();

                // bind to socket
                IPEndPoint iep = null;

                iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port);
                EndPoint ep = (EndPoint)iep;

                m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize;
                m_socket.SendBufferSize    = m_configuration.SendBufferSize;
                m_socket.Blocking          = false;
                m_socket.Bind(ep);

                var platform = Environment.OSVersion.Platform;
                if (platform != PlatformID.MacOSX && platform != PlatformID.Unix)
                {
                    try
                    {
                        const uint IOC_IN            = 0x80000000;
                        const uint IOC_VENDOR        = 0x18000000;
                        uint       SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
                        m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
                    }
                    catch
                    {
                        // ignore; SIO_UDP_CONNRESET not supported on this platform
                    }
                }

                IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint;
                LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound);
                m_listenPort = boundEp.Port;

                m_receiveBuffer            = new byte[m_configuration.ReceiveBufferSize];
                m_sendBuffer               = new byte[m_configuration.SendBufferSize];
                m_readHelperMessage        = new NetIncomingMessage(NetIncomingMessageType.Error);
                m_readHelperMessage.m_data = m_receiveBuffer;

                byte[] macBytes = new byte[8];
                NetRandom.Instance.NextBytes(macBytes);

#if IS_MAC_AVAILABLE
                try
                {
                    System.Net.NetworkInformation.PhysicalAddress pa = NetUtility.GetMacAddress();
                    if (pa != null)
                    {
                        macBytes = pa.GetAddressBytes();
                        LogVerbose("Mac address is " + NetUtility.ToHexString(macBytes));
                    }
                    else
                    {
                        LogWarning("Failed to get Mac address");
                    }
                }
                catch (NotSupportedException)
                {
                    // not supported; lets just keep the random bytes set above
                }
#endif
                byte[] epBytes  = BitConverter.GetBytes(boundEp.GetHashCode());
                byte[] combined = new byte[epBytes.Length + macBytes.Length];
                Array.Copy(epBytes, 0, combined, 0, epBytes.Length);
                Array.Copy(macBytes, 0, combined, epBytes.Length, macBytes.Length);
                m_uniqueIdentifier = BitConverter.ToInt64(SHA1.Create().ComputeHash(combined), 0);

                m_status = NetPeerStatus.Running;
            }
        }
Exemple #35
0
        private void ReceiveSocketData(double now)
        {
            int bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);

            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);
            }
        }
Exemple #36
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))             // 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

                // 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
                        }
                    }
                }

                // send unsent unconnected messages
                NetTuple <IPEndPoint, NetOutgoingMessage> unsent;
                while (m_unsentUnconnectedMessages.TryDequeue(out unsent))
                {
                    NetOutgoingMessage om = unsent.Item2;
#if DEBUG
                    if (om.m_messageType == NetMessageType.NatPunchMessage)
                    {
                        LogDebug("Sending Nat Punch Message to " + unsent.Item1.ToString());
                    }
#endif

                    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;
            }

            //if (m_socket == null || m_socket.Available < 1)
            //	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?
                        return;
                    }

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

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

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

                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);
        }
 /// <summary>
 /// Reads a pending message from any connection, if any.
 /// Returns true if message was read, otherwise false.
 /// </summary>
 /// <returns>True, if message was read.</returns>
 public bool ReadMessage(out NetIncomingMessage message)
 {
     message = ReadMessage();
     return(message != null);
 }
        private void InitializeNetwork()
        {
            lock (m_initializeLock)
            {
                m_configuration.Lock();

                if (m_status == NetPeerStatus.Running)
                {
                    return;
                }

                if (m_configuration.m_enableUPnP)
                {
                    m_upnp = new NetUPnP(this);
                }

                InitializePools();

                m_releasedIncomingMessages.Clear();
                m_unsentUnconnectedMessages.Clear();
                m_handshakes.Clear();

                // bind to socket
                BindSocket(false);

                m_receiveBuffer            = new byte[m_configuration.ReceiveBufferSize];
                m_sendBuffer               = new byte[m_configuration.SendBufferSize];
                m_readHelperMessage        = new NetIncomingMessage(NetIncomingMessageType.Error);
                m_readHelperMessage.m_data = m_receiveBuffer;

                byte[] macBytes = new byte[8];
                MWCRandom.Instance.NextBytes(macBytes);

#if IS_MAC_AVAILABLE
                try
                {
                    System.Net.NetworkInformation.PhysicalAddress pa = NetUtility.GetMacAddress();
                    if (pa != null)
                    {
                        macBytes = pa.GetAddressBytes();
                        LogVerbose("Mac address is " + NetUtility.ToHexString(macBytes));
                    }
                    else
                    {
                        LogWarning("Failed to get Mac address");
                    }
                }
                catch (NotSupportedException)
                {
                    // not supported; lets just keep the random bytes set above
                }
#endif
                IPEndPoint boundEp  = m_socket.LocalEndPoint as IPEndPoint;
                byte[]     epBytes  = BitConverter.GetBytes(boundEp.GetHashCode());
                byte[]     combined = new byte[epBytes.Length + macBytes.Length];
                Array.Copy(epBytes, 0, combined, 0, epBytes.Length);
                Array.Copy(macBytes, 0, combined, epBytes.Length, macBytes.Length);
                m_uniqueIdentifier = BitConverter.ToInt64(NetUtility.CreateSHA1Hash(combined), 0);

                m_status = NetPeerStatus.Running;
            }
        }
        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 / 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
                Tuple <IPEndPoint, 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);
                }
            }

            //
            // 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");

                IPEndPoint ipsender = (IPEndPoint)m_senderRemote;

                if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
                {
                    // is this an UPnP response?
                    string resp = System.Text.Encoding.ASCII.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));

                    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);
        }
        private void HandleReleasedFragment(NetIncomingMessage im)
        {
            VerifyNetworkThread();

            //
            // read fragmentation header and combine fragments
            //
            int group;
            int totalBits;
            int chunkByteSize;
            int chunkNumber;
            int ptr = NetFragmentationHelper.ReadHeader(
                im.m_data, 0,
                out group,
                out totalBits,
                out chunkByteSize,
                out chunkNumber
                );

            NetException.Assert(im.LengthBytes > ptr);

            NetException.Assert(group > 0);
            NetException.Assert(totalBits > 0);
            NetException.Assert(chunkByteSize > 0);

            int totalBytes     = NetUtility.BytesToHoldBits((int)totalBits);
            int totalNumChunks = totalBytes / chunkByteSize;

            if (totalNumChunks * chunkByteSize < totalBytes)
            {
                totalNumChunks++;
            }

            NetException.Assert(chunkNumber < totalNumChunks);

            if (chunkNumber >= totalNumChunks)
            {
                LogWarning("Index out of bounds for chunk " + chunkNumber + " (total chunks " + totalNumChunks + ")");
                return;
            }

            Dictionary <int, ReceivedFragmentGroup> groups;

            if (!m_receivedFragmentGroups.TryGetValue(im.SenderConnection, out groups))
            {
                groups = new Dictionary <int, ReceivedFragmentGroup>();
                m_receivedFragmentGroups[im.SenderConnection] = groups;
            }

            ReceivedFragmentGroup info;

            if (!groups.TryGetValue(group, out info))
            {
                info                = new ReceivedFragmentGroup();
                info.Data           = new byte[totalBytes];
                info.ReceivedChunks = new NetBitVector(totalNumChunks);
                groups[group]       = info;
            }

            info.ReceivedChunks[chunkNumber] = true;
            //info.LastReceived = (float)NetTime.Now;

            // copy to data
            int offset = (chunkNumber * chunkByteSize);

            Buffer.BlockCopy(im.m_data, ptr, info.Data, offset, im.LengthBytes - ptr);

            int cnt = info.ReceivedChunks.Count();

            //LogVerbose("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")");

            LogVerbose("Received fragment " + chunkNumber + " of " + totalNumChunks + " (" + cnt + " chunks received)");

            if (info.ReceivedChunks.Count() == totalNumChunks)
            {
                // Done! Transform this incoming message
                im.m_data       = info.Data;
                im.m_bitLength  = (int)totalBits;
                im.m_isFragment = false;

                LogVerbose("Fragment group #" + group + " fully received in " + totalNumChunks + " chunks (" + totalBits + " bits)");
                groups.Remove(group);

                ReleaseMessage(im);
            }
            else
            {
                // data has been copied; recycle this incoming message
                Recycle(im);
            }

            return;
        }
Exemple #41
0
        // received a library message while Connected
        internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength)
        {
            m_peer.VerifyNetworkThread();

            double now = NetTime.Now;

            switch (tp)
            {
            case NetMessageType.Connect:
                m_peer.LogDebug("Received handshake message (" + tp + ") despite connection being in place");
                break;

            case NetMessageType.ConnectResponse:
                // handshake message must have been lost
                HandleConnectResponse(now, tp, ptr, payloadLength);
                break;

            case NetMessageType.ConnectionEstablished:
                // do nothing, all's well
                break;

            case NetMessageType.LibraryError:
                m_peer.ThrowOrLog("LibraryError received by ReceivedLibraryMessage; this usually indicates a malformed message");
                break;

            case NetMessageType.Disconnect:
                NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength);

                m_disconnectRequested  = true;
                m_disconnectMessage    = msg.ReadString();
                m_disconnectReqSendBye = false;
                //ExecuteDisconnect(msg.ReadString(), false);
                break;

            case NetMessageType.Acknowledge:
                for (int i = 0; i < payloadLength; i += 3)
                {
                    NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++];     // netmessagetype
                    int            seqNr = m_peer.m_receiveBuffer[ptr++];
                    seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8);

                    // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends
                    m_queuedIncomingAcks.Enqueue(new NetTuple <NetMessageType, int>(acktp, seqNr));
                }
                break;

            case NetMessageType.Ping:
                int pingNr = m_peer.m_receiveBuffer[ptr++];
                SendPong(pingNr);
                break;

            case NetMessageType.Pong:
                NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int   pongNr            = pmsg.ReadByte();
                float remoteSendTime    = pmsg.ReadSingle();
                ReceivedPong(now, pongNr, remoteSendTime);
                break;

            case NetMessageType.ExpandMTURequest:
                SendMTUSuccess(payloadLength);
                break;

            case NetMessageType.ExpandMTUSuccess:
                if (m_peer.Configuration.AutoExpandMTU == false)
                {
                    m_peer.LogDebug("Received ExpandMTURequest altho AutoExpandMTU is turned off!");
                    break;
                }
                NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int size = emsg.ReadInt32();
                HandleExpandMTUSuccess(now, size);
                break;

            case NetMessageType.NatIntroduction:
                // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual
                m_peer.HandleNatIntroduction(ptr);
                break;

            default:
                m_peer.LogError("Connection received unhandled library message: " + tp);
                break;
            }
        }
        internal void ReceivedHandshake(TimeSpan now, NetMessageType type, int offset, int payloadLength)
        {
            Peer.AssertIsOnLibraryThread();

            switch (type)
            {
            case NetMessageType.Connect:
                if (Status == NetConnectionStatus.ReceivedInitiation)
                {
                    // Whee! Server full has already been checked
                    var(success, hail, hailLength) = ValidateHandshakeData(offset, payloadLength);
                    if (success)
                    {
                        if (hail != null)
                        {
                            RemoteHailMessage = Peer.CreateIncomingMessage(NetIncomingMessageType.Data);
                            RemoteHailMessage.SetBuffer(hail, true);
                            RemoteHailMessage.ByteLength = hailLength;
                        }
                        else
                        {
                            RemoteHailMessage = null;
                        }

                        if (_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionApproval))
                        {
                            // ok, let's not add connection just yet
                            var appMsg = Peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval);

                            appMsg.ReceiveTime      = now;
                            appMsg.SenderConnection = this;
                            appMsg.SenderEndPoint   = RemoteEndPoint;

                            if (RemoteHailMessage != null)
                            {
                                appMsg.Write(RemoteHailMessage.GetBuffer().AsSpan(0, RemoteHailMessage.ByteLength));
                            }

                            SetStatus(NetConnectionStatus.RespondedAwaitingApproval);
                            Peer.ReleaseMessage(appMsg);
                            return;
                        }

                        SendConnectResponse(now, true);
                    }
                    return;
                }
                if (Status == NetConnectionStatus.RespondedAwaitingApproval)
                {
                    Peer.LogWarning(new NetLogMessage(NetLogCode.IgnoringMultipleConnects, endPoint: this));
                    return;
                }
                if (Status == NetConnectionStatus.RespondedConnect)
                {
                    // our ConnectResponse must have been lost
                    SendConnectResponse(now, true);
                    return;
                }
                Peer.LogDebug(NetLogMessage.FromValues(NetLogCode.UnhandledConnect, endPoint: this, value: (int)Status));
                break;

            case NetMessageType.ConnectResponse:
                HandleConnectResponse(offset, payloadLength);
                break;

            case NetMessageType.ConnectionEstablished:
                switch (Status)
                {
                case NetConnectionStatus.Connected:
                    // ok...
                    break;

                case NetConnectionStatus.Disconnected:
                case NetConnectionStatus.Disconnecting:
                case NetConnectionStatus.None:
                    // too bad, almost made it
                    break;

                case NetConnectionStatus.ReceivedInitiation:
                    // uh, a little premature... ignore
                    break;

                case NetConnectionStatus.InitiatedConnect:
                    // weird, should have been RespondedConnect...
                    break;

                case NetConnectionStatus.RespondedConnect:
                    // awesome
                    NetIncomingMessage msg = Peer.SetupReadHelperMessage(offset, payloadLength);
                    InitializeRemoteTimeOffset(msg.ReadTimeSpan());

                    Peer.AcceptConnection(this);
                    InitializePing();
                    SetStatus(NetConnectionStatus.Connected);
                    return;
                }
                break;

            case NetMessageType.InvalidHandshake:
            case NetMessageType.WrongAppIdentifier:
            case NetMessageType.ConnectTimedOut:
            case NetMessageType.TimedOut:
            case NetMessageType.Disconnect:
                NetOutgoingMessage?reason = null;
                try
                {
                    reason = Peer.CreateReadHelperOutMessage(offset, payloadLength);
                }
                catch
                {
                }
                ExecuteDisconnect(reason, false);
                break;

            case NetMessageType.Discovery:
                Peer.HandleIncomingDiscoveryRequest(now, RemoteEndPoint, offset, payloadLength);
                return;

            case NetMessageType.DiscoveryResponse:
                Peer.HandleIncomingDiscoveryResponse(now, RemoteEndPoint, offset, payloadLength);
                return;

            case NetMessageType.Ping:
                // silently ignore
                return;

            default:
                Peer.LogDebug(NetLogMessage.FromValues(NetLogCode.UnhandledHandshakeMessage, value: (int)Status));
                break;
            }
        }
        internal void ReceivedHandshake(double now, NetMessageType tp, int ptr, int payloadLength)
        {
            m_peer.VerifyNetworkThread();

            byte[] hail;
            switch (tp)
            {
            case NetMessageType.Connect:
                if (m_status == NetConnectionStatus.None)
                {
                    // Whee! Server full has already been checked
                    bool ok = ValidateHandshakeData(ptr, payloadLength, out hail);
                    if (ok)
                    {
                        if (hail != null)
                        {
                            m_remoteHailMessage            = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail);
                            m_remoteHailMessage.LengthBits = (hail.Length * 8);
                        }
                        else
                        {
                            m_remoteHailMessage = null;
                        }

                        if (m_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionApproval))
                        {
                            // ok, let's not add connection just yet
                            NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes));
                            appMsg.m_receiveTime      = now;
                            appMsg.m_senderConnection = this;
                            appMsg.m_senderEndpoint   = this.m_remoteEndpoint;
                            if (m_remoteHailMessage != null)
                            {
                                appMsg.Write(m_remoteHailMessage.m_data, 0, m_remoteHailMessage.LengthBytes);
                            }
                            m_peer.ReleaseMessage(appMsg);
                            return;
                        }

                        SendConnectResponse((float)now, true);
                    }
                    return;
                }
                if (m_status == NetConnectionStatus.RespondedConnect)
                {
                    // our ConnectResponse must have been lost
                    SendConnectResponse((float)now, true);
                    return;
                }
                m_peer.LogDebug("Unhandled Connect: " + tp + ", status is " + m_status + " length: " + payloadLength);
                break;

            case NetMessageType.ConnectResponse:
                switch (m_status)
                {
                case NetConnectionStatus.InitiatedConnect:
                    // awesome
                    bool ok = ValidateHandshakeData(ptr, payloadLength, out hail);
                    if (ok)
                    {
                        if (hail != null)
                        {
                            m_remoteHailMessage            = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail);
                            m_remoteHailMessage.LengthBits = (hail.Length * 8);
                        }
                        else
                        {
                            m_remoteHailMessage = null;
                        }

                        m_peer.AcceptConnection(this);
                        SendConnectionEstablished();
                        return;
                    }
                    break;

                case NetConnectionStatus.RespondedConnect:
                    // hello, wtf?
                    break;

                case NetConnectionStatus.Disconnecting:
                case NetConnectionStatus.Disconnected:
                case NetConnectionStatus.None:
                    // wtf? anyway, bye!
                    break;

                case NetConnectionStatus.Connected:
                    // my ConnectionEstablished must have been lost, send another one
                    SendConnectionEstablished();
                    return;
                }
                break;

            case NetMessageType.ConnectionEstablished:
                switch (m_status)
                {
                case NetConnectionStatus.Connected:
                    // ok...
                    break;

                case NetConnectionStatus.Disconnected:
                case NetConnectionStatus.Disconnecting:
                case NetConnectionStatus.None:
                    // too bad, almost made it
                    break;

                case NetConnectionStatus.InitiatedConnect:
                    // weird, should have been ConnectResponse...
                    break;

                case NetConnectionStatus.RespondedConnect:
                    // awesome

                    NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                    InitializeRemoteTimeOffset(msg.ReadSingle());

                    m_peer.AcceptConnection(this);
                    InitializePing();
                    SetStatus(NetConnectionStatus.Connected, "Connected to " + NetUtility.ToHexString(m_remoteUniqueIdentifier));
                    return;
                }
                break;

            case NetMessageType.Disconnect:
                // ouch
                string reason = "Ouch";
                try
                {
                    NetIncomingMessage inc = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                    reason = inc.ReadString();
                }
                catch
                {
                }
                ExecuteDisconnect(reason, false);
                break;

            default:
                m_peer.LogDebug("Unhandled type during handshake: " + tp + " length: " + payloadLength);
                break;
            }
        }
        internal override void ReceiveMessage(NetIncomingMessage message)
        {
            int relate = NetUtility.RelativeSequenceNumber(message.m_sequenceNumber, m_windowStart);

            // ack no matter what
            m_connection.QueueAck(message.m_receivedMessageType, message.m_sequenceNumber);

            if (relate == 0)
            {
                // Log("Received message #" + message.SequenceNumber + " right on time");
                //
                // excellent, right on time
                //
                //m_peer.LogVerbose("Received RIGHT-ON-TIME " + message);

                AdvanceWindow();
                m_peer.ReleaseMessage(message);

                // release withheld messages
                int nextSeqNr = (message.m_sequenceNumber + 1) % NetConstants.NumSequenceNumbers;

                while (m_earlyReceived[nextSeqNr % m_windowSize])
                {
                    //message = m_withheldMessages[nextSeqNr % m_windowSize];
                    //NetException.Assert(message != null);

                    // remove it from withheld messages
                    //m_withheldMessages[nextSeqNr % m_windowSize] = null;

                    //m_peer.LogVerbose("Releasing withheld message #" + message);

                    //m_peer.ReleaseMessage(message);

                    AdvanceWindow();
                    nextSeqNr++;
                }

                return;
            }

            if (relate < 0)
            {
                // duplicate
                m_peer.LogVerbose("Received message #" + message.m_sequenceNumber + " DROPPING DUPLICATE");
                return;
            }

            // relate > 0 = early message
            if (relate > m_windowSize)
            {
                // too early message!
                m_peer.LogDebug("Received " + message + " TOO EARLY! Expected " + m_windowStart);
                return;
            }

            m_earlyReceived.Set(message.m_sequenceNumber % m_windowSize, true);
            //m_peer.LogVerbose("Received " + message + " WITHHOLDING, waiting for " + m_windowStart);
            //m_withheldMessages[message.m_sequenceNumber % m_windowSize] = message;

            m_peer.ReleaseMessage(message);
        }
Exemple #45
0
 /// <summary>
 /// Decrypt an incoming message in place
 /// </summary>
 public abstract bool Decrypt(NetIncomingMessage msg);