Skip to content

Commit d7b8e2f

Browse files
Merge pull request #1576 from rabbitmq/rabbitmq-dotnet-client-980
Truncate long client provided names
2 parents 2a48e6c + 728de89 commit d7b8e2f

File tree

5 files changed

+68
-11
lines changed

5 files changed

+68
-11
lines changed

projects/RabbitMQ.Client/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,8 +952,8 @@ virtual RabbitMQ.Client.TcpClientAdapter.ReceiveTimeout.set -> void
952952
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, System.TimeSpan timeout) -> System.Threading.Tasks.Task
953953
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText) -> System.Threading.Tasks.Task
954954
~static RabbitMQ.Client.IConnectionExtensions.AbortAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.TimeSpan timeout) -> System.Threading.Tasks.Task
955-
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection) -> System.Threading.Tasks.Task
955+
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
956956
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, System.TimeSpan timeout) -> System.Threading.Tasks.Task
957-
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText) -> System.Threading.Tasks.Task
957+
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task
958958
~static RabbitMQ.Client.IConnectionExtensions.CloseAsync(this RabbitMQ.Client.IConnection connection, ushort reasonCode, string reasonText, System.TimeSpan timeout) -> System.Threading.Tasks.Task
959959
~virtual RabbitMQ.Client.DefaultBasicConsumer.HandleBasicDeliverAsync(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, RabbitMQ.Client.ReadOnlyBasicProperties properties, System.ReadOnlyMemory<byte> body) -> System.Threading.Tasks.Task

projects/RabbitMQ.Client/client/api/ConnectionFactory.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ public sealed class ConnectionFactory : ConnectionFactoryBase, IConnectionFactor
197197

198198
// just here to hold the value that was set through the setter
199199
private Uri _uri;
200+
private string _clientProvidedName;
200201

201202
/// <summary>
202203
/// Amount of time protocol handshake operations are allowed to take before
@@ -367,7 +368,14 @@ public Uri Uri
367368
/// <summary>
368369
/// Default client provided name to be used for connections.
369370
/// </summary>
370-
public string ClientProvidedName { get; set; }
371+
public string ClientProvidedName
372+
{
373+
get => _clientProvidedName;
374+
set
375+
{
376+
_clientProvidedName = EnsureClientProvidedNameLength(value);
377+
}
378+
}
371379

372380
/// <summary>
373381
/// Given a list of mechanism names supported by the server, select a preferred mechanism,
@@ -593,7 +601,7 @@ private ConnectionConfig CreateConfig(string clientProvidedName)
593601
CredentialsRefresher,
594602
AuthMechanisms,
595603
ClientProperties,
596-
clientProvidedName,
604+
EnsureClientProvidedNameLength(clientProvidedName),
597605
RequestedChannelMax,
598606
RequestedFrameMax,
599607
MaxInboundMessageBodySize,
@@ -712,5 +720,17 @@ private List<AmqpTcpEndpoint> LocalEndpoints()
712720
{
713721
return new List<AmqpTcpEndpoint> { Endpoint };
714722
}
723+
724+
private static string EnsureClientProvidedNameLength(string clientProvidedName)
725+
{
726+
if (clientProvidedName.Length > InternalConstants.DefaultRabbitMqMaxClientProvideNameLength)
727+
{
728+
return clientProvidedName.Substring(0, InternalConstants.DefaultRabbitMqMaxClientProvideNameLength);
729+
}
730+
else
731+
{
732+
return clientProvidedName;
733+
}
734+
}
715735
}
716736
}

projects/RabbitMQ.Client/client/api/IConnectionExtensions.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ public static class IConnectionExtensions
1818
/// (or closing), then this method will do nothing.
1919
/// It can also throw <see cref="IOException"/> when socket was closed unexpectedly.
2020
/// </remarks>
21-
public static Task CloseAsync(this IConnection connection)
21+
public static Task CloseAsync(this IConnection connection, CancellationToken cancellationToken = default)
2222
{
2323
return connection.CloseAsync(Constants.ReplySuccess, "Goodbye", InternalConstants.DefaultConnectionCloseTimeout, false,
24-
CancellationToken.None);
24+
cancellationToken);
2525
}
2626

2727
/// <summary>
2828
/// Asynchronously close this connection and all its channels.
2929
/// </summary>
3030
/// <remarks>
31-
/// The method behaves in the same way as <see cref="CloseAsync(IConnection)"/>, with the only
31+
/// The method behaves in the same way as <see cref="CloseAsync(IConnection, CancellationToken)"/>, with the only
3232
/// difference that the connection is closed with the given connection close code and message.
3333
/// <para>
3434
/// The close code (See under "Reply Codes" in the AMQP specification).
@@ -37,10 +37,11 @@ public static Task CloseAsync(this IConnection connection)
3737
/// A message indicating the reason for closing the connection.
3838
/// </para>
3939
/// </remarks>
40-
public static Task CloseAsync(this IConnection connection, ushort reasonCode, string reasonText)
40+
public static Task CloseAsync(this IConnection connection, ushort reasonCode, string reasonText,
41+
CancellationToken cancellationToken = default)
4142
{
4243
return connection.CloseAsync(reasonCode, reasonText, InternalConstants.DefaultConnectionCloseTimeout, false,
43-
CancellationToken.None);
44+
cancellationToken);
4445
}
4546

4647
/// <summary>
@@ -92,7 +93,7 @@ public static Task CloseAsync(this IConnection connection, ushort reasonCode, st
9293
/// </summary>
9394
/// <remarks>
9495
/// Note that all active channels and sessions will be closed if this method is called.
95-
/// In comparison to normal <see cref="CloseAsync(IConnection)"/> method, <see cref="AbortAsync(IConnection)"/> will not throw
96+
/// In comparison to normal <see cref="CloseAsync(IConnection, CancellationToken)"/> method, <see cref="AbortAsync(IConnection)"/> will not throw
9697
/// <see cref="IOException"/> during closing connection.
9798
///This method waits infinitely for the in-progress close operation to complete.
9899
/// </remarks>

projects/RabbitMQ.Client/client/api/InternalConstants.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,12 @@ internal static class InternalConstants
4444
/// configures the largest message size which should be lower than this maximum of 128MiB.
4545
/// </summary>
4646
internal const uint DefaultRabbitMqMaxInboundMessageBodySize = 1_048_576 * 128;
47+
48+
/// <summary>
49+
/// Largest client provide name, in characters, allowed in RabbitMQ.
50+
/// This is not configurable, but was discovered while working on this issue:
51+
/// https://github.com/rabbitmq/rabbitmq-dotnet-client/issues/980
52+
/// </summary>
53+
internal const int DefaultRabbitMqMaxClientProvideNameLength = 3652;
4754
}
4855
}

projects/Test/Integration/TestConnectionFactory.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,36 @@ public async Task TestCreateConnectionAsync_UsesValidEndpointWhenMultipleSupplie
436436
var ep = new AmqpTcpEndpoint("localhost");
437437
using (IConnection conn = await cf.CreateConnectionAsync(new List<AmqpTcpEndpoint> { invalidEp, ep }, cts.Token))
438438
{
439-
await conn.CloseAsync();
439+
await conn.CloseAsync(cts.Token);
440+
}
441+
}
442+
}
443+
444+
[Theory]
445+
[InlineData(3650)]
446+
[InlineData(3651)]
447+
[InlineData(3652)]
448+
[InlineData(3653)]
449+
[InlineData(3654)]
450+
public async Task TestCreateConnectionAsync_TruncatesWhenClientNameIsLong_GH980(ushort count)
451+
{
452+
string cpn = GetUniqueString(count);
453+
using (var cts = new CancellationTokenSource(WaitSpan))
454+
{
455+
ConnectionFactory cf0 = new ConnectionFactory { ClientProvidedName = cpn };
456+
using (IConnection conn = await cf0.CreateConnectionAsync(cts.Token))
457+
{
458+
await conn.CloseAsync(cts.Token);
459+
Assert.True(cf0.ClientProvidedName.Length <= InternalConstants.DefaultRabbitMqMaxClientProvideNameLength);
460+
Assert.Contains(cf0.ClientProvidedName, cpn);
461+
}
462+
463+
ConnectionFactory cf1 = new ConnectionFactory();
464+
using (IConnection conn = await cf1.CreateConnectionAsync(cpn, cts.Token))
465+
{
466+
await conn.CloseAsync(cts.Token);
467+
Assert.True(conn.ClientProvidedName.Length <= InternalConstants.DefaultRabbitMqMaxClientProvideNameLength);
468+
Assert.Contains(conn.ClientProvidedName, cpn);
440469
}
441470
}
442471
}

0 commit comments

Comments
 (0)