예제 #1
0
        /// <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");
            }
        }
예제 #2
0
        /// <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");
            }
        }