/// <summary> /// Queues a service name registration for the connection. /// </summary> /// <param name="serviceName">Name of the service.</param> /// <param name="onAquired">Action invoked when the service name is assigned to the connection.</param> /// <param name="onLost">Action invoked when the service name is no longer assigned to the connection.</param> /// <param name="options">Options for the registration.</param> /// <exception cref="ObjectDisposedException">The connection has been disposed.</exception> /// <exception cref="InvalidOperationException">The operation is invalid in the current state.</exception> /// <exception cref="DisconnectedException">The connection was closed after it was established.</exception> /// <exception cref="DBusException">Error returned by remote peer.</exception> /// <exception cref="ProtocolException">Unexpected reply.</exception> /// <remarks> /// This operation is not supported for AutoConnection connections. /// </remarks> public async Task QueueServiceRegistrationAsync(string serviceName, Action onAquired = null, Action onLost = null, ServiceRegistrationOptions options = ServiceRegistrationOptions.Default) { CheckNotConnectionType(ConnectionType.ClientAutoConnect); var connection = GetConnectedConnection(); if (!options.HasFlag(ServiceRegistrationOptions.AllowReplacement) && (onLost != null)) { throw new ArgumentException($"{nameof(onLost)} can only be set when {nameof(ServiceRegistrationOptions.AllowReplacement)} is also set", nameof(onLost)); } RequestNameOptions requestOptions = RequestNameOptions.None; if (options.HasFlag(ServiceRegistrationOptions.ReplaceExisting)) { requestOptions |= RequestNameOptions.ReplaceExisting; } if (options.HasFlag(ServiceRegistrationOptions.AllowReplacement)) { requestOptions |= RequestNameOptions.AllowReplacement; } var reply = await connection.RequestNameAsync(serviceName, requestOptions, onAquired, onLost, CaptureSynchronizationContext()); switch (reply) { case RequestNameReply.PrimaryOwner: case RequestNameReply.InQueue: return; case RequestNameReply.Exists: case RequestNameReply.AlreadyOwner: default: throw new ProtocolException("Unexpected reply"); } }
/// <summary> /// Requests a service name to be assigned to the connection. /// </summary> /// <param name="serviceName">Name of the service.</param> /// <param name="onLost">Action invoked when the service name is no longer assigned to the connection.</param> /// <param name="options"></param> /// <exception cref="ObjectDisposedException">The connection has been disposed.</exception> /// <exception cref="InvalidOperationException">The operation is invalid in the current state.</exception> /// <exception cref="DisconnectedException">The connection was closed after it was established.</exception> /// <exception cref="DBusException">Error returned by remote peer.</exception> /// <remarks> /// This operation is not supported for AutoConnection connections. /// </remarks> public async Task RegisterServiceAsync(string serviceName, Action onLost = null, ServiceRegistrationOptions options = ServiceRegistrationOptions.Default) { CheckNotConnectionType(ConnectionType.ClientAutoConnect); var connection = GetConnectedConnection(); if (!options.HasFlag(ServiceRegistrationOptions.AllowReplacement) && (onLost != null)) { throw new ArgumentException($"{nameof(onLost)} can only be set when {nameof(ServiceRegistrationOptions.AllowReplacement)} is also set", nameof(onLost)); } RequestNameOptions requestOptions = RequestNameOptions.DoNotQueue; if (options.HasFlag(ServiceRegistrationOptions.ReplaceExisting)) { requestOptions |= RequestNameOptions.ReplaceExisting; } if (options.HasFlag(ServiceRegistrationOptions.AllowReplacement)) { requestOptions |= RequestNameOptions.AllowReplacement; } var reply = await connection.RequestNameAsync(serviceName, requestOptions, null, onLost, CaptureSynchronizationContext()).ConfigureAwait(false); switch (reply) { case RequestNameReply.PrimaryOwner: return; case RequestNameReply.Exists: throw new InvalidOperationException("Service is registered by another connection"); case RequestNameReply.AlreadyOwner: throw new InvalidOperationException("Service is already registered by this connection"); case RequestNameReply.InQueue: default: throw new ProtocolException("Unexpected reply"); } }
public static async Task <RequestNameReply> RegisterServiceCallback(this IConnection connection, string serviceName, ServiceRegistrationOptions options = ServiceRegistrationOptions.Default, Action <string> onAquired = null, Action <string> onLost = null) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (string.IsNullOrEmpty(serviceName)) { throw new ArgumentNullException(nameof(serviceName)); } IDisposable acquireDisposer = null; if (onAquired != null) { acquireDisposer = await connection.DBus.WatchNameAcquired(name => { if (name == serviceName) { onAquired(name); var c = acquireDisposer; if (c != null) { c.Dispose(); } } }); } IDisposable lostDisposer = null; if (onLost != null) { lostDisposer = await connection.DBus.WatchNameLost(name => { if (name == serviceName) { onLost(name); var c = lostDisposer; if (c != null) { c.Dispose(); } } }); } var requestOptions = RequestNameOptions.None; if (options.HasFlag(ServiceRegistrationOptions.ReplaceExisting)) { requestOptions |= RequestNameOptions.ReplaceExisting; } if (options.HasFlag(ServiceRegistrationOptions.AllowReplacement)) { requestOptions |= RequestNameOptions.AllowReplacement; } try { return(await connection.DBus.RequestName(serviceName, requestOptions)); } catch (Exception) { if (acquireDisposer != null) { acquireDisposer.Dispose(); } if (lostDisposer != null) { lostDisposer.Dispose(); } throw; } }
/// <summary> /// Register service name and wait (Task) until name acquired. /// </summary> /// <param name="connection"></param> /// <param name="serviceName"></param> /// <param name="options"></param> /// <param name="cancellationToken"></param> /// <param name="onLost"></param> /// <returns></returns> public static async Task RegisterServiceWait(this IConnection connection, string serviceName, ServiceRegistrationOptions options = ServiceRegistrationOptions.Default, Action <string> onLost = null, CancellationToken cancellationToken = default(CancellationToken)) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (string.IsNullOrEmpty(serviceName)) { throw new ArgumentNullException(nameof(serviceName)); } var tcs = new TaskCompletionSource <bool>(); IDisposable acquireDisposer = null; acquireDisposer = await connection.DBus.WatchNameAcquired(name => { if (name == serviceName) { tcs.TrySetResult(true); var c = acquireDisposer; if (c != null) { c.Dispose(); } } }); IDisposable lostDisposer = null; if (onLost != null) { lostDisposer = await connection.DBus.WatchNameLost(name => { if (name == serviceName) { onLost(name); var c = lostDisposer; if (c != null) { c.Dispose(); } tcs.TrySetResult(false); } }); } var requestOptions = RequestNameOptions.None; if (options.HasFlag(ServiceRegistrationOptions.ReplaceExisting)) { requestOptions |= RequestNameOptions.ReplaceExisting; } if (options.HasFlag(ServiceRegistrationOptions.AllowReplacement)) { requestOptions |= RequestNameOptions.AllowReplacement; } RequestNameReply reply; try { reply = await connection.DBus.RequestName(serviceName, requestOptions); } catch (Exception) { if (acquireDisposer != null) { acquireDisposer.Dispose(); } if (lostDisposer != null) { lostDisposer.Dispose(); } throw; } switch (reply) { case RequestNameReply.AlreadyOwner: case RequestNameReply.PrimaryOwner: return; case RequestNameReply.Exists: case RequestNameReply.InQueue: if (cancellationToken.CanBeCanceled) { cancellationToken.Register(() => tcs.TrySetCanceled()); } if (await tcs.Task) { return; } throw new InvalidOperationException("Name could not be acquired"); } }