/// <summary> /// Frees managed resources. /// </summary> public void Dispose() { BeforeDispose?.Invoke(); _keyPair?.Dispose(); _delegateProxyFactory = null; _delegateProxyCache.Clear(); _delegateProxyCache = null; _rawMessageTransport = null; }
/// <summary> /// Creates a new instance of the RemotingClient class. /// </summary> /// <param name="config">Configuration settings</param> public RemotingClient(ClientConfig config) : this() { if (config == null) { throw new ArgumentException("No config provided and no default configuration found."); } Serializer = config.Serializer ?? new BsonSerializerAdapter(); MessageEncryption = config.MessageEncryption; _config = config; if (MessageEncryption) { _keyPair = new RsaKeyPair(config.KeySize); } _channel = config.Channel ?? new WebsocketClientChannel(); _channel.Init(this); _rawMessageTransport = _channel.RawMessageTransport; _rawMessageTransport.ReceiveMessage += OnMessage; _rawMessageTransport.ErrorOccured += (s, exception) => { if (exception != null) { throw exception; } throw new NetworkException(s); }; _clientInstances.AddOrUpdate( key: config.UniqueClientInstanceName, addValueFactory: uniqueInstanceName => this, updateValueFactory: (uniqueInstanceName, oldClient) => { oldClient?.Dispose(); return(this); }); if (!config.IsDefault) { return; } RemotingClient.DefaultRemotingClient ??= this; }
/// <summary> /// Frees managed resources. /// </summary> public void Dispose() { if (RemotingClient.DefaultRemotingClient == this) { RemotingClient.DefaultRemotingClient = null; } _clientInstances.TryRemove(_config.UniqueClientInstanceName, out _); Disconnect(); _cancellationTokenSource.Cancel(); _delegateRegistry.Clear(); if (_rawMessageTransport != null) { _rawMessageTransport.ReceiveMessage -= OnMessage; _rawMessageTransport = null; } if (_channel != null) { _channel.Dispose(); _channel = null; } if (_handshakeCompletedWaitHandle != null) { _handshakeCompletedWaitHandle.Dispose(); _handshakeCompletedWaitHandle = null; } if (_authenticationCompletedWaitHandle != null) { _authenticationCompletedWaitHandle.Dispose(); _authenticationCompletedWaitHandle = null; } if (_goodbyeCompletedWaitHandle != null) { _goodbyeCompletedWaitHandle.Dispose(); _goodbyeCompletedWaitHandle = null; } _keyPair?.Dispose(); }
/// <summary> /// Creates a new session. /// </summary> /// <param name="clientPublicKey">Client's public key</param> /// <param name="server">Server instance</param> /// <param name="rawMessageTransport">Component that does the raw message transport</param> /// <returns>The newly created session</returns> public RemotingSession CreateSession(byte[] clientPublicKey, IRemotingServer server, IRawMessageTransport rawMessageTransport) { if (server == null) { throw new ArgumentException(nameof(server)); } if (rawMessageTransport == null) { throw new ArgumentNullException(nameof(rawMessageTransport)); } var session = new RemotingSession( KeySize, clientPublicKey, server, rawMessageTransport); _sessions.TryAdd(session.SessionId, session); return(session); }
/// <summary> /// Creates a new instance of the RemotingSession class. /// </summary> /// <param name="keySize">Key size of the RSA keys for asymmetric encryption</param> /// <param name="clientPublicKey">Public key of this session's client</param> /// <param name="server">Server instance, that hosts this session</param> /// <param name="rawMessageTransport">Component, that does the raw message transport (send and receive)</param> internal RemotingSession(int keySize, byte[] clientPublicKey, IRemotingServer server, IRawMessageTransport rawMessageTransport) { _sessionId = Guid.NewGuid(); _lastActivityTimestamp = DateTime.Now; _isAuthenticated = false; _keyPair = new RsaKeyPair(keySize); CreatedOn = DateTime.Now; _remoteDelegateInvocationEventAggregator = new RemoteDelegateInvocationEventAggregator(); _server = server ?? throw new ArgumentNullException(nameof(server)); _delegateProxyFactory = _server.ServiceRegistry.GetService <IDelegateProxyFactory>(); _delegateProxyCache = new ConcurrentDictionary <Guid, IDelegateProxy>(); _rawMessageTransport = rawMessageTransport ?? throw new ArgumentNullException(nameof(rawMessageTransport)); _clientPublicKeyBlob = clientPublicKey; _rawMessageTransport.ReceiveMessage += OnReceiveMessage; _rawMessageTransport.ErrorOccured += OnErrorOccured; MessageEncryption = clientPublicKey != null; WireMessage completeHandshakeMessage; if (MessageEncryption) { var encryptedSessionId = RsaKeyExchange.EncryptSecret( keySize: _server.SessionRepository.KeySize, receiversPublicKeyBlob: clientPublicKey, secretToEncrypt: _sessionId.ToByteArray(), sendersPublicKeyBlob: _keyPair.PublicKey); var rawContent = _server.Serializer.Serialize(encryptedSessionId); var signedMessageData = new SignedMessageData() { MessageRawData = rawContent, Signature = RsaSignature.CreateSignature( keySize: keySize, sendersPrivateKeyBlob: _keyPair.PrivateKey, rawData: rawContent) }; var rawData = _server.Serializer.Serialize(typeof(SignedMessageData), signedMessageData); completeHandshakeMessage = new WireMessage { MessageType = "complete_handshake", Data = rawData }; } else { completeHandshakeMessage = new WireMessage { MessageType = "complete_handshake", Data = _sessionId.ToByteArray() }; } _remoteDelegateInvocationEventAggregator.RemoteDelegateInvocationNeeded += (delegateType, uniqueCallKey, handlerKey, arguments) => { var sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var remoteDelegateInvocationMessage = new RemoteDelegateInvocationMessage { UniqueCallKey = uniqueCallKey, HandlerKey = handlerKey, DelegateArguments = arguments }; var remoteDelegateInvocationWebsocketMessage = _server.MessageEncryptionManager .CreateWireMessage( serializedMessage: _server.Serializer.Serialize(remoteDelegateInvocationMessage), serializer: _server.Serializer, sharedSecret: sharedSecret, keyPair: _keyPair, messageType: "invoke"); // Invoke remote delegate on client _rawMessageTransport.SendMessage( _server.Serializer.Serialize(remoteDelegateInvocationWebsocketMessage)); return(null); }; _rawMessageTransport.SendMessage(_server.Serializer.Serialize(completeHandshakeMessage)); }