public void PublishDescription(ServerDescription description) { ServerTuple result; if (!_servers.TryGetValue(description.EndPoint, out result)) { throw new InvalidOperationException("Server does not exist."); } var oldDescription = result.Server.Description; if (result.Monitor == null) { var mockServer = Mock.Get(result.Server); mockServer.SetupGet(s => s.Description).Returns(description); mockServer.Raise(s => s.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(oldDescription, description)); } else { if (description.WireVersionRange != null) { var maxWireVersion = description.MaxWireVersion; var server = (Server)result.Server; var helloResult = new HelloResult(new BsonDocument { { "compressors", new BsonArray() }, { "maxWireVersion", maxWireVersion } }); var mockConnection = Mock.Get(server._connectionPool().AcquireConnection(CancellationToken.None)); mockConnection.SetupGet(c => c.Description) .Returns(new ConnectionDescription(new ConnectionId(description.ServerId, 0), helloResult)); } var mockMonitor = Mock.Get(result.Monitor); mockMonitor.SetupGet(m => m.Description).Returns(description); mockMonitor.Raise(m => m.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(oldDescription, description)); } }
private void ApplyResponse(BsonArray response) { if (response.Count != 2) { throw new FormatException($"Invalid response count: {response.Count}."); } var address = response[0].AsString; var helloDocument = response[1].AsBsonDocument; JsonDrivenHelper.EnsureAllFieldsAreValid(helloDocument, "hosts", "isWritablePrimary", OppressiveLanguageConstants.LegacyHelloResponseIsWritablePrimaryFieldName, "helloOk", "maxWireVersion", "minWireVersion", "ok", "primary", "secondary", "setName", "setVersion"); var endPoint = EndPointHelper.Parse(address); var helloResult = new HelloResult(helloDocument); var currentServerDescription = _serverFactory.GetServerDescription(endPoint); var newServerDescription = currentServerDescription.With( canonicalEndPoint: helloResult.Me, electionId: helloResult.ElectionId, replicaSetConfig: helloResult.GetReplicaSetConfig(), state: helloResult.Wrapped.GetValue("ok", false).ToBoolean() ? ServerState.Connected : ServerState.Disconnected, type: helloResult.ServerType, wireVersionRange: new Range <int>(helloResult.MinWireVersion, helloResult.MaxWireVersion)); var currentClusterDescription = _cluster.Description; _serverFactory.PublishDescription(newServerDescription); SpinWait.SpinUntil(() => !object.ReferenceEquals(_cluster.Description, currentClusterDescription), 100); // sometimes returns false and that's OK }
// methods /// <inheritdoc/> public void Authenticate(IConnection connection, ConnectionDescription description, CancellationToken cancellationToken) { Ensure.IsNotNull(connection, nameof(connection)); Ensure.IsNotNull(description, nameof(description)); // If we don't have SaslSupportedMechs as part of the response, that means we didn't piggyback the initial // hello or legacy hello request and should query the server (provided that the server >= 4.0), merging results into // a new ConnectionDescription if (!description.HelloResult.HasSaslSupportedMechs && Feature.ScramSha256Authentication.IsSupported(description.ServerVersion)) { var command = CustomizeInitialHelloCommand(HelloHelper.CreateCommand(_serverApi)); var helloProtocol = HelloHelper.CreateProtocol(command, _serverApi); var helloResult = HelloHelper.GetResult(connection, helloProtocol, cancellationToken); var mergedHelloResult = new HelloResult(description.HelloResult.Wrapped.Merge(helloResult.Wrapped)); description = new ConnectionDescription( description.ConnectionId, mergedHelloResult, description.BuildInfoResult); } var authenticator = GetOrCreateAuthenticator(connection, description); authenticator.Authenticate(connection, description, cancellationToken); }
public void CreateCommand_should_return_expected_result(ExplainVerbosity verbosity, string verbosityString) { var subject = new ExplainOperation(_databaseNamespace, _explainableOperation, _messageEncoderSettings) { Verbosity = verbosity }; var expectedResult = new BsonDocument { { "explain", BsonDocument.Parse("{ find : 'test' }") }, { "verbosity", verbosityString } }; var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(new ClusterId(), endPoint); var connectionId = new ConnectionId(serverId); var helloResult = new HelloResult(new BsonDocument { { "ok", 1 }, { "maxMessageSizeBytes", 48000000 }, { "maxWireVersion", WireVersion.Server36 } }); var connectionDescription = new ConnectionDescription(connectionId, helloResult); var session = NoCoreSession.Instance; var result = subject.CreateExplainCommand(connectionDescription, session); result.Should().Be(expectedResult); }
public async Task <string> ShowHelloAsync(HelloResult name) { var result = ShowHello(name); await Task.CompletedTask; return(result); }
public string ShowHello(HelloResult hello) { Console.WriteLine($"from wcf {hello.Name} call SayHello! [{ServiceName}]"); var result = $"from wcf name:{hello.Name};gender:{hello.Gender};avatar:{hello.Head} [{ServiceName}]"; return(result); }
// private methods private ConnectionDescription CreateConnectionDescription(int maxWireVersion) { var clusterId = new ClusterId(1); var serverId = new ServerId(clusterId, new DnsEndPoint("localhost", 27017)); var connectionId = new ConnectionId(serverId, 1); var helloResult = new HelloResult(new BsonDocument("maxWireVersion", maxWireVersion)); return(new ConnectionDescription(connectionId, helloResult)); }
public HelloResult SayHello(string name) { Console.WriteLine($"from wcf {name} call SayHello! [{ServiceName}]"); var result = new HelloResult { Name = $"from wcf {name} [{ServiceName}]", Gender = "male", Head = "head.png" }; return(result); }
// private methods private ConnectionDescription CreateConnectionDescription(SemanticVersion serverVersion) { var clusterId = new ClusterId(1); var serverId = new ServerId(clusterId, new DnsEndPoint("localhost", 27017)); var connectionId = new ConnectionId(serverId, 1); var helloResult = new HelloResult(new BsonDocument()); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", serverVersion.ToString() } }); return(new ConnectionDescription(connectionId, helloResult, buildInfoResult)); }
private ConnectionDescription CreateConnectionDescriptionSupportingSession(int maxWireVersion = WireVersion.Server36) { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var helloDocument = new BsonDocument { { "logicalSessionTimeoutMinutes", 30 }, { "maxWireVersion", maxWireVersion } }; var helloResult = new HelloResult(helloDocument); return(new ConnectionDescription(connectionId, helloResult)); }
private ConnectionDescription CreateConnectionDescriptionSupportingSession(string version = "3.6.0") { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var helloDocument = new BsonDocument { { "logicalSessionTimeoutMinutes", 30 } }; var helloResult = new HelloResult(helloDocument); var buildInfoDocument = new BsonDocument { { "version", version } }; var buildInfoResult = new BuildInfoResult(buildInfoDocument); return(new ConnectionDescription(connectionId, helloResult, buildInfoResult)); }
private ConnectionDescription CreateConnectionDescription(bool withLogicalSessionTimeout, bool?serviceId = null) { var clusterId = new ClusterId(1); var endPoint = new DnsEndPoint("localhost", 27017); var serverId = new ServerId(clusterId, endPoint); var connectionId = new ConnectionId(serverId, 1); var helloResultDocument = BsonDocument.Parse($"{{ ok : 1, maxWireVersion : {WireVersion.Server42} }}"); if (withLogicalSessionTimeout) { helloResultDocument["logicalSessionTimeoutMinutes"] = 1; helloResultDocument["msg"] = "isdbgrid"; // mongos } if (serviceId.HasValue) { helloResultDocument["serviceId"] = ObjectId.Empty; // load balancing mode } var helloResult = new HelloResult(helloResultDocument); var connectionDescription = new ConnectionDescription(connectionId, helloResult); return(connectionDescription); }
public void HandleChannelException_should_update_topology_as_expected_on_network_error_or_timeout( string errorType, bool shouldUpdateTopology) { var serverId = new ServerId(_clusterId, _endPoint); var connectionId = new ConnectionId(serverId); Exception innerMostException; switch (errorType) { case "MongoConnectionExceptionWithSocketTimeout": innerMostException = new SocketException((int)SocketError.TimedOut); break; case nameof(MongoConnectionException): innerMostException = new SocketException((int)SocketError.NetworkUnreachable); break; default: throw new ArgumentException("Unknown error type."); } var operationUsingChannelException = new MongoConnectionException(connectionId, "Oops", new IOException("Cry", innerMostException)); var mockConnection = new Mock <IConnectionHandle>(); var helloResult = new HelloResult(new BsonDocument { { "compressors", new BsonArray() }, { "maxWireVersion", WireVersion.Server44 } }); mockConnection.SetupGet(c => c.Description) .Returns(new ConnectionDescription(new ConnectionId(serverId, 0), helloResult)); var mockConnectionPool = new Mock <IConnectionPool>(); mockConnectionPool.Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>())).Returns(mockConnection.Object); mockConnectionPool.Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>())).ReturnsAsync(mockConnection.Object); var mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>(); mockConnectionPoolFactory .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint, It.IsAny <IConnectionExceptionHandler>())) .Returns(mockConnectionPool.Object); var mockMonitorServerInitialDescription = new ServerDescription(serverId, _endPoint).With(reasonChanged: "Initial D", type: ServerType.Unknown); var mockServerMonitor = new Mock <IServerMonitor>(); mockServerMonitor.SetupGet(m => m.Description).Returns(mockMonitorServerInitialDescription); mockServerMonitor.SetupGet(m => m.Lock).Returns(new object()); var mockServerMonitorFactory = new Mock <IServerMonitorFactory>(); mockServerMonitorFactory.Setup(f => f.Create(It.IsAny <ServerId>(), _endPoint)).Returns(mockServerMonitor.Object); var subject = new DefaultServer(_clusterId, _clusterClock, _clusterConnectionMode, _connectionModeSwitch, _directConnection, _settings, _endPoint, mockConnectionPoolFactory.Object, mockServerMonitorFactory.Object, _capturedEvents, _serverApi); subject.Initialize(); var heartbeatDescription = mockMonitorServerInitialDescription.With(reasonChanged: "Heartbeat", type: ServerType.Standalone); mockServerMonitor.Setup(m => m.Description).Returns(heartbeatDescription); mockServerMonitor.Raise( m => m.DescriptionChanged += null, new ServerDescriptionChangedEventArgs(mockMonitorServerInitialDescription, heartbeatDescription)); subject.Description.Should().Be(heartbeatDescription); subject.HandleChannelException(mockConnection.Object, operationUsingChannelException); if (shouldUpdateTopology) { subject.Description.Type.Should().Be(ServerType.Unknown); subject.Description.ReasonChanged.Should().Contain("ChannelException"); } else { subject.Description.Should().Be(heartbeatDescription); } }
private void ApplyApplicationError(BsonDocument applicationError) { var expectedKeys = new[] { "address", "generation", // optional "maxWireVersion", "when", "type", "response" // optional }; JsonDrivenHelper.EnsureAllFieldsAreValid(applicationError, expectedKeys); var address = applicationError["address"].AsString; var endPoint = EndPointHelper.Parse(address); var server = (Server)_serverFactory.GetServer(endPoint); var connectionId = new ConnectionId(server.ServerId); var type = applicationError["type"].AsString; var maxWireVersion = applicationError["maxWireVersion"].AsInt32; Exception simulatedException = null; switch (type) { case "command": var response = applicationError["response"].AsBsonDocument; var command = new BsonDocument("Link", "start!"); simulatedException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, command, response, "errmsg"); // can return null break; case "network": { var innerException = CoreExceptionHelper.CreateException("IOExceptionWithNetworkUnreachableSocketException"); simulatedException = new MongoConnectionException(connectionId, "Ignorance, yet knowledge.", innerException); break; } case "timeout": { var innerException = CoreExceptionHelper.CreateException("IOExceptionWithTimedOutSocketException"); simulatedException = new MongoConnectionException(connectionId, "Chaos, yet harmony.", innerException); break; } default: throw new ArgumentException($"Unsupported value of {type} for type"); } var mockConnection = new Mock <IConnectionHandle>(); var helloResult = new HelloResult(new BsonDocument { { "compressors", new BsonArray() } }); var serverVersion = WireVersionHelper.MapWireVersionToServerVersion(maxWireVersion); var buildInfoResult = new BuildInfoResult(new BsonDocument { { "version", serverVersion } }); mockConnection .SetupGet(c => c.Description) .Returns(new ConnectionDescription(connectionId, helloResult, buildInfoResult)); int generation = 0; if (applicationError.TryGetValue("generation", out var generationBsonValue)) { generation = generationBsonValue.AsInt32; if (simulatedException is MongoConnectionException mongoConnectionException) { mongoConnectionException.Generation = generation; } } mockConnection.SetupGet(c => c.Generation).Returns(generation); mockConnection .SetupGet(c => c.Generation) .Returns(generation); if (simulatedException != null) { var when = applicationError["when"].AsString; switch (when) { case "beforeHandshakeCompletes": server.HandleBeforeHandshakeCompletesException(simulatedException); break; case "afterHandshakeCompletes": server.HandleChannelException(mockConnection.Object, simulatedException); break; default: throw new ArgumentException($"Unsupported value of {when} for when."); } } }
public IEnumerator Connect( MonoBehaviour monoBehaviour, UnityAction <AsyncResult <bool> > callback ) { _webSocket.OnMessage -= this.OnMessageHandler; _webSocket.OnError -= this.OnErrorHandler; var done = false; var success = false; EventArgs args = null; Player[] players = null; var messageArgsList = new List <MessageEventArgs>(); void OnOpenHandler(object sender, EventArgs e) { // 完了フラグ・成功フラグを立てる Debug.Log("OnOpenHandler: " + e); done = true; success = true; } void OnErrorHandler(object sender, EventArgs e) { Debug.Log("OnErrorHandler: " + e); // 失敗理由を記録 args = e; } void OnCloseHandler(object sender, EventArgs e) { Debug.Log("OnCloseHandler: " + e); // 完了フラグを立てる done = true; } try { _webSocket.OnOpen += OnOpenHandler; _webSocket.OnError += OnErrorHandler; _webSocket.OnClose += OnCloseHandler; _webSocket.ConnectAsync(); for (var i = 0; i < 30 && !done; i++) { #if DISABLE_COROUTINE yield return(null); #else yield return(new WaitForSeconds(1)); #endif } if (!success) { // 失敗した場合は抜ける yield break; } success = false; done = false; Debug.Log("Hello"); HelloResult helloResult = null; void OnMessageHandler(object sender, EventArgs e) { // 認証処理の応答を処理するためのハンドラ Debug.Log("OnMessage: " + e.ToString()); if (e is MessageEventArgs data) { var(messageType, payload, sequenceNumber, lifeTimeMilliSeconds) = _messenger.Unpack(data.RawData); var message = _messenger.Parse(messageType, payload); if (message is Error error) { _eventQueue.Enqueue( new OnErrorEvent( error, sequenceNumber, lifeTimeMilliSeconds ) ); return; } else if (message is HelloResult) { helloResult = message as HelloResult; success = true; } else { messageArgsList.Add(data); } } else { args = e; } done = true; } try { _webSocket.OnMessage += OnMessageHandler; Debug.Log("SendAsync"); _webSocket.SendAsync( _messenger.Pack( new HelloRequest { AccessToken = _accessToken, MyProfile = Profile, } ), completed => { if (completed) { success = true; } done = true; } ); for (var i = 0; i < 30 && !done; i++) { #if DISABLE_COROUTINE yield return(null); #else yield return(new WaitForSeconds(1)); #endif } if (!success || helloResult == null) { // 失敗した場合は抜ける yield break; } MyConnectionId = helloResult.MyProfile.ConnectionId; players = helloResult.Players.ToArray(); Connected = true; } finally { _webSocket.OnMessage -= OnMessageHandler; } } finally { _webSocket.OnOpen -= OnOpenHandler; _webSocket.OnError -= OnErrorHandler; _webSocket.OnClose -= OnCloseHandler; callback.Invoke(new AsyncResult <bool>( success, success ? null : new ConnectionException(args) )); if (players != null) { foreach (var player in players) { _eventQueue.Enqueue( new OnJoinPlayerEvent( player, 0, 0 ) ); } } foreach (var e in messageArgsList) { this.OnMessageHandler(null, e); } _webSocket.OnMessage += this.OnMessageHandler; _webSocket.OnError += this.OnErrorHandler; } _monoBehaviour = monoBehaviour; if (monoBehaviour != null) { _dispatchCoroutine = monoBehaviour.StartCoroutine(Dispatch()); } }
private async Task HeartbeatAsync(CancellationToken cancellationToken) { CommandWireProtocol <BsonDocument> helloProtocol = null; bool processAnother = true; while (processAnother && !cancellationToken.IsCancellationRequested) { HelloResult heartbeatHelloResult = null; Exception heartbeatException = null; var previousDescription = _currentDescription; try { IConnection connection; lock (_lock) { connection = _connection; } if (connection == null) { var initializedConnection = await InitializeConnectionAsync(cancellationToken).ConfigureAwait(false); lock (_lock) { if (_state.Value == State.Disposed) { try { initializedConnection.Dispose(); } catch { } throw new OperationCanceledException("The ServerMonitor has been disposed."); } _connection = initializedConnection; _handshakeBuildInfoResult = _connection.Description.BuildInfoResult; heartbeatHelloResult = _connection.Description.HelloResult; } } else { // If MoreToCome is true, that means we are streaming hello or legacy hello results and must // continue using the existing helloProtocol object. // Otherwise helloProtocol has either not been initialized or we may need to switch between // heartbeat commands based on the last heartbeat response. if (helloProtocol == null || helloProtocol.MoreToCome == false) { helloProtocol = InitializeHelloProtocol(connection, previousDescription?.HelloOk ?? false); } heartbeatHelloResult = await GetHelloResultAsync(connection, helloProtocol, cancellationToken).ConfigureAwait(false); } } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { return; } catch (Exception ex) { IConnection toDispose = null; lock (_lock) { helloProtocol = null; heartbeatException = ex; _roundTripTimeMonitor.Reset(); toDispose = _connection; _connection = null; } toDispose?.Dispose(); } lock (_lock) { if (cancellationToken.IsCancellationRequested) { return; } } ServerDescription newDescription; if (heartbeatHelloResult != null) { if (_handshakeBuildInfoResult == null) { // we can be here only if there is a bug in the driver throw new ArgumentNullException("BuildInfo has been lost."); } var averageRoundTripTime = _roundTripTimeMonitor.Average; var averageRoundTripTimeRounded = TimeSpan.FromMilliseconds(Math.Round(averageRoundTripTime.TotalMilliseconds)); newDescription = _baseDescription.With( averageRoundTripTime: averageRoundTripTimeRounded, canonicalEndPoint: heartbeatHelloResult.Me, electionId: heartbeatHelloResult.ElectionId, helloOk: heartbeatHelloResult.HelloOk, lastWriteTimestamp: heartbeatHelloResult.LastWriteTimestamp, logicalSessionTimeout: heartbeatHelloResult.LogicalSessionTimeout, maxBatchCount: heartbeatHelloResult.MaxBatchCount, maxDocumentSize: heartbeatHelloResult.MaxDocumentSize, maxMessageSize: heartbeatHelloResult.MaxMessageSize, replicaSetConfig: heartbeatHelloResult.GetReplicaSetConfig(), state: ServerState.Connected, tags: heartbeatHelloResult.Tags, topologyVersion: heartbeatHelloResult.TopologyVersion, type: heartbeatHelloResult.ServerType, version: _handshakeBuildInfoResult.ServerVersion, wireVersionRange: new Range <int>(heartbeatHelloResult.MinWireVersion, heartbeatHelloResult.MaxWireVersion)); } else { newDescription = _baseDescription.With(lastUpdateTimestamp: DateTime.UtcNow); } if (heartbeatException != null) { var topologyVersion = default(Optional <TopologyVersion>); if (heartbeatException is MongoCommandException heartbeatCommandException) { topologyVersion = TopologyVersion.FromMongoCommandException(heartbeatCommandException); } newDescription = newDescription.With(heartbeatException: heartbeatException, topologyVersion: topologyVersion); } newDescription = newDescription.With(reasonChanged: "Heartbeat", lastHeartbeatTimestamp: DateTime.UtcNow); lock (_lock) { cancellationToken.ThrowIfCancellationRequested(); SetDescription(newDescription); } processAnother = // serverSupportsStreaming (newDescription.Type != ServerType.Unknown && heartbeatHelloResult != null && heartbeatHelloResult.TopologyVersion != null) || // connectionIsStreaming (helloProtocol != null && helloProtocol.MoreToCome) || // transitionedWithNetworkError (IsNetworkError(heartbeatException) && previousDescription.Type != ServerType.Unknown); } bool IsNetworkError(Exception ex) { return(ex is MongoConnectionException mongoConnectionException && mongoConnectionException.IsNetworkException); } }