/// <summary> /// Should be called by derived classes, within a lock when the connection state has been changed. /// The caller should also make a sub-sequent call to <see cref="NotifyConnectionLost"/>, /// <see cref="NotifyConnectionFailed"/>, <see cref="NotifyDisconnected"/>, or <see cref="NotifyConnected"/> /// </summary> /// <param name="state"></param> protected void SetConnectionState(RpcConnectionState state) { if (this.connectionState != state) { this.connectionState = state; this.hasPendingStateChange = true; } }
private static Exception?TranslateConnectionException(Exception?ex, RpcConnectionState newState) { if (ex != null) { return(newState switch { RpcConnectionState.ConnectionLost => new RpcCommunicationException(RpcCommunicationStatus.ConnectionLost, "Lightweight connection lost.", ex), RpcConnectionState.ConnectionFailed => new RpcCommunicationException(RpcCommunicationStatus.Unavailable, "Failed to connect.", ex), _ => new RpcCommunicationException(RpcCommunicationStatus.Unknown, "Lightweight connection lost.", ex) });
protected void NotifyConnectionStateChanged() { RpcConnectionState state = this.ConnectionState; if (this.lastConnectionState != null && this.lastConnectionState == state) { return; } this.lastConnectionState = state; ConnectionStateChanged?.Invoke(this, state); }
protected void AssertIsConnected() { RpcConnectionState connectionState = this.ConnectionState; if (connectionState == RpcConnectionState.Connected) { return; } throw new RpcClientException( $"Client must be in {nameof(RpcConnectionState.Connected)} state, " + $"current state is {connectionState}"); }
protected void AssertNotAlreadyConnectedOrConnecting() { RpcConnectionState connectionState = this.ConnectionState; if (connectionState == RpcConnectionState.Connecting) { throw new RpcClientException("An attempt to connect while in process of connecting"); } if (connectionState == RpcConnectionState.Connected) { throw new RpcClientException("An attempt to connect when already connected"); } }
private async Task <RpcPipelineClient?> ResetConnectionAsync(RpcConnectionState state, Exception?ex) { TaskCompletionSource <RpcPipelineClient>?connectionTcs; RpcPipelineClient?connectedClient; lock (this.SyncRoot) { if (this.ConnectionState == RpcConnectionState.Disconnected) { // Already disconnected Debug.Assert(this.connectedClient == null); return(null); } connectedClient = this.connectedClient; this.connectedClient = null; connectionTcs = this.connectionTcs; this.connectionTcs = null; this.OnConnectionResetSynchronized(); this.SetConnectionState(state); } connectionTcs?.TrySetCanceled(); // TODO: wait for unfinished frames? if (connectedClient != null) { connectedClient.ReceiveLoopFaulted -= this.ConnectedClient_ReceiveLoopFaulted; await connectedClient.CloseAsync(TranslateConnectionException(ex, state)).ContextFree(); } return(connectedClient); }
private void ReadClientOnConnectionStateChanged(IRpcClient sender, RpcConnectionState state) { this.subscribedTopics.Clear(); }
private void RpcClientOnConnectionStateChanged(IRpcClient sender, RpcConnectionState state) { UnitySynchronizationContext.Instance.Post(o => UpdateConnectionStateUI(), null); }