/// <summary> /// Initializes a new instance of the <see cref="AmqpConnectionScope"/> class. /// </summary> /// /// <param name="serviceEndpoint">Endpoint for the Service Bus service to which the scope is associated.</param> /// <param name="credential">The credential to use for authorization with the Service Bus service.</param> /// <param name="transport">The transport to use for communication.</param> /// <param name="proxy">The proxy, if any, to use for communication.</param> /// <param name="identifier">The identifier to assign this scope; if not provided, one will be generated.</param> /// public AmqpConnectionScope(Uri serviceEndpoint, ServiceBusTokenCredential credential, ServiceBusTransportType transport, IWebProxy proxy, string identifier = default) { Argument.AssertNotNull(serviceEndpoint, nameof(serviceEndpoint)); Argument.AssertNotNull(credential, nameof(credential)); ValidateTransport(transport); ServiceEndpoint = serviceEndpoint; Transport = transport; Proxy = proxy; TokenProvider = new CbsTokenProvider(new ServiceBusTokenCredential(credential, serviceEndpoint.ToString()), OperationCancellationSource.Token); Id = identifier ?? $"{ ServiceEndpoint }-{ Guid.NewGuid().ToString("D").Substring(0, 8) }"; Task <AmqpConnection> connectionFactory(TimeSpan timeout) => CreateAndOpenConnectionAsync(AmqpVersion, ServiceEndpoint, Transport, Proxy, Id, timeout); ActiveConnection = new FaultTolerantAmqpObject <AmqpConnection>( connectionFactory, CloseConnection); TransactionController = new FaultTolerantAmqpObject <Controller>( CreateControllerAsync, CloseController); }
/// <summary> /// Initializes a new instance of the <see cref="AmqpConnectionScope"/> class. /// </summary> /// /// <param name="serviceEndpoint">Endpoint for the Service Bus service to which the scope is associated.</param> /// <param name="credential">The credential to use for authorization with the Service Bus service.</param> /// <param name="transport">The transport to use for communication.</param> /// <param name="proxy">The proxy, if any, to use for communication.</param> /// <param name="identifier">The identifier to assign this scope; if not provided, one will be generated.</param> /// public AmqpConnectionScope(Uri serviceEndpoint, ServiceBusTokenCredential credential, ServiceBusTransportType transport, IWebProxy proxy, string identifier = default) { Argument.AssertNotNull(serviceEndpoint, nameof(serviceEndpoint)); Argument.AssertNotNull(credential, nameof(credential)); ValidateTransport(transport); ServiceEndpoint = serviceEndpoint; Transport = transport; Proxy = proxy; TokenProvider = new CbsTokenProvider(new ServiceBusTokenCredential(credential, serviceEndpoint.ToString()), OperationCancellationSource.Token); Id = identifier ?? $"{ ServiceEndpoint }-{ Guid.NewGuid().ToString("D", CultureInfo.InvariantCulture).Substring(0, 8) }"; #pragma warning disable CA2214 // Do not call overridable methods in constructors. This internal method is virtual for testing purposes. Task <AmqpConnection> connectionFactory(TimeSpan timeout) => CreateAndOpenConnectionAsync(AmqpVersion, ServiceEndpoint, Transport, Proxy, Id, timeout); #pragma warning restore CA2214 // Do not call overridable methods in constructors ActiveConnection = new FaultTolerantAmqpObject <AmqpConnection>( connectionFactory, CloseConnection); TransactionController = new FaultTolerantAmqpObject <Controller>( CreateControllerAsync, CloseController); }
/// <summary> /// Builds the audience of the connection for use in the signature. /// </summary> /// /// <param name="transportType">The type of protocol and transport that will be used for communicating with the Service Bus service.</param> /// <param name="fullyQualifiedNamespace">The fully qualified Service Bus namespace. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param> /// <param name="entityName">The name of the specific entity to connect the client to.</param> /// /// <returns>The value to use as the audience of the signature.</returns> /// internal static string BuildConnectionResource( ServiceBusTransportType transportType, string fullyQualifiedNamespace, string entityName) { // If there is no namespace, there is no basis for a URL and the // resource is empty. if (string.IsNullOrEmpty(fullyQualifiedNamespace)) { return(string.Empty); } var builder = new UriBuilder(fullyQualifiedNamespace) { Scheme = transportType.GetUriScheme(), Path = entityName, Port = -1, Fragment = string.Empty, Password = string.Empty, UserName = string.Empty, }; if (builder.Path.EndsWith("/", StringComparison.Ordinal)) { builder.Path = builder.Path.TrimEnd('/'); } return(builder.Uri.AbsoluteUri.ToLowerInvariant()); }
/// <summary> /// Initializes a new instance of the <see cref="ServiceBusConnection"/> class. /// </summary> /// /// <param name="connectionString">The connection string to use for connecting to the Service Bus namespace.</param> /// <param name="options">A set of options to apply when configuring the connection.</param> /// /// <remarks> /// If the connection string is copied from the Service Bus entity itself, it will contain the name of the desired Service Bus entity, /// and can be used directly without passing the name="entityName" />. The name of the Service Bus entity should be /// passed only once, either as part of the connection string or separately. /// </remarks> /// internal ServiceBusConnection( string connectionString, ServiceBusClientOptions options) { Argument.AssertNotNullOrEmpty(connectionString, nameof(connectionString)); Argument.AssertNotNull(options, nameof(options)); options = options.Clone(); ValidateConnectionOptions(options); var builder = new ServiceBusConnectionStringBuilder(connectionString); FullyQualifiedNamespace = builder.FullyQualifiedNamespace; TransportType = options.TransportType; EntityPath = builder.EntityName; var sharedAccessSignature = new SharedAccessSignature ( BuildAudienceResource(options.TransportType, FullyQualifiedNamespace, EntityPath), builder.SasKeyName, builder.SasKey ); var sharedCredentials = new SharedAccessSignatureCredential(sharedAccessSignature); var tokenCredentials = new ServiceBusTokenCredential( sharedCredentials, BuildAudienceResource(options.TransportType, FullyQualifiedNamespace, EntityPath)); _innerClient = CreateTransportClient(tokenCredentials, options); }
/// <summary> /// Initializes a new instance of the <see cref="ServiceBusConnection"/> class. /// </summary> /// /// <param name="fullyQualifiedNamespace">The fully qualified Service Bus namespace to connect to. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param> /// <param name="credential">The Azure managed identity credential to use for authorization. Access controls may be specified by the Service Bus namespace or the requested Service Bus entity, depending on Azure configuration.</param> /// <param name="options">A set of options to apply when configuring the connection.</param> /// internal ServiceBusConnection( string fullyQualifiedNamespace, TokenCredential credential, ServiceBusClientOptions options) { Argument.AssertNotNullOrEmpty(fullyQualifiedNamespace, nameof(fullyQualifiedNamespace)); Argument.AssertNotNull(credential, nameof(credential)); Argument.AssertNotNull(options, nameof(options)); options = options.Clone(); ValidateConnectionOptions(options); switch (credential) { case SharedAccessSignatureCredential _: break; case ServiceBusSharedKeyCredential sharedKeyCredential: credential = sharedKeyCredential.AsSharedAccessSignatureCredential(BuildAudienceResource(options.TransportType, fullyQualifiedNamespace, EntityPath)); break; } var tokenCredential = new ServiceBusTokenCredential(credential, BuildAudienceResource(options.TransportType, fullyQualifiedNamespace, EntityPath)); FullyQualifiedNamespace = fullyQualifiedNamespace; TransportType = options.TransportType; _innerClient = CreateTransportClient(tokenCredential, options); }
public MockConnectionMockScope( Uri serviceEndpoint, ServiceBusTokenCredential credential, ServiceBusTransportType transport, IWebProxy proxy) : base(serviceEndpoint, credential, transport, proxy) { MockConnection = new Mock <AmqpConnection>(new MockTransport(), CreateMockAmqpSettings(), new AmqpConnectionSettings()); }
/// <summary> /// Translates an <see cref="ServiceBusSharedAccessKeyCredential"/> into the equivalent shared access signature credential. /// </summary> /// /// <param name="credential">The credential to translate.</param> /// <param name="fullyQualifiedNamespace">The fully qualified Service Bus namespace being connected to.</param> /// <param name="entityPath">The path of the entity being connected to.</param> /// <param name="transportType">The type of transport being used for the connection.</param> /// /// <returns>The <see cref="SharedAccessSignatureCredential" /> which the <paramref name="credential" /> was translated into.</returns> /// internal static SharedAccessSignatureCredential TranslateSharedKeyCredential(ServiceBusSharedAccessKeyCredential credential, string fullyQualifiedNamespace, string entityPath, ServiceBusTransportType transportType) { if ((credential == null) || (string.IsNullOrEmpty(fullyQualifiedNamespace))) { return(null); } return(credential.AsSharedAccessSignatureCredential(BuildConnectionResource(transportType, fullyQualifiedNamespace, entityPath))); }
/// <summary> /// Determines the URI scheme to be used for the given connection type. /// </summary> /// /// <param name="instance">The instance that this method was invoked on.</param> /// /// <returns>The scheme that should be used for the given connection type when forming an associated URI.</returns> /// public static string GetUriScheme(this ServiceBusTransportType instance) { switch (instance) { case ServiceBusTransportType.AmqpTcp: case ServiceBusTransportType.AmqpWebSockets: return(AmqpUriScheme); default: throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.InvalidTransportType, instance.ToString(), nameof(instance))); } }
/// <summary> /// Creates an AMQP connection for a given scope. /// </summary> /// /// <param name="amqpVersion">The version of AMQP to use for the connection.</param> /// <param name="serviceEndpoint">The endpoint for the Service Bus service to which the scope is associated.</param> /// <param name="transportType">The type of transport to use for communication.</param> /// <param name="proxy">The proxy, if any, to use for communication.</param> /// <param name="scopeIdentifier">The unique identifier for the associated scope.</param> /// <param name="timeout">The timeout to consider when creating the connection.</param> /// /// <returns>An AMQP connection that may be used for communicating with the Service Bus service.</returns> /// protected virtual async Task <AmqpConnection> CreateAndOpenConnectionAsync( Version amqpVersion, Uri serviceEndpoint, ServiceBusTransportType transportType, IWebProxy proxy, string scopeIdentifier, TimeSpan timeout) { var hostName = serviceEndpoint.Host; AmqpSettings amqpSettings = CreateAmpqSettings(AmqpVersion); AmqpConnectionSettings connectionSetings = CreateAmqpConnectionSettings(hostName, scopeIdentifier); TransportSettings transportSettings = transportType.IsWebSocketTransport() ? CreateTransportSettingsForWebSockets(hostName, proxy) : CreateTransportSettingsforTcp(hostName, serviceEndpoint.Port); // Create and open the connection, respecting the timeout constraint // that was received. var stopWatch = Stopwatch.StartNew(); var initiator = new AmqpTransportInitiator(amqpSettings, transportSettings); TransportBase transport = await initiator.ConnectTaskAsync(timeout).ConfigureAwait(false); var connection = new AmqpConnection(transport, amqpSettings, connectionSetings); await OpenAmqpObjectAsync(connection, timeout.CalculateRemaining(stopWatch.Elapsed)).ConfigureAwait(false); stopWatch.Stop(); // Create the CBS link that will be used for authorization. The act of creating the link will associate // it with the connection. new AmqpCbsLink(connection); // When the connection is closed, close each of the links associated with it. EventHandler closeHandler = null; closeHandler = (snd, args) => { foreach (var link in ActiveLinks.Keys) { link.SafeClose(); } connection.Closed -= closeHandler; }; connection.Closed += closeHandler; return(connection); }
internal static string ToSerializedValue(this ServiceBusTransportType value) { switch( value ) { case ServiceBusTransportType.NotSpecified: return "NotSpecified"; case ServiceBusTransportType.NetMessaging: return "NetMessaging"; case ServiceBusTransportType.AMQP: return "AMQP"; } return null; }
/// <summary> /// Builds the audience for use in the signature. /// </summary> /// /// <param name="transportType">The type of protocol and transport that will be used for communicating with the Service Bus service.</param> /// <param name="fullyQualifiedNamespace">The fully qualified Service Bus namespace. This is likely to be similar to <c>{yournamespace}.servicebus.windows.net</c>.</param> /// <param name="entityName">The name of the specific entity to connect the client to.</param> /// /// <returns>The value to use as the audience of the signature.</returns> /// private static string BuildAudienceResource(ServiceBusTransportType transportType, string fullyQualifiedNamespace, string entityName) { var builder = new UriBuilder(fullyQualifiedNamespace) { Scheme = transportType.GetUriScheme(), Path = entityName, Port = -1, Fragment = string.Empty, Password = string.Empty, UserName = string.Empty, }; if (builder.Path.EndsWith("/")) { builder.Path = builder.Path.TrimEnd('/'); } return(builder.Uri.AbsoluteUri.ToLowerInvariant()); }
/// <summary> /// Instantiates a new <see cref="ServiceBusConnectionStringBuilder"/>. /// </summary> /// <example> /// <code> /// var connectionStringBuilder = new ServiceBusConnectionStringBuilder( /// "contoso.servicebus.windows.net", /// "myQueue", /// "{ ... SAS token ... }", /// TransportType.Amqp /// ); /// </code> /// </example> /// <param name="endpoint">Fully qualified endpoint.</param> /// <param name="entityPath"></param> /// <param name="sharedAccessSignature"></param> /// <param name="transportType"></param> public ServiceBusConnectionStringBuilder(string endpoint, string entityPath, string sharedAccessSignature, ServiceBusTransportType transportType) : this(endpoint, entityPath, sharedAccessSignature) { this.TransportType = transportType; }
private static ITransport GetTransportByType(ServiceBusTransportType transportType) { return _transportMap[transportType]; }
/// <summary> /// Determines whether the specified transport makes use of web sockets. /// </summary> /// /// <param name="instance">The instance that this method was invoked on.</param> /// /// <returns><c>true</c> if the transport uses web sockets; otherwise, <c>false</c>.</returns> /// public static bool IsWebSocketTransport(this ServiceBusTransportType instance) => (instance == ServiceBusTransportType.AmqpWebSockets);