Beispiel #1
0
        private bool ReceiveMachineDisconnectedMessage(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }
            byte id;

            try
            {
                id = msg.ReadByte();
            }
            catch
            {
                return(false);
            }
            if (id == localMachine.id)
            {
                // Some race condition occured, we should already be disconnected from host
                // TODO: Suitable place to end session as we were probably kicked?
                return(true);
            }


            if (isHost || !machineFromId.ContainsKey(id))
            {
                // Host already removed machine and machine might have been disconnected before it fully connected
                return(true);
            }
            RemoveMachine(machineFromId[id]);
            return(true);
        }
Beispiel #2
0
        private bool ReceiveGamerIdRequest(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!isHost)
            {
                return(false);
            }
            if (originMachine.gamers.Count >= MaxSupportedLocalGamers)
            {
                // A single requester should not request too many gamer ids
                return(false);
            }

            bool available = false;
            byte id        = 255;

            if (GetOpenSlotsForMachine(originMachine) > 0)
            {
                available = GetUniqueId(gamerFromId, out id);

                // Let host create (but not add) remote gamer directly
                if (available && isHost && originMachine != localMachine)
                {
                    var isPrivateSlot = originMachine.isHost && GetOpenPrivateGamerSlots() > 0;
                    var pendingGamer  = new NetworkGamer(originMachine, id, isPrivateSlot, false, LoadingGamertag, LoadingGamertag);
                    gamerFromId.Add(id, pendingGamer);
                }
            }
            SendGamerIdResponse(originMachine, available, id);
            return(true);
        }
Beispiel #3
0
        private bool ReceiveGamerLeft(NetBuffer msg, NetworkMachine originMachine)
        {
            byte id;

            try
            {
                id = msg.ReadByte();
            }
            catch
            {
                return(false);
            }
            if (id == 255)
            {
                return(false);
            }
            if (!gamerFromId.ContainsKey(id))
            {
                return(false);
            }
            var gamer = gamerFromId[id];

            if (gamer.machine != originMachine)
            {
                return(false);
            }

            RemoveGamer(gamer);
            return(true);
        }
Beispiel #4
0
        private NetOutgoingMessage CreateMessageWithHeader(MessageType type, NetworkMachine recipientMachine)
        {
            var msg = peer.CreateMessage();

            msg.Write((byte)type);
            msg.Write((byte)(recipientMachine != null ? recipientMachine.id : 255));
            msg.Write((byte)localMachine.id);
            return(msg);
        }
Beispiel #5
0
 private void AddMachine(NetworkMachine machine, NetConnection connection)
 {
     allMachines.Add(machine);
     machineFromId.Add(machine.id, machine);
     if (connection != null)
     {
         connectionFromMachine.Add(machine, connection);
     }
 }
Beispiel #6
0
        private bool ReceiveMachineConnectedMessage(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }
            byte id;

            try
            {
                id = msg.ReadByte();
            }
            catch
            {
                return(false);
            }
            if (id == localMachine.id)
            {
                // The host is broadcasting our local machine to everyone
                return(true);
            }

            NetworkMachine newMachine;

            if (isHost)
            {
                // Host has already added machine
                newMachine = machineFromId[id];

                // Tell new machine about the current state of the game
                SendSessionStateChanged(newMachine);

                // Tell new machine about the machines already in the session
                foreach (var existingMachine in allMachines)
                {
                    if (existingMachine == localMachine || existingMachine == newMachine)
                    {
                        continue;
                    }
                    SendMachineConnectedMessage(existingMachine, newMachine);
                }
            }
            else
            {
                newMachine = new NetworkMachine(this, false, false, id);
                AddMachine(newMachine, hostConnection);
            }

            // Tell new machine about our gamers
            foreach (var localGamer in localGamers)
            {
                SendGamerJoined(localGamer, newMachine);
            }

            return(true);
        }
        private int GetOpenSlotsForMachine(NetworkMachine machine)
        {
            int slots = GetOpenPublicGamerSlots();

            if (machine.isHost)
            {
                slots = Math.Max(slots, GetOpenPrivateGamerSlots());
            }
            return(slots);
        }
Beispiel #8
0
        private void RemoveMachine(NetworkMachine machine)
        {
            for (int i = machine.gamers.Count - 1; i >= 0; i--)
            {
                RemoveGamer(machine.gamers[i]);
            }

            allMachines.Remove(machine);
            machineFromId.Remove(machine.id);
            connectionFromMachine.Remove(machine);
        }
Beispiel #9
0
        private bool ReceiveStartGame(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }

            state = NetworkSessionState.Playing;
            InvokeGameStartedEvent(new GameStartedEventArgs());
            return(true);
        }
Beispiel #10
0
        private void SendGamerJoined(LocalNetworkGamer localGamer, NetworkMachine recipient)
        {
            var msg = CreateMessageWithHeader(MessageType.GamerJoined, recipient);

            msg.Write(localGamer.id);
            msg.Write(localGamer.DisplayName);
            msg.Write(localGamer.Gamertag);
            msg.Write(localGamer.isPrivateSlot);
            msg.Write(localGamer.isReady);
            SendMessage(msg, NetDeliveryMethod.ReliableOrdered);
        }
Beispiel #11
0
        private void SendMachineDisconnectedMessage(NetworkMachine machine)
        {
            if (!isHost)
            {
                throw new InvalidOperationException();
            }

            var msg = CreateMessageWithHeader(MessageType.MachineDisconnected, null);

            msg.Write(machine.id);
            SendMessage(msg, NetDeliveryMethod.ReliableOrdered);
        }
Beispiel #12
0
        internal NetworkGamer(NetworkMachine machine, byte id, bool isPrivateSlot, bool isReady, string displayName, string gamertag)
            : base()
        {
            this.session       = machine.session;
            this.machine       = machine;
            this.id            = id;
            this.isPrivateSlot = isPrivateSlot;
            this.isReady       = isReady;

            this.DisplayName = displayName;
            this.Gamertag    = gamertag;
        }
Beispiel #13
0
        internal void DisconnectMachine(NetworkMachine machine, NetworkSessionEndReason reason)
        {
            if (!isHost)
            {
                throw new InvalidOperationException();
            }

            if (connectionFromMachine[machine].Status == NetConnectionStatus.Connected)
            {
                connectionFromMachine[machine].Disconnect(reason.ToString());
            }
        }
Beispiel #14
0
        private void SendGamerIdResponse(NetworkMachine recipient, bool success, byte id)
        {
            if (!isHost || (success && id == 255))
            {
                throw new InvalidOperationException();
            }

            var msg = CreateMessageWithHeader(MessageType.GamerIdResponse, recipient);

            msg.Write(success);
            msg.Write(id);
            SendMessage(msg, NetDeliveryMethod.ReliableOrdered);
        }
Beispiel #15
0
        private bool ReceiveResetReady(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }

            foreach (var gamer in allGamers)
            {
                gamer.isReady = false;
            }
            return(true);
        }
Beispiel #16
0
        private bool ReceiveEndGame(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }

            foreach (var gamer in allGamers)
            {
                gamer.isReady = false;
            }
            state = NetworkSessionState.Lobby;
            InvokeGameEndedEvent(new GameEndedEventArgs());
            return(true);
        }
Beispiel #17
0
        private void SendSessionStateChanged(NetworkMachine recipient)
        {
            if (!isHost)
            {
                throw new InvalidOperationException();
            }

            var msg = CreateMessageWithHeader(MessageType.SessionStateChanged, recipient);

            msg.Write(allowHostMigration);
            msg.Write(allowJoinInProgress);
            msg.Write(maxGamers);
            msg.Write(privateGamerSlots);
            msg.Write((byte)state);
            properties.Pack(msg);
            SendMessage(msg, NetDeliveryMethod.ReliableOrdered);
        }
Beispiel #18
0
        private bool ReceiveGamerIdResponse(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }
            bool slotAvailable;
            byte id;

            try
            {
                slotAvailable = msg.ReadBoolean();
                id            = msg.ReadByte();
            }
            catch
            {
                return(false);
            }
            if (slotAvailable && id == 255)
            {
                return(false);
            }

            if (pendingSignedInGamers.Count == 0)
            {
                // Don't treat as error but host will have marked slot used by client
                return(true);
            }
            if (!slotAvailable)
            {
                pendingSignedInGamers.RemoveAt(0);
                return(true);
            }
            var signedInGamer = pendingSignedInGamers[0];

            pendingSignedInGamers.RemoveAt(0);

            var isPrivateSlot = isHost && GetOpenPrivateGamerSlots() > 0;
            var localGamer    = new LocalNetworkGamer(signedInGamer, localMachine, id, isPrivateSlot);

            AddGamer(localGamer);
            SendGamerJoined(localGamer, null);
            return(true);
        }
Beispiel #19
0
        private bool ReceiveSessionStateChanged(NetBuffer msg, NetworkMachine originMachine)
        {
            if (!originMachine.isHost)
            {
                return(false);
            }

            bool allowHostMigration, allowJoinInProgress;
            int  maxGamers, privateGamerSlots;
            NetworkSessionState      state;
            NetworkSessionProperties properties = new NetworkSessionProperties();

            try
            {
                allowHostMigration  = msg.ReadBoolean();
                allowJoinInProgress = msg.ReadBoolean();
                maxGamers           = msg.ReadInt32();
                privateGamerSlots   = msg.ReadInt32();
                state = (NetworkSessionState)msg.ReadByte();
                if (!properties.Unpack(msg))
                {
                    return(false);
                }
            }
            catch
            {
                return(false);
            }

            this.allowHostMigration  = allowHostMigration;
            this.allowJoinInProgress = allowJoinInProgress;
            this.maxGamers           = maxGamers;
            this.privateGamerSlots   = privateGamerSlots;
            this.state = state;
            this.properties.CopyValuesFrom(properties);
            return(true);
        }
Beispiel #20
0
        private bool ReceiveGamerStateChanged(NetBuffer msg, NetworkMachine originMachine)
        {
            byte   id;
            string displayName, gamertag;
            bool   isReady;

            try
            {
                id          = msg.ReadByte();
                displayName = msg.ReadString();
                gamertag    = msg.ReadString();
                isReady     = msg.ReadBoolean();
            }
            catch
            {
                return(false);
            }
            if (id == 255)
            {
                return(false);
            }
            if (!gamerFromId.ContainsKey(id))
            {
                return(false);
            }
            var gamer = gamerFromId[id];

            if (gamer.machine != originMachine)
            {
                return(false);
            }

            gamer.DisplayName = displayName;
            gamer.Gamertag    = gamertag;
            gamer.isReady     = isReady;
            return(true);
        }
Beispiel #21
0
        private void ReceiveMessage(NetBuffer msg, NetDeliveryMethod deliveryMethod, NetworkMachine senderMachine)
        {
            // Decode header
            if (msg.LengthBytes < 3)
            {
                // TODO: Kick machine?
                Debug.Write("Received empty message from machine " + senderMachine.id);
                return;
            }

            //ushort header0, header1;
            byte headerMsgType, headerRecipientId, headerOriginId;

            try
            {
                headerMsgType     = msg.ReadByte();
                headerRecipientId = msg.ReadByte();
                headerOriginId    = msg.ReadByte();
            }
            catch
            {
                // TODO: Kick machine?
                Debug.WriteLine("Received message with malformed header from machine " + senderMachine.id);
                return;
            }
            if (headerMsgType >= MessageTypeCount)
            {
                // TODO: Kick machine?
                Debug.WriteLine("Received message with malformed header from machine " + senderMachine.id);
                return;
            }

            MessageType msgType   = (MessageType)headerMsgType;
            bool        sendToAll = headerRecipientId == 255;

            if ((!sendToAll && !machineFromId.ContainsKey(headerRecipientId)) || !machineFromId.ContainsKey(headerOriginId))
            {
                if (isHost)
                {
                    // TODO: Kick machine?
                    Debug.WriteLine("Received message with malformed header from machine " + senderMachine.id);
                }
                return;
            }

            var recipientMachine = sendToAll ? null : machineFromId[headerRecipientId];
            var originMachine    = machineFromId[headerOriginId];

            if (isHost && senderMachine != originMachine)
            {
                // TODO: Kick machine?
                Debug.WriteLine("Received message with malformed header from machine " + senderMachine.id);
                return;
            }

            if (msgType != MessageType.User)
            {
                Debug.WriteLine("R " + senderMachine.id + "(" + originMachine.id + ")->" + (recipientMachine != null ? recipientMachine.id.ToString() : "[all]") + " " + msgType);
            }

            // Handle message
            bool success = false;

            switch (msgType)
            {
            case MessageType.SessionStateChanged:
                success = ReceiveSessionStateChanged(msg, originMachine);
                break;

            case MessageType.MachineConnected:
                success = ReceiveMachineConnectedMessage(msg, originMachine);
                break;

            case MessageType.MachineDisconnected:
                success = ReceiveMachineDisconnectedMessage(msg, originMachine);
                break;

            case MessageType.GamerIdRequest:
                success = ReceiveGamerIdRequest(msg, originMachine);
                break;

            case MessageType.GamerIdResponse:
                success = ReceiveGamerIdResponse(msg, originMachine);
                break;

            case MessageType.GamerJoined:
                success = ReceiveGamerJoined(msg, originMachine, recipientMachine);
                break;

            case MessageType.GamerLeft:
                success = ReceiveGamerLeft(msg, originMachine);
                break;

            case MessageType.GamerStateChanged:
                success = ReceiveGamerStateChanged(msg, originMachine);
                break;

            case MessageType.ResetReady:
                success = ReceiveResetReady(msg, originMachine);
                break;

            case MessageType.StartGame:
                success = ReceiveStartGame(msg, originMachine);
                break;

            case MessageType.EndGame:
                success = ReceiveEndGame(msg, originMachine);
                break;

            case MessageType.User:
                success = ReceiveUserMessage(msg, originMachine);
                break;

            default:
                throw new NotImplementedException();
            }

            if (!success)
            {
                // TODO: Kick machine if host and disconnect if client?
                Debug.WriteLine("Failed to parse last message!");
                return;
            }

            // If host, forward message to peers
            if (isHost && senderMachine != localMachine && recipientMachine != localMachine)
            {
                if (msgType != MessageType.User)
                {
                    Debug.WriteLine("Forwarding " + msgType + " message to machine " + (recipientMachine != null ? recipientMachine.id.ToString() : "[all]"));
                }

                SendMessage(CreateMessageFrom(msg), deliveryMethod, ignoreSelf: true);
            }
        }
Beispiel #22
0
        private bool ReceiveGamerJoined(NetBuffer msg, NetworkMachine originMachine, NetworkMachine recipientMachine)
        {
            byte   id;
            string displayName, gamertag;
            bool   isPrivateSlot, isReady;

            try
            {
                id            = msg.ReadByte();
                displayName   = msg.ReadString();
                gamertag      = msg.ReadString();
                isPrivateSlot = msg.ReadBoolean();
                isReady       = msg.ReadBoolean();
            }
            catch
            {
                return(false);
            }
            if (id == 255)
            {
                return(false);
            }

            if (originMachine.isLocal)
            {
                // Already added local gamer
                return(true);
            }

            if (isHost)
            {
                if (!gamerFromId.ContainsKey(id))
                {
                    // Host must know about all gamers
                    return(false);
                }
                if (id == 0)
                {
                    // Someone is impersonating the host gamer
                    return(false);
                }

                if (recipientMachine == null || recipientMachine == localMachine)
                {
                    // Host already added gamer, just update it and add it to the game
                    var gamer = gamerFromId[id];
                    if (gamer.state != NetworkGamerState.Pending)
                    {
                        return(false);
                    }

                    gamer.DisplayName   = displayName;
                    gamer.Gamertag      = gamertag;
                    gamer.isPrivateSlot = isPrivateSlot;
                    gamer.isReady       = isReady;
                    AddGamer(gamer);
                }
                else
                {
                    // TODO: Make sure client is not spamming recipient
                }
            }
            else
            {
                if (id == 0)
                {
                    // Special case for host gamer
                    if (!originMachine.isHost)
                    {
                        return(false);
                    }

                    // Already added host gamer with id 0, just update it
                    Host.DisplayName   = displayName;
                    Host.Gamertag      = gamertag;
                    Host.isPrivateSlot = isPrivateSlot;
                    Host.isReady       = isReady;
                }
                else
                {
                    AddGamer(new NetworkGamer(originMachine, id, isPrivateSlot, isReady, displayName, gamertag));
                }
            }
            return(true);
        }
Beispiel #23
0
        private bool ReceiveUserMessage(NetBuffer msg, NetworkMachine originMachine)
        {
            byte            senderId, recipientId;
            SendDataOptions options;
            int             length;
            Packet          packet;

            try
            {
                senderId    = msg.ReadByte();
                recipientId = msg.ReadByte();
                options     = (SendDataOptions)msg.ReadByte();
                length      = msg.ReadInt32();
                packet      = packetPool.Get(length); // Critical TODO: Protect memory
                msg.ReadBytes(packet.data, 0, length);
            }
            catch
            {
                return(false);
            }
            bool sendToAll = recipientId == 255;

            if (senderId == 255)
            {
                return(false);
            }
            var sender = gamerFromId.ContainsKey(senderId) ? gamerFromId[senderId] : null; // Sender can be null if gamer joined not yet received

            if (sender != null && sender.machine != originMachine)
            {
                return(false);
            }
            if (!IsSendDataOptionsValid(options))
            {
                return(false);
            }

            if (sendToAll)
            {
                bool firstGamer = true;
                foreach (var localGamer in localGamers)
                {
                    var uniquePacket = firstGamer ? packet : packetPool.GetAndFillWith(packet.data);
                    if (!localGamer.AddInboundPacket(uniquePacket, senderId, options))
                    {
                        // TODO: Kick machine if host?
                        Debug.WriteLine("MaxDelayedInboundPacketsAllowed reached!");
                        return(false);
                    }
                    firstGamer = false;
                }
                return(true);
            }
            else
            {
                var recipient = FindGamerById(recipientId);
                if (recipient == null)
                {
                    // TODO: Check if recipient is on list of previous gamers, for now assume true
                    bool previousGamer = true;

                    // Message is ok if the recipient was a gamer previously
                    return(previousGamer);
                }

                var localGamer = recipient as LocalNetworkGamer;
                if (localGamer == null)
                {
                    if (isHost)
                    {
                        // The message is meant for someone else (return true so that the message is forwarded)
                        return(true);
                    }
                    else
                    {
                        // The message is meant for us but the local gamer is gone? The host made a mistake or our local gamer left, see above
                        bool previousLocalGamer = true;
                        return(previousLocalGamer);
                    }
                }

                if (!localGamer.AddInboundPacket(packet, senderId, options))
                {
                    // TODO: Kick machine if host?
                    Debug.WriteLine("MaxDelayedInboundPacketsAllowed reached!");
                    return(false);
                }
                return(true);
            }
        }
Beispiel #24
0
        internal NetworkSession(NetPeer peer, bool isHost, byte machineId, NetworkSessionType type, NetworkSessionProperties properties, int maxGamers, int privateGamerSlots, IEnumerable <SignedInGamer> localGamers, string hostDisplayName, string hostGamertag)
        {
            if (peer.Configuration.AutoFlushSendQueue)
            {
                throw new InvalidOperationException("Peer must not flush send queue automatically");
            }
            if (isHost && machineId != 0)
            {
                throw new InvalidOperationException("Host must have machine id 0");
            }
            if (!isHost && machineId == 0)
            {
                throw new InvalidOperationException("Client cannot have machine id 0");
            }

            this.peer      = peer;
            this.isHost    = isHost;
            this.machineId = machineId;
            this.type      = type;
            this.guid      = Guid.NewGuid();

            this.properties   = properties;
            this.localMachine = new NetworkMachine(this, true, isHost, machineId);
            this.hostMachine  = isHost ? this.localMachine : new NetworkMachine(this, false, true, 0);

            AddMachine(this.localMachine, null);

            if (!isHost)
            {
                if (peer.ConnectionsCount != 1 || peer.Connections[0].Status != NetConnectionStatus.Connected)
                {
                    throw new InvalidOperationException("Client peer must be connected to host before NetworkSession can be instantiated");
                }
                hostConnection     = peer.Connections[0];
                hostConnection.Tag = this.hostMachine;

                AddMachine(this.hostMachine, hostConnection);

                // Add host gamer with id 0, important for NetworkSession.Host property
                AddGamer(new NetworkGamer(this.hostMachine, 0, privateGamerSlots > 0, false, hostDisplayName, hostGamertag));
            }

            this.maxGamers         = maxGamers;
            this.privateGamerSlots = privateGamerSlots;

            if (isHost)
            {
                // Add local gamers directly to make sure that there is always at least one gamer in the session
                byte id = 0;
                foreach (var gamer in localGamers)
                {
                    AddGamer(new LocalNetworkGamer(gamer, this.localMachine, id++, GetOpenPrivateGamerSlots() > 0));
                }
                if (allGamers.Count == 0)
                {
                    throw new InvalidOperationException();
                }
            }
            else
            {
                foreach (var gamer in localGamers)
                {
                    AddLocalGamer(gamer);
                }
            }

            this.AllGamers              = new GamerCollection <NetworkGamer>(new List <NetworkGamer>(), this.allGamers);
            this.PreviousGamers         = new GamerCollection <NetworkGamer>(new List <NetworkGamer>(), this.previousGamers);
            this.RemoteGamers           = new GamerCollection <NetworkGamer>(new List <NetworkGamer>(), this.remoteGamers);
            this.LocalGamers            = new GamerCollection <LocalNetworkGamer>(new List <LocalNetworkGamer>(), this.localGamers);
            this.BytesPerSecondReceived = 0;
            this.BytesPerSecondSent     = 0;

            this.SimulatedLatency    = TimeSpan.Zero;
            this.SimulatedPacketLoss = 0.0f;

            SignedInGamer.SignedOut += LocalGamerSignedOut;
        }
        private void ReceiveMessages()
        {
            NetIncomingMessage msg;

            while ((msg = peer.ReadMessage()) != null)
            {
                if (msg.MessageType == NetIncomingMessageType.DiscoveryRequest)
                {
                    Debug.WriteLine("Local discovery request received");

                    if (isHost)
                    {
                        UpdatePublicInfo();

                        NetworkMasterServer.SendRequestHostsResponse(peer, msg.SenderEndPoint, true, guid, publicInfo);
                    }
                }
                else if (msg.MessageType == NetIncomingMessageType.ConnectionApproval)
                {
                    if (!isHost)
                    {
                        throw new InvalidOperationException();
                    }

                    if (allowJoinInProgress || state == NetworkSessionState.Lobby)
                    {
                        byte machineId;
                        if (GetOpenPublicGamerSlots() > 0 && GetUniqueId(machineFromId, out machineId))
                        {
                            // Approved, create network machine
                            var machine = new NetworkMachine(this, false, false, machineId);
                            msg.SenderConnection.Tag = machine;
                            AddMachine(machine, msg.SenderConnection);

                            // Send approval to client containing unique machine id
                            var hailMsg = peer.CreateMessage();
                            hailMsg.Write(machineId);
                            msg.SenderConnection.Approve(hailMsg);
                        }
                        else
                        {
                            msg.SenderConnection.Deny(NetworkSessionJoinError.SessionFull.ToString());
                        }
                    }
                    else
                    {
                        msg.SenderConnection.Deny(NetworkSessionJoinError.SessionNotJoinable.ToString());
                    }
                }
                else if (msg.MessageType == NetIncomingMessageType.StatusChanged)
                {
                    var status = (NetConnectionStatus)msg.ReadByte();
                    Debug.WriteLine("Connection status updated: " + status + " (Reason: " + msg.ReadString() + ")");

                    if (status == NetConnectionStatus.Connected)
                    {
                        if (!isHost)
                        {
                            throw new InvalidOperationException("A client cannot accept new connections");
                        }
                        if (msg.SenderConnection.Tag == null)
                        {
                            throw new InvalidOperationException();
                        }

                        var machine = (NetworkMachine)msg.SenderConnection.Tag;

                        SendMachineConnectedMessage(machine, null);
                    }
                    else if (status == NetConnectionStatus.Disconnected)
                    {
                        if (msg.SenderConnection != null)
                        {
                            if (msg.SenderConnection.Tag == null)
                            {
                                throw new InvalidOperationException();
                            }

                            var machine = (NetworkMachine)msg.SenderConnection.Tag;

                            RemoveMachine(machine);

                            if (isHost)
                            {
                                SendMachineDisconnectedMessage(machine);
                            }
                            else
                            {
                                string reasonString;
                                NetworkSessionEndReason reason;
                                if (msg.ReadString(out reasonString) && Enum.TryParse(reasonString, out reason))
                                {
                                    End(reason);
                                }
                                else
                                {
                                    End(NetworkSessionEndReason.Disconnected);
                                }
                            }
                        }
                    }
                }
                else if (msg.MessageType == NetIncomingMessageType.Data)
                {
                    if (msg.SenderConnection.Tag == null)
                    {
                        throw new InvalidOperationException();
                    }
                    ReceiveMessage(msg, msg.DeliveryMethod, (NetworkMachine)msg.SenderConnection.Tag);
                }
                else if (msg.MessageType == NetIncomingMessageType.UnconnectedData)
                {
                    if (msg.SenderEndPoint.Equals(NetworkMasterServer.ResolveEndPoint()))
                    {
                        MasterServerMessageType   responseType;
                        MasterServerMessageResult responseResult;
                        if (NetworkMasterServer.ParseResponseHeader(msg, out responseType, out responseResult))
                        {
                            if (responseResult == MasterServerMessageResult.Ok)
                            {
                                if (responseType == MasterServerMessageType.RequestGeneralInfo)
                                {
                                    string generalInfo;
                                    if (NetworkMasterServer.ParseRequestGeneralInfoResponse(msg, out generalInfo))
                                    {
                                        masterServerGeneralInfo = generalInfo;
                                    }
                                }
                                else if (responseType == MasterServerMessageType.RegisterHost)
                                {
                                    isRegisteredAsHostWithMasterServer = true;
                                }
                                else if (responseType == MasterServerMessageType.UnregisterHost)
                                {
                                    isRegisteredAsHostWithMasterServer = false;
                                }
                            }
                            else
                            {
                                hasFailedMasterServerValidation = true;
                            }
                        }
                    }
                    else
                    {
                        Debug.WriteLine("Unconnected data not from master server recieved from " + msg.SenderEndPoint + ", ignoring...");
                    }
                }
                else
                {
                    HandleLidgrenMessage(msg);
                }
                peer.Recycle(msg);

                if (IsDisposed)
                {
                    break;
                }
            }
        }
 internal LocalNetworkGamer(SignedInGamer signedInGamer, NetworkMachine machine, byte id, bool isPrivateSlot)
     : base(machine, id, isPrivateSlot, false, signedInGamer.DisplayName, signedInGamer.Gamertag)
 {
     this.signedInGamer = signedInGamer;
 }