Beispiel #1
0
        internal RemotePeer(NetConnection connection, PeerInfo peerInfo)
        {
            PeerInfo = peerInfo;

            if (connection != null)
            {
                AddConnection(connection);
            }
        }
Beispiel #2
0
        private void HandleConnection(NetConnection connection)
        {
            // Read hail message:
            IPEndPoint internalEndPoint;
            ulong      sideChannelId;
            int        sideChannelToken;
            string     requestedName;

            byte[] remotePlayerData = null;
            try
            {
                UInt16 theirAppVersion = connection.RemoteHailMessage.ReadUInt16();
                if (theirAppVersion != owner.appConfig.ApplicationVersion)
                {
                    owner.Log("Disconnected client with wrong application version");
                    connection.Disconnect(DisconnectStrings.BadGameVersion);
                    return;
                }

                int    theirAppSignatureLength = (int)connection.RemoteHailMessage.ReadVariableUInt32();
                byte[] theirAppSignature;
                if (theirAppSignatureLength < 0 || theirAppSignatureLength > NetworkAppConfig.ApplicationSignatureMaximumLength)
                {
                    theirAppSignature = null;
                }
                else
                {
                    theirAppSignature = connection.RemoteHailMessage.ReadBytes(theirAppSignatureLength);
                }

                if (theirAppSignature == null || !owner.appConfig.ApplicationSignature.SequenceEqual(theirAppSignature))
                {
                    owner.Log("Disconnected client with wrong application signature");
                    connection.Disconnect(DisconnectStrings.BadGameVersion);
                    return;
                }


                internalEndPoint = connection.RemoteHailMessage.ReadIPEndPoint();
                sideChannelId    = connection.RemoteHailMessage.ReadUInt64();
                sideChannelToken = connection.RemoteHailMessage.ReadInt32();
                requestedName    = connection.RemoteHailMessage.ReadString();
                remotePlayerData = connection.RemoteHailMessage.ReadByteArray();
            }
            catch
            {
                owner.UnconnectedProtocolError("Bad hail message");
                connection.Disconnect(DisconnectStrings.BadHailMessage);
                return;
            }


            if (owner.GameInfo.SideChannelAuth)
            {
                int expectedToken;
                if (sideChannelToken == 0 || authTokens == null || !authTokens.TryGetValue(sideChannelId, out expectedToken) || expectedToken != sideChannelToken)
                {
                    owner.UnconnectedProtocolError("Bad side-channel authentication");
                    connection.Disconnect(DisconnectStrings.BadSideChannelAuth);
                }
            }


            requestedName = requestedName.FilterNameNoDuplicates(locallyConnected, owner.LocalPeerInfo.PlayerName);


            // Check whether the server is full:
            // (Could possibly handle this as Approve/Deny, but would then have to track slots for pending connections.)
            if (IsFull)
            {
                owner.Log("Rejecting incoming connection (player name: " + requestedName + "): game is full");
                connection.Disconnect(DisconnectStrings.GameFull);
                return;
            }


            // Setup remote peer:
            PeerInfo peerInfo = new PeerInfo()
            {
                ConnectionId           = nextConnectionId++,
                PlayerName             = requestedName,
                PlayerData             = remotePlayerData,
                InputAssignment        = AssignInput(),
                InternalEndPoint       = internalEndPoint,
                ExternalEndPoint       = connection.RemoteEndPoint,
                SideChannelId          = sideChannelId,
                IsApplicationConnected = false,
                IsServer = false,
            };


            RemotePeer remotePeer = new RemotePeer(connection, peerInfo);

            owner.Log("New connection: " + peerInfo.ToString());


            // Setup connection tokens:
            int[] connectionTokens = new int[locallyConnected.Count];
            for (int i = 0; i < connectionTokens.Length; i++)
            {
                connectionTokens[i] = random.Next();
            }


            // Send info to joining peer:
            {
                var message = NetPeer.CreateMessage();
                message.Write(P2PServerMessage.NetworkStartInfo);
                owner.GameInfo.WriteTo(message);
                peerInfo.WriteTo(message, true);      // Send their peer info (except: they already have their own playerData)
                owner.LocalPeerInfo.WriteTo(message); // Send our peer info

                // Write out a list of who to connect to:
                Debug.Assert(locallyConnected.Count < byte.MaxValue);
                message.Write((byte)(locallyConnected.Count));
                for (int i = 0; i < locallyConnected.Count; i++)
                {
                    (locallyConnected[i].Tag as RemotePeer).PeerInfo.WriteTo(message);
                    message.Write(connectionTokens[i]);
                }

                remotePeer.Connection.SendMessage(message, NetDeliveryMethod.ReliableOrdered, 0);
            }


            // Send connect instructions to other peers:
            for (int i = 0; i < locallyConnected.Count; i++)
            {
                var message = NetPeer.CreateMessage();
                message.Write(P2PServerMessage.PeerJoinedNetwork);
                peerInfo.WriteTo(message);
                message.Write(connectionTokens[i]);

                locallyConnected[i].SendMessage(message, NetDeliveryMethod.ReliableOrdered, 0);
            }


            // Add new connection to the local connection list:
            locallyConnected.Add(connection);

            // Start waiting for this new client to connect to the full network:
            StartPendingConnection(remotePeer);

            // Although the first connection won't need to wait:
            if (locallyConnected.Count == 1)
            {
                ReadyCheckAll();
            }
        }
Beispiel #3
0
 // Special use (for setting the server's peer info, and for host migration)
 internal void SetPeerInfo(PeerInfo peerInfo)
 {
     PeerInfo = peerInfo;
 }
Beispiel #4
0
 // Special use (for setting the server's peer info, and for host migration)
 internal void SetPeerInfo(PeerInfo peerInfo)
 {
     this.PeerInfo = peerInfo;
 }