/// <summary> /// Processes a RPC result message from server. /// </summary> /// <param name="message">Deserialized WireMessage that contains a MethodCallResultMessage or a RemoteInvocationException</param> /// <exception cref="KeyNotFoundException">Thrown, when the received result is of a unknown call</exception> private void ProcessRpcResultMessage(WireMessage message) { byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; Guid unqiueCallKey = message.UniqueCallKey == null ? Guid.Empty : new Guid(message.UniqueCallKey); if (!_activeCalls.TryGetValue(unqiueCallKey, out ClientRpcContext clientRpcContext)) { throw new KeyNotFoundException("Received a result for a unknown call."); } clientRpcContext.Error = message.Error; if (message.Error) { var remoteException = Serializer.Deserialize <RemoteInvocationException>( MessageEncryptionManager.GetDecryptedMessageData( message: message, serializer: Serializer, sharedSecret: sharedSecret, sendersPublicKeyBlob: _serverPublicKeyBlob, sendersPublicKeySize: _keyPair?.KeySize ?? 0)); clientRpcContext.RemoteException = remoteException; } else { try { var rawMessage = MessageEncryptionManager.GetDecryptedMessageData( message: message, serializer: Serializer, sharedSecret: sharedSecret, sendersPublicKeyBlob: _serverPublicKeyBlob, sendersPublicKeySize: _keyPair?.KeySize ?? 0); var resultMessage = Serializer .Deserialize <MethodCallResultMessage>(rawMessage); clientRpcContext.ResultMessage = resultMessage; } catch (Exception e) { Console.WriteLine(e); throw; } } clientRpcContext.WaitHandle.Set(); }
/// <summary> /// Authenticates this CoreRemoting client instance with the specified credentials. /// </summary> /// <exception cref="SecurityException">Thrown, if authentication failed or timed out</exception> private void Authenticate() { if (_config.Credentials == null || (_config.Credentials != null && _config.Credentials.Length == 0)) { return; } if (_authenticationCompletedWaitHandle.IsSet) { return; } byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var authRequestMessage = new AuthenticationRequestMessage() { Credentials = _config.Credentials }; var wireMessage = MessageEncryptionManager.CreateWireMessage( messageType: "auth", serializer: Serializer, serializedMessage: Serializer.Serialize(authRequestMessage), keyPair: _keyPair, sharedSecret: sharedSecret); byte[] rawData = Serializer.Serialize(wireMessage); _rawMessageTransport.LastException = null; _rawMessageTransport.SendMessage(rawData); if (_rawMessageTransport.LastException != null) { throw _rawMessageTransport.LastException; } _authenticationCompletedWaitHandle.Wait(_config.AuthenticationTimeout * 1000); if (!_authenticationCompletedWaitHandle.IsSet) { throw new SecurityException("Authentication timeout."); } if (!_isAuthenticated) { throw new SecurityException("Authentication failed. Please check credentials."); } }
private RemotingClient() { MethodCallMessageBuilder = new MethodCallMessageBuilder(); MessageEncryptionManager = new MessageEncryptionManager(); _proxyGenerator = new ProxyGenerator(); _activeCalls = new ConcurrentDictionary <Guid, ClientRpcContext>(); _cancellationTokenSource = new CancellationTokenSource(); _delegateRegistry = new ClientDelegateRegistry(); _handshakeCompletedWaitHandle = new ManualResetEventSlim(initialState: false); _authenticationCompletedWaitHandle = new ManualResetEventSlim(initialState: false); _goodbyeCompletedWaitHandle = new ManualResetEventSlim(initialState: false); }
/// <summary> /// Calls a method on a remote service synchronously. /// </summary> /// <param name="methodCallMessage">Details of the remote method to be invoked</param> /// <param name="oneWay">Invoke method without waiting for or processing result.</param> /// <returns>Results of the remote method invocation</returns> internal ClientRpcContext InvokeRemoteMethod(MethodCallMessage methodCallMessage, bool oneWay = false) { byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var clientRpcContext = new ClientRpcContext(); if (!_activeCalls.TryAdd(clientRpcContext.UniqueCallKey, clientRpcContext)) { throw new ApplicationException("Duplicate unique call key."); } var wireMessage = MessageEncryptionManager.CreateWireMessage( messageType: "rpc", serializer: Serializer, serializedMessage: Serializer.Serialize(methodCallMessage), sharedSecret: sharedSecret, keyPair: _keyPair, uniqueCallKey: clientRpcContext.UniqueCallKey.ToByteArray()); byte[] rawData = Serializer.Serialize(wireMessage); _rawMessageTransport.LastException = null; _rawMessageTransport.SendMessage(rawData); if (_rawMessageTransport.LastException != null) { throw _rawMessageTransport.LastException; } if (!oneWay && clientRpcContext.ResultMessage == null) { if (_config.InvocationTimeout <= 0) { clientRpcContext.WaitHandle.WaitOne(); } else { clientRpcContext.WaitHandle.WaitOne(_config.InvocationTimeout * 1000); } } return(clientRpcContext); }
/// <summary> /// Disconnects from the server. The server is actively notified about disconnection. /// </summary> public void Disconnect() { if (_channel != null && HasSession) { if (_keepSessionAliveTimer != null) { _keepSessionAliveTimer.Stop(); _keepSessionAliveTimer.Dispose(); _keepSessionAliveTimer = null; } byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var goodbyeMessage = new GoodbyeMessage() { SessionId = _sessionId }; var wireMessage = MessageEncryptionManager.CreateWireMessage( messageType: "goodbye", serializer: Serializer, serializedMessage: Serializer.Serialize(goodbyeMessage), keyPair: _keyPair, sharedSecret: sharedSecret); byte[] rawData = Serializer.Serialize(wireMessage); _goodbyeCompletedWaitHandle.Reset(); _channel.RawMessageTransport.SendMessage(rawData); _goodbyeCompletedWaitHandle.Wait(10000); } _channel?.Disconnect(); _handshakeCompletedWaitHandle?.Reset(); _authenticationCompletedWaitHandle?.Reset(); Identity = null; }
/// <summary> /// Creates a new instance of the RemotingServer class. /// </summary> /// <param name="config">Configuration settings to be used (Default configuration is used, if left null)</param> public RemotingServer(ServerConfig config = null) { _config = config ?? new ServerConfig(); _uniqueServerInstanceName = string.IsNullOrWhiteSpace(_config.UniqueServerInstanceName) ? Guid.NewGuid().ToString() : _config.UniqueServerInstanceName; _serverInstances.AddOrUpdate( key: _config.UniqueServerInstanceName, addValueFactory: uniqueInstanceName => this, updateValueFactory: (uniqueInstanceName, oldServer) => { oldServer?.Dispose(); return(this); }); SessionRepository = _config.SessionRepository ?? new SessionRepository( keySize: _config.KeySize, inactiveSessionSweepInterval: _config.InactiveSessionSweepInterval, maximumSessionInactivityTime: _config.MaximumSessionInactivityTime); _container = _config.DependencyInjectionContainer ?? new CastleWindsorDependencyInjectionContainer(); Serializer = _config.Serializer ?? new BsonSerializerAdapter(); MethodCallMessageBuilder = new MethodCallMessageBuilder(); MessageEncryptionManager = new MessageEncryptionManager(); _container.RegisterService <IDelegateProxyFactory, DelegateProxyFactory>( lifetime: ServiceLifetime.Singleton); _config.RegisterServicesAction?.Invoke(_container); Channel = _config.Channel ?? new WebsocketServerChannel(); Channel.Init(this); if (_config.IsDefault) { RemotingServer.DefaultRemotingServer ??= this; } }
/// <summary> /// Processes a remote delegate invocation message from server. /// </summary> /// <param name="message">Deserialized WireMessage that contains a RemoteDelegateInvocationMessage</param> private void ProcessRemoteDelegateInvocationMessage(WireMessage message) { byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var delegateInvocationMessage = Serializer .Deserialize <RemoteDelegateInvocationMessage>( MessageEncryptionManager.GetDecryptedMessageData( message: message, serializer: Serializer, sharedSecret: sharedSecret, sendersPublicKeyBlob: _serverPublicKeyBlob, sendersPublicKeySize: _keyPair?.KeySize ?? 0)); var localDelegate = _delegateRegistry.GetDelegateByHandlerKey(delegateInvocationMessage.HandlerKey); // Invoke local delegate with arguments from remote caller localDelegate.DynamicInvoke(delegateInvocationMessage.DelegateArguments); }
/// <summary> /// Processes a authentication response message from server. /// </summary> /// <param name="message">Deserialized WireMessage that contains a AuthenticationResponseMessage</param> private void ProcessAuthenticationResponseMessage(WireMessage message) { byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var authResponseMessage = Serializer .Deserialize <AuthenticationResponseMessage>( MessageEncryptionManager.GetDecryptedMessageData( message: message, serializer: Serializer, sharedSecret: sharedSecret, sendersPublicKeyBlob: _serverPublicKeyBlob, sendersPublicKeySize: _keyPair?.KeySize ?? 0)); _isAuthenticated = authResponseMessage.IsAuthenticated; Identity = _isAuthenticated ? authResponseMessage.AuthenticatedIdentity : null; _authenticationCompletedWaitHandle.Set(); }