/// <inheritdoc/> public async Task RegisterAsync(EndpointModel endpoint, Func <EndpointConnectivityState, Task> callback) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (callback == null) { throw new ArgumentNullException(nameof(callback)); } var id = new EndpointIdentifier(endpoint); if (!_callbacks.TryAdd(id, callback)) { _callbacks.AddOrUpdate(id, callback, (k, v) => callback); } await _lock.WaitAsync(); try { // Add a persistent session if (!_clients.TryGetValue(id, out var _)) { _clients.Add(id, new ClientSession( _opcApplicationConfig, id.Endpoint.Clone(), _logger, NotifyStateChangeAsync, true, _maxOpTimeout)); _logger.Debug("Open session for endpoint {id} ({endpoint}).", id, endpoint.Url); } } finally { _lock.Release(); } }
/// <inheritdoc/> public async Task UnregisterAsync(EndpointModel endpoint) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } var id = new EndpointIdentifier(endpoint); _callbacks.TryRemove(id, out _); await _lock.WaitAsync(); try { // Remove any session if (_clients.TryGetValue(id, out var client)) { await Try.Async(client.CloseAsync); Try.Op(client.Dispose); _clients.Remove(id); _logger.Debug("Endpoint {id} ({endpoint}) closed.", id, endpoint.Url); } else { _logger.Debug( "Session for endpoint {id} ({endpoint}) not found.", endpoint.Url, id); } } finally { _lock.Release(); } }
/// <inheritdoc/> public async Task UnregisterAsync(EndpointModel endpoint) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } var id = new EndpointIdentifier(endpoint); _callbacks.TryRemove(id, out _); await _lock.WaitAsync(); try { // Remove any session if (_clients.TryGetValue(id, out var client)) { await Try.Async(client.CloseAsync); _clients.Remove(id); } } finally { _lock.Release(); } }
/// <summary> /// Create session /// </summary> /// <param name="id"></param> /// <param name="persistent"></param> /// <returns></returns> internal IClientSession GetOrCreateSession(EndpointIdentifier id, bool persistent) { return(_clients.GetOrAdd(id, k => new ClientSession( CreateApplicationConfiguration(TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(2)), k.Endpoint, () => Certificate, _logger, NotifyStateChangeAsync, persistent, _maxOpTimeout))); }
IDisposable SubscribeStream() { EndpointIdentifier senderIdentifier = _identifier == EndpointIdentifier.Client ? EndpointIdentifier.Server : EndpointIdentifier.Client; return(_stream .Receive(senderIdentifier) .ObserveOn(NewThreadScheduler.Default) .Subscribe(packet => { _tracer.Verbose(ClientProperties.MqttChannel_ReceivedPacket(packet.Length)); _receiver.OnNext(packet); }, ex => { if (ex is ObjectDisposedException) { _receiver.OnError(new MqttException(ClientProperties.MqttChannel_StreamDisconnected, ex)); } else { _receiver.OnError(ex); } }, () => { _tracer.Warn(ClientProperties.MqttChannel_NetworkStreamCompleted); _receiver.OnCompleted(); })); }
/// <summary> /// Run export cycles /// </summary> /// <param name="id"></param> /// <param name="diagnostics"></param> /// <param name="ct"></param> /// <returns></returns> private async Task UploadModelAsync(EndpointIdentifier id, DiagnosticsModel diagnostics, CancellationToken ct) { var fullPath = Path.Combine(Path.GetTempPath(), FileName); try { _outer._logger.Information("Start model upload to {fileName} for {url}.", FileName, id.Endpoint.Url); using (var file = new FileStream(fullPath, FileMode.Create)) using (var stream = new GZipStream(file, CompressionMode.Compress)) { // TODO: Try read nodeset from namespace metadata! // ... // Otherwise browse model await BrowseEncodeModelAsync(id.Endpoint, diagnostics, stream, ct); } // now upload file await _outer._upload.SendFileAsync(fullPath, Encoding); _outer._logger.Information("Model uploaded to {fileName} for {url}.", FileName, id.Endpoint.Url); } catch (OperationCanceledException) { _outer._logger.Information("Cancelled model upload of {fileName} for {url}", FileName, id.Endpoint.Url); } catch (Exception ex) { _outer._logger.Error(ex, "Error during exportto {fileName} for {url}.", FileName, id.Endpoint.Url); } finally { File.Delete(fullPath); _outer._tasks.TryRemove(id, out var tmp); } }
/// <inheritdoc/> public Task <T> ExecuteServiceAsync <T>(EndpointModel endpoint, CredentialModel elevation, int priority, Func <Session, Task <T> > service, TimeSpan?timeout, CancellationToken ct, Func <Exception, bool> handler) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (string.IsNullOrEmpty(endpoint.Url)) { throw new ArgumentNullException(nameof(endpoint.Url)); } var key = new EndpointIdentifier(endpoint); while (!_cts.IsCancellationRequested) { var client = GetOrCreateSession(key); if (!client.Inactive) { var scheduled = client.TryScheduleServiceCall(elevation, priority, service, handler, timeout, ct, out var result); if (scheduled) { // Session is owning the task to completion now. return(result); } } // Create new session next go around EvictIfInactive(key); } return(Task.FromCanceled <T>(_cts.Token)); }
public void Send(byte[] payload, EndpointIdentifier identifier) { if (_disposed) { throw new ObjectDisposedException(nameof(PrivateStream)); } _payloadSequence.OnNext(Tuple.Create(payload, identifier)); }
public PrivateChannel(PrivateStream stream, EndpointIdentifier identifier, MqttConfiguration configuration) { this.stream = stream; this.identifier = identifier; receiver = new ReplaySubject <byte[]> (window: TimeSpan.FromSeconds(configuration.WaitTimeoutSecs)); sender = new ReplaySubject <byte[]> (window: TimeSpan.FromSeconds(configuration.WaitTimeoutSecs)); streamSubscription = SubscribeStream(); }
/// <summary> /// Notify about session/endpoint state changes /// </summary> /// <param name="ep"></param> /// <param name="state"></param> /// <returns></returns> private Task NotifyStateChangeAsync(EndpointModel ep, EndpointConnectivityState state) { var id = new EndpointIdentifier(ep); if (_callbacks.TryGetValue(id, out var cb)) { return(cb(state)); } return(Task.CompletedTask); }
/// <summary> /// Create model upload task /// </summary> /// <param name="outer"></param> /// <param name="id"></param> /// <param name="contentType"></param> /// <param name="diagnostics"></param> public ModelUploadTask(DataUploadServices outer, EndpointIdentifier id, string contentType, DiagnosticsModel diagnostics) { Encoding = ValidateEncoding(contentType, out var extension); StartTime = DateTime.UtcNow; FileName = $"{id.GetHashCode()}_{StartTime.ToBinary()}{extension}"; _outer = outer; _cts = new CancellationTokenSource(); _job = _outer._scheduler.Run(() => UploadModelAsync(id, diagnostics, _cts.Token)); }
public IObservable <byte[]> Receive(EndpointIdentifier identifier) { if (_disposed) { throw new ObjectDisposedException(nameof(PrivateStream)); } return(_payloadSequence .Where(t => t.Item2 == identifier) .Select(t => t.Item1)); }
/// <inheritdoc/> public Task Unregister(EndpointModel endpoint) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } var id = new EndpointIdentifier(endpoint); _callbacks.TryRemove(id, out _); // Remove persistent session if (_clients.TryRemove(id, out var client)) { return(Try.Async(client.CloseAsync)); } return(Task.CompletedTask); }
/// <summary> /// Handle inactive /// </summary> /// <param name="id"></param> /// <returns></returns> private void EvictIfInactive(EndpointIdentifier id) { _lock.Wait(); try { if (_clients.TryGetValue(id, out var item)) { if (item.Inactive && _clients.Remove(id)) { item.Dispose(); _logger.Debug("Evicted inactive session from session cache."); } } } finally { _lock.Release(); } }
/// <summary> /// Create session /// </summary> /// <param name="id"></param> /// <returns></returns> private IClientSession GetOrCreateSession(EndpointIdentifier id) { _lock.Wait(); try { if (!_clients.TryGetValue(id, out var session)) { session = new ClientSession( _opcApplicationConfig, id.Endpoint.Clone(), _logger, NotifyStateChangeAsync, false, _maxOpTimeout); _clients.Add(id, session); _logger.Debug("Add new session to session cache."); } return(session); } finally { _lock.Release(); } }
/// <inheritdoc/> public Task Register(EndpointModel endpoint, Func <EndpointConnectivityState, Task> callback) { if (endpoint == null) { throw new ArgumentNullException(nameof(endpoint)); } if (callback == null) { throw new ArgumentNullException(nameof(callback)); } var id = new EndpointIdentifier(endpoint); if (!_callbacks.TryAdd(id, callback)) { _callbacks.AddOrUpdate(id, callback, (k, v) => callback); } // Create persistent session GetOrCreateSession(id, true); return(Task.CompletedTask); }
/// <summary> /// Initializes a new instance of the <see cref="RxHciMessage"/> class. /// </summary> /// <param name="endpointIdentifier">the identifier of the endpoint.</param> /// <param name="payload">the payload.</param> protected RxHciMessage(EndpointIdentifier endpointIdentifier, IList <byte> payload) { EndpointIdentifier = endpointIdentifier; Payload = payload ?? throw new ArgumentNullException(nameof(payload)); }
public PrivateChannelFactory(ISubject <PrivateStream> privateStreamListener, EndpointIdentifier identifier, MqttConfiguration configuration) { this.privateStreamListener = privateStreamListener; this.identifier = identifier; this.configuration = configuration; }
/// <summary> /// Initializes a new instance of the <see cref="TxHciMessage"/> class. /// </summary> /// <param name="identifier">Identifier for destination endpoint.</param> /// <param name="payload">payload to be sent.</param> protected TxHciMessage(EndpointIdentifier identifier, List <byte>?payload) { EndpointIdentifier = identifier; Payload = payload; }
/// <summary> /// Creates an appropriate mail endpoint and forwards the SendMessageRequest to it /// for processing /// </summary> /// <returns></returns> public bool SendMail(SendMessageRequest message, EndpointIdentifier serviceIdentifier) { var mailEndpoint = _mailEndpointFactory.CreateEndpoint(serviceIdentifier); return mailEndpoint.SendMail(message); }
public PrivateBinding(ISubject <PrivateStream> privateStreamListener, EndpointIdentifier identifier) { this.privateStreamListener = privateStreamListener; this.identifier = identifier; }
/// <summary> /// Creates an IMailEndpoint for the given EndpointIdentifier /// </summary> public IMailEndpoint CreateEndpoint(EndpointIdentifier endpointIdentifier) { return(_scope.ResolveNamed <IMailEndpoint>(endpointIdentifier.ToString())); }