/// <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"); } }
public async Task <RequestNameReply> RequestNameAsync(string name, RequestNameOptions options, Action onAquired, Action onLost, SynchronizationContext synchronzationContext) { lock (_gate) { ThrowIfNotConnected(); ThrowIfRemoteIsNotBus(); if (_serviceNameRegistrations.ContainsKey(name)) { throw new InvalidOperationException("The name is already requested"); } _serviceNameRegistrations[name] = new ServiceNameRegistration { OnAquire = onAquired, OnLost = onLost, SynchronizationContext = synchronzationContext }; } try { var reply = await CallRequestNameAsync(name, options); return(reply); } catch { lock (_gate) { _serviceNameRegistrations.Remove(name); } throw; } }
private async Task <RequestNameReply> CallRequestNameAsync(string name, RequestNameOptions options) { var writer = new MessageWriter(); writer.WriteString(name); writer.WriteUInt32((uint)options); Message callMsg = new Message( new Header(MessageType.MethodCall) { Path = DBusObjectPath, Interface = DBusInterface, Member = "RequestName", Destination = DBusServiceName, Signature = "su" }, writer.ToArray(), writer.UnixFds ); Message reply = await CallMethodAsync(callMsg, checkConnected : true, checkReplyType : true); var reader = new MessageReader(reply, null); var rv = reader.ReadUInt32(); return((RequestNameReply)rv); }
/// <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"); } }