public bool Subscribe(Guid correlationId, TcpPackageConnection connection) { Ensure.NotNull(connection, "connection"); if (_subscription != null || _unsubscribed != 0) return false; _correlationId = correlationId; connection.EnqueueSend(CreateSubscriptionPackage()); return true; }
private void HandleTcpPackage(TcpPackageConnection connection, TcpPackage package) { if (_connection != connection || _state == ConnectionState.Closed || _state == ConnectionState.Init) { LogDebug("IGNORED: HandleTcpPackage connId {0}, package {1}, {2}.", connection.ConnectionId, package.Command, package.CorrelationId); return; } LogDebug("HandleTcpPackage connId {0}, package {1}, {2}.", _connection.ConnectionId, package.Command, package.CorrelationId); _packageNumber += 1; if (package.Command == TcpCommand.HeartbeatResponseCommand) return; if (package.Command == TcpCommand.HeartbeatRequestCommand) { _connection.EnqueueSend(new TcpPackage(TcpCommand.HeartbeatResponseCommand, package.CorrelationId, null)); return; } if (package.Command == TcpCommand.Authenticated || package.Command == TcpCommand.NotAuthenticated) { if (_state == ConnectionState.Connecting && _connectingPhase == ConnectingPhase.Authentication && _authInfo.CorrelationId == package.CorrelationId) { if (package.Command == TcpCommand.NotAuthenticated) RaiseAuthenticationFailed("Not authenticated"); GoToConnectedState(); return; } } if (package.Command == TcpCommand.BadRequest && package.CorrelationId == Guid.Empty) { string message = Helper.EatException(() => Helper.UTF8NoBom.GetString(package.Data.Array, package.Data.Offset, package.Data.Count)); var exc = new EventStoreConnectionException( string.Format("Bad request received from server. Error: {0}", string.IsNullOrEmpty(message) ? "<no message>" : message)); CloseConnection("Connection-wide BadRequest received. Too dangerous to continue.", exc); return; } OperationItem operation; SubscriptionItem subscription; if (_operations.TryGetActiveOperation(package.CorrelationId, out operation)) { var result = operation.Operation.InspectPackage(package); LogDebug("HandleTcpPackage OPERATION DECISION {0} ({1}), {2}", result.Decision, result.Description, operation); switch (result.Decision) { case InspectionDecision.DoNothing: break; case InspectionDecision.EndOperation: _operations.RemoveOperation(operation); break; case InspectionDecision.Retry: _operations.ScheduleOperationRetry(operation); break; case InspectionDecision.Reconnect: ReconnectTo(new NodeEndPoints(result.TcpEndPoint, result.SecureTcpEndPoint)); _operations.ScheduleOperationRetry(operation); break; default: throw new Exception(string.Format("Unknown InspectionDecision: {0}", result.Decision)); } if (_state == ConnectionState.Connected) _operations.ScheduleWaitingOperations(connection); } else if (_subscriptions.TryGetActiveSubscription(package.CorrelationId, out subscription)) { var result = subscription.Operation.InspectPackage(package); LogDebug("HandleTcpPackage SUBSCRIPTION DECISION {0} ({1}), {2}", result.Decision, result.Description, subscription); switch (result.Decision) { case InspectionDecision.DoNothing: break; case InspectionDecision.EndOperation: _subscriptions.RemoveSubscription(subscription); break; case InspectionDecision.Retry: _subscriptions.ScheduleSubscriptionRetry(subscription); break; case InspectionDecision.Reconnect: ReconnectTo(new NodeEndPoints(result.TcpEndPoint, result.SecureTcpEndPoint)); _subscriptions.ScheduleSubscriptionRetry(subscription); break; case InspectionDecision.Subscribed: subscription.IsSubscribed = true; break; default: throw new Exception(string.Format("Unknown InspectionDecision: {0}", result.Decision)); } } else { LogDebug("HandleTcpPackage UNMAPPED PACKAGE with CorrelationId {0:B}, Command: {1}", package.CorrelationId, package.Command); } }
private void TcpConnectionEstablished(TcpPackageConnection connection) { if (_state != ConnectionState.Connecting || _connection != connection || connection.IsClosed) { LogDebug("IGNORED (_state {0}, _conn.Id {1:B}, conn.Id {2:B}, conn.closed {3}): TCP connection to [{4}, L{5}] established.", _state, _connection == null ? Guid.Empty : _connection.ConnectionId, connection.ConnectionId, connection.IsClosed, connection.RemoteEndPoint, connection.LocalEndPoint); return; } LogDebug("TCP connection to [{0}, L{1}, {2:B}] established.", connection.RemoteEndPoint, connection.LocalEndPoint, connection.ConnectionId); _heartbeatInfo = new HeartbeatInfo(_packageNumber, true, _stopwatch.Elapsed); if (_settings.DefaultUserCredentials != null) { _connectingPhase = ConnectingPhase.Authentication; _authInfo = new AuthInfo(Guid.NewGuid(), _stopwatch.Elapsed); _connection.EnqueueSend(new TcpPackage(TcpCommand.Authenticate, TcpFlags.Authenticated, _authInfo.CorrelationId, _settings.DefaultUserCredentials.Username, _settings.DefaultUserCredentials.Password, null)); } else { GoToConnectedState(); } }
private void TcpConnectionClosed(TcpPackageConnection connection) { if (_state == ConnectionState.Init) throw new Exception(); if (_state == ConnectionState.Closed || _connection != connection) { LogDebug("IGNORED (_state: {0}, _conn.ID: {1:B}, conn.ID: {2:B}): TCP connection to [{3}, L{4}] closed.", _state, _connection == null ? Guid.Empty : _connection.ConnectionId, connection.ConnectionId, connection.RemoteEndPoint, connection.LocalEndPoint); return; } _state = ConnectionState.Connecting; _connectingPhase = ConnectingPhase.Reconnecting; LogDebug("TCP connection to [{0}, L{1}, {2:B}] closed.", connection.RemoteEndPoint, connection.LocalEndPoint, connection.ConnectionId); _subscriptions.PurgeSubscribedAndDroppedSubscriptions(_connection.ConnectionId); _reconnInfo = new ReconnectionInfo(_reconnInfo.ReconnectionAttempt, _stopwatch.Elapsed); if (Interlocked.CompareExchange(ref _wasConnected, 0, 1) == 1) { RaiseDisconnected(connection.RemoteEndPoint); } }
private void CloseTcpConnection(string reason) { if (_connection == null) { LogDebug("CloseTcpConnection IGNORED because _connection == null"); return; } LogDebug("CloseTcpConnection"); _connection.Close(reason); TcpConnectionClosed(_connection); _connection = null; }
private void TcpConnectionError(TcpPackageConnection connection, Exception exception) { if (_connection != connection) return; if (_state == ConnectionState.Closed) return; LogDebug("TcpConnectionError connId {0:B}, exc {1}.", connection.ConnectionId, exception); CloseConnection("TCP connection error occurred.", exception); }
private void EstablishTcpConnection(NodeEndPoints endPoints) { var endPoint = _settings.UseSslConnection ? endPoints.SecureTcpEndPoint ?? endPoints.TcpEndPoint : endPoints.TcpEndPoint; if (endPoint == null) { CloseConnection("No end point to node specified."); return; } LogDebug("EstablishTcpConnection to [{0}]", endPoint); if (_state != ConnectionState.Connecting) return; if (_connectingPhase != ConnectingPhase.EndPointDiscovery) return; _connectingPhase = ConnectingPhase.ConnectionEstablishing; _connection = new TcpPackageConnection( _settings.Log, endPoint, Guid.NewGuid(), _settings.UseSslConnection, _settings.TargetHost, _settings.ValidateServer, _settings.ClientConnectionTimeout, (connection, package) => EnqueueMessage(new HandleTcpPackageMessage(connection, package)), (connection, exc) => EnqueueMessage(new TcpConnectionErrorMessage(connection, exc)), connection => EnqueueMessage(new TcpConnectionEstablishedMessage(connection)), (connection, error) => EnqueueMessage(new TcpConnectionClosedMessage(connection, error))); _connection.StartReceiving(); }
public void CheckTimeoutsAndRetry(TcpPackageConnection connection) { Ensure.NotNull(connection, "connection"); var retrySubscriptions = new List<SubscriptionItem>(); var removeSubscriptions = new List<SubscriptionItem>(); foreach (var subscription in _activeSubscriptions.Values) { if (subscription.IsSubscribed) continue; if (subscription.ConnectionId != connection.ConnectionId) { retrySubscriptions.Add(subscription); } else if (subscription.Timeout > TimeSpan.Zero && DateTime.UtcNow - subscription.LastUpdated > _settings.OperationTimeout) { var err = String.Format("EventStoreConnection '{0}': subscription never got confirmation from server.\n" + "UTC now: {1:HH:mm:ss.fff}, operation: {2}.", _connectionName, DateTime.UtcNow, subscription); _settings.Log.Error(err); if (_settings.FailOnNoServerResponse) { subscription.Operation.DropSubscription(SubscriptionDropReason.SubscribingError, new OperationTimedOutException(err)); removeSubscriptions.Add(subscription); } else { retrySubscriptions.Add(subscription); } } } foreach (var subscription in retrySubscriptions) { ScheduleSubscriptionRetry(subscription); } foreach (var subscription in removeSubscriptions) { RemoveSubscription(subscription); } if (_retryPendingSubscriptions.Count > 0) { foreach (var subscription in _retryPendingSubscriptions) { subscription.RetryCount += 1; StartSubscription(subscription, connection); } _retryPendingSubscriptions.Clear(); } while (_waitingSubscriptions.Count > 0) { StartSubscription(_waitingSubscriptions.Dequeue(), connection); } }
public void StartSubscription(SubscriptionItem subscription, TcpPackageConnection connection) { Ensure.NotNull(connection, "connection"); if (subscription.IsSubscribed) { LogDebug("StartSubscription REMOVING due to already subscribed {0}.", subscription); RemoveSubscription(subscription); return; } subscription.CorrelationId = Guid.NewGuid(); subscription.ConnectionId = connection.ConnectionId; subscription.LastUpdated = DateTime.UtcNow; _activeSubscriptions.Add(subscription.CorrelationId, subscription); if (!subscription.Operation.Subscribe(subscription.CorrelationId, connection)) { LogDebug("StartSubscription REMOVING AS COULDN'T SUBSCRIBE {0}.", subscription); RemoveSubscription(subscription); } else { LogDebug("StartSubscription SUBSCRIBING {0}.", subscription); } }
internal void DropSubscription(SubscriptionDropReason reason, Exception exc, TcpPackageConnection connection = null) { if (Interlocked.CompareExchange(ref _unsubscribed, 1, 0) == 0) { if (_verboseLogging) _log.Debug("Subscription {0:B} to {1}: closing subscription, reason: {2}, exception: {3}...", _correlationId, _streamId == string.Empty ? "<all>" : _streamId, reason, exc); if (reason != SubscriptionDropReason.UserInitiated) { if (exc == null) throw new Exception(string.Format("No exception provided for subscription drop reason '{0}", reason)); _source.TrySetException(exc); } if (reason == SubscriptionDropReason.UserInitiated && _subscription != null && connection != null) connection.EnqueueSend(CreateUnsubscriptionPackage()); if (_subscription != null) ExecuteActionAsync(() => _subscriptionDropped(_subscription, reason, exc)); } }
public TcpConnectionClosedMessage(TcpPackageConnection connection, SocketError error) { Ensure.NotNull(connection, "connection"); Connection = connection; Error = error; }
public TcpConnectionEstablishedMessage(TcpPackageConnection connection) { Ensure.NotNull(connection, "connection"); Connection = connection; }
public TcpConnectionErrorMessage(TcpPackageConnection connection, Exception exception) { Connection = connection; Exception = exception; }
public HandleTcpPackageMessage(TcpPackageConnection connection, TcpPackage package) { Connection = connection; Package = package; }