public async Task <ServerHelloRequest> ClientHelloWithCookie(MasterServerSession session, ClientHelloWithCookieRequest request) { _logger.Verbose( $"Handling {nameof(ClientHelloWithCookieRequest)} " + $"(CertificateResponseId={request.CertificateResponseId}, " + $"Random='{BitConverter.ToString(request.Random)}', " + $"Cookie='{BitConverter.ToString(request.Cookie)}')." ); if (!request.Cookie.SequenceEqual(session.Cookie)) { _logger.Warning( $"Session sent {nameof(ClientHelloWithCookieRequest)} with a mismatching cookie " + $"(EndPoint='{session.EndPoint}', " + $"Cookie='{BitConverter.ToString(request.Cookie)}', " + $"Expected='{BitConverter.ToString(session.Cookie ?? new byte[0])}')." ); return(null); } if (!request.Random.SequenceEqual(session.ClientRandom)) { _logger.Warning( $"Session sent {nameof(ClientHelloWithCookieRequest)} with a mismatching client random " + $"(EndPoint='{session.EndPoint}', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"Expected='{BitConverter.ToString(session.ClientRandom ?? new byte[0])}')." ); return(null); } // Generate a server random session.ServerRandom = _randomProvider.GetRandom(); // Generate a key pair var keyPair = _diffieHellmanService.GetECKeyPair(); session.ServerPrivateKeyParameters = keyPair.PrivateKeyParameters; // Generate a signature var signature = MakeSignature(session.ClientRandom, session.ServerRandom, keyPair.PublicKey); await _messageDispatcher.SendWithRetry(session, new ServerCertificateRequest() { ResponseId = request.CertificateResponseId, Certificates = new List <byte[]>() { _certificate.RawData } }); return(new ServerHelloRequest { Random = session.ServerRandom, PublicKey = keyPair.PublicKey, Signature = signature }); }
public async Task <ConnectToServerResponse> ConnectToServer(MasterServerSession session, ConnectToServerRequest request) { _logger.Verbose( $"Handling {nameof(ConnectToServerRequest)} " + $"(UserId='{request.UserId}', " + $"UserName='******', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"PublicKey='{BitConverter.ToString(request.PublicKey)}', " + $"Secret='{request.Secret}', " + $"Code='{request.Code}', " + $"Password='******', " + $"UseRelay={request.UseRelay})." ); Server server = null; if (!String.IsNullOrEmpty(request.Code)) { server = await _serverRepository.GetServerByCode(request.Code); } else if (!String.IsNullOrEmpty(request.Secret)) { server = await _serverRepository.GetServer(request.Secret); } if (server is null) { return new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.InvalidCode } } ; if (server.CurrentPlayerCount >= server.MaximumPlayerCount) { return new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.ServerAtCapacity } } ; if (!_sessionService.TryGetSession(server.RemoteEndPoint, out var hostSession)) { _logger.Warning( "Failed to retrieve server host session while handling " + $"{nameof(ConnectToServerRequest)} " + $"(RemoteEndPoint='{server.RemoteEndPoint}', " + $"UserId='{request.UserId}', " + $"UserName='******', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"PublicKey='{BitConverter.ToString(request.PublicKey)}', " + $"Secret='{request.Secret}', " + $"Code='{request.Code}', " + $"Password='******', " + $"UseRelay={request.UseRelay})." ); return(new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.UnknownError }); } var connectingEndPoint = (IPEndPoint)session.EndPoint; var remoteEndPoint = (IPEndPoint)hostSession.EndPoint; if (request.UseRelay) { GetAvailableRelayServerResponse getAvailableRelayServerResponse; try { getAvailableRelayServerResponse = await _relayServerService.GetAvailableRelayServer( new GetAvailableRelayServerRequest( session.EndPoint.ToString() !, hostSession.EndPoint.ToString() ! ) ); } catch (TimeoutException e) { _logger.Error(e, "Failed to get an available relay server while handling " + $"{nameof(ConnectToServerRequest)} " + $"(RemoteEndPoint='{server.RemoteEndPoint}', " + $"UserId='{request.UserId}', " + $"UserName='******', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"PublicKey='{BitConverter.ToString(request.PublicKey)}', " + $"Secret='{request.Secret}', " + $"Code='{request.Code}', " + $"Password='******', " + $"UseRelay={request.UseRelay})." ); return(new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.NoAvailableDedicatedServers }); } if (!getAvailableRelayServerResponse.Success) { _logger.Warning( "No available relay servers while handling " + $"{nameof(ConnectToServerRequest)} " + $"(RemoteEndPoint='{server.RemoteEndPoint}', " + $"UserId='{request.UserId}', " + $"UserName='******', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"PublicKey='{BitConverter.ToString(request.PublicKey)}', " + $"Secret='{request.Secret}', " + $"Code='{request.Code}', " + $"Password='******', " + $"UseRelay={request.UseRelay})." ); return(new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.NoAvailableDedicatedServers }); } remoteEndPoint = IPEndPoint.Parse(getAvailableRelayServerResponse.RemoteEndPoint); connectingEndPoint = remoteEndPoint; } // Let the host know that someone is about to connect (hole-punch) await _messageDispatcher.SendWithRetry(hostSession, new PrepareForConnectionRequest { UserId = request.UserId, UserName = request.UserName, RemoteEndPoint = connectingEndPoint, Random = request.Random, PublicKey = request.PublicKey, IsConnectionOwner = false, IsDedicatedServer = false }); session.Secret = request.Secret; _logger.Information( "Successfully connected to server " + $"(RemoteEndPoint='{remoteEndPoint}', " + $"UserId='{request.UserId}', " + $"UserName='******', " + $"Random='{BitConverter.ToString(request.Random)}', " + $"PublicKey='{BitConverter.ToString(request.PublicKey)}', " + $"Secret='{request.Secret}', " + $"Code='{request.Code}', " + $"Password='******', " + $"UseRelay={request.UseRelay})." ); return(new ConnectToServerResponse { Result = ConnectToServerResponse.ResultCode.Success, UserId = server.Host.UserId, UserName = server.Host.UserName, Secret = server.Secret, DiscoveryPolicy = (DiscoveryPolicy)server.DiscoveryPolicy, InvitePolicy = (InvitePolicy)server.InvitePolicy, MaximumPlayerCount = server.MaximumPlayerCount, Configuration = new GameplayServerConfiguration() { BeatmapDifficultyMask = (BeatmapDifficultyMask)server.BeatmapDifficultyMask, GameplayModifiersMask = (GameplayModifiersMask)server.GameplayModifiersMask, SongPackBloomFilterTop = server.SongPackBloomFilterTop, SongPackBloomFilterBottom = server.SongPackBloomFilterBottom }, IsConnectionOwner = true, IsDedicatedServer = false, RemoteEndPoint = remoteEndPoint, Random = server.Random, PublicKey = server.PublicKey }); }