internal void ReceiveDiscoveryResponse(NetIncomingMessage message) { Debug.Assert(message.SenderEndPoint != null); // Read game info: DiscoveredGame discoveredGame = DiscoveredGame.ReadFromDiscoveryResponse(owner.appConfig, message); if (discoveredGame == null) // not a valid response { return; } // Check if we need to update an existing game: // (RemoteGameInfo could be versioned, if we were worried about packet ordering) for (int i = 0; i < discoveryList.Count; i++) { if (discoveryList[i].EndPoint.Equals(discoveredGame.EndPoint)) { discoveryList[i].CopyFrom(discoveredGame); discoveryListDirty = true; return; } } // Otherwise just add it: discoveryList.Add(discoveredGame); discoveryListDirty = true; }
internal void CopyFrom(DiscoveredGame other) { GameInfo.CopyFrom(other.GameInfo); EndPoint = other.EndPoint; expireTime = other.expireTime; VersionMismatch = other.VersionMismatch; IsFull = other.IsFull; applicationData = other.applicationData; // <- assumed to be immutable }
public void HandleMessage(NetIncomingMessage message, ref bool recycle) { Debug.Assert(!didDisconnect); RemotePeer senderRemotePeer = null; if (message.SenderConnection != null) { senderRemotePeer = message.SenderConnection.Tag as RemotePeer; } try { switch (message.MessageType) { case NetIncomingMessageType.DiscoveryRequest: // (Clients trying to find LAN games) { var response = NetPeer.CreateMessage(); DiscoveredGame.WriteDiscoveryResponse(owner.appConfig, response, owner.GameInfo, IsFull, owner.NetworkApplication.GetDiscoveryData()); NetPeer.SendDiscoveryResponse(response, message.SenderEndPoint); } break; case NetIncomingMessageType.StatusChanged: var status = (NetConnectionStatus)message.ReadByte(); switch (status) { case NetConnectionStatus.Connected: HandleConnection(message.SenderConnection); break; case NetConnectionStatus.Disconnected: HandleDisconnection(message.SenderConnection, message); break; } break; case NetIncomingMessageType.UnconnectedData: HandleUnconnectedMessage(message); break; case NetIncomingMessageType.Data: HandleNetworkManagementFromClient(message); break; } } catch (NetworkDataException exception) { NetworkDataError(senderRemotePeer, exception); } }
public static DiscoveredGame FakeGame() { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var random = new Random(); var name = new string(Enumerable.Repeat(chars, 14).Select(s => s[random.Next(s.Length)]).ToArray()); var game = new DiscoveredGame(); game.GameInfo = new GameInfo(name, false, false); game.EndPoint = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65535); game.IsFull = true; return(game); }
public static DiscoveredGame ReadFromDiscoveryResponse(NetworkAppConfig appConfig, NetIncomingMessage message) { try { // START: Version safe data // { var theirAppId = message.ReadString(); if (theirAppId != appConfig.AppId) { return(null); // Wrong application } var gameName = message.ReadString().FilterName(); var theirAppVersion = message.ReadUInt16(); var theirAppSignatureLength = (int)message.ReadVariableUInt32(); byte[] theirAppSignature; if (theirAppSignatureLength < 0 || theirAppSignatureLength > NetworkAppConfig.ApplicationSignatureMaximumLength) { theirAppSignature = null; } else { theirAppSignature = message.ReadBytes(theirAppSignatureLength); } // } // END: Version safe data // Check for version mismatch if (theirAppVersion != appConfig.ApplicationVersion || theirAppSignature == null || !appConfig.ApplicationSignature.SequenceEqual(theirAppSignature)) { var gi = new GameInfo(gameName); var dg = new DiscoveredGame(message); dg.GameInfo = gi; if (theirAppVersion < appConfig.ApplicationVersion) { dg.VersionMismatch = -1; } else if (theirAppVersion > appConfig.ApplicationVersion) { dg.VersionMismatch = 1; } else { dg.VersionMismatch = 0; } Debug.Assert(dg.VersionMismatch.HasValue); return(dg); } // If we get here, all the versioning is correct: { var isInternetGame = message.ReadBoolean(); var gi = new GameInfo(gameName, isInternetGame, false); // <- NOTE: we are assuming that the side-channel handles discovery var dg = new DiscoveredGame(message); dg.GameInfo = gi; dg.IsFull = message.ReadBoolean(); dg.applicationData = message.ReadByteArray(); return(dg); } } catch { return(null); } }