Skip to content

Commit f9d1fc4

Browse files
committed
CSHARP-1730: Add ClientDocumentHelper and enforce max sizes on ApplicationName and ClientDocument.
1 parent bfc6c47 commit f9d1fc4

File tree

20 files changed

+530
-208
lines changed

20 files changed

+530
-208
lines changed

src/MongoDB.Driver.Core.Dotnet/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
},
66
"buildOptions": {
77
"compile": {
8-
"include": [ "../MongoDB.Driver.Core/**/*.cs", "../MongoDB.Shared/Hasher.cs" ]
8+
"include": [ "../MongoDB.Driver.Core/**/*.cs", "../MongoDB.Shared/ApplicationNameHelper.cs", "../MongoDB.Shared/Hasher.cs" ]
99
},
1010
"warningsAsErrors": true,
1111
"outputName" : "MongoDB.Driver.Core",

src/MongoDB.Driver.Core/Core/Configuration/ConnectionSettings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.Linq;
1919
using MongoDB.Driver.Core.Authentication;
2020
using MongoDB.Driver.Core.Misc;
21+
using MongoDB.Shared;
2122

2223
namespace MongoDB.Driver.Core.Configuration
2324
{
@@ -54,7 +55,7 @@ public ConnectionSettings(
5455
_authenticators = Ensure.IsNotNull(authenticators.WithDefault(__noAuthenticators), "authenticators").ToList();
5556
_maxIdleTime = Ensure.IsGreaterThanZero(maxIdleTime.WithDefault(TimeSpan.FromMinutes(10)), "maxIdleTime");
5657
_maxLifeTime = Ensure.IsGreaterThanZero(maxLifeTime.WithDefault(TimeSpan.FromMinutes(30)), "maxLifeTime");
57-
_applicationName = applicationName.WithDefault(null);
58+
_applicationName = ApplicationNameHelper.EnsureApplicationNameIsValid(applicationName.WithDefault(null), nameof(applicationName));
5859
}
5960

6061
// properties

src/MongoDB.Driver.Core/Core/Configuration/ConnectionString.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using MongoDB.Driver.Core.Clusters;
2626
using MongoDB.Driver.Core.Misc;
2727
using MongoDB.Driver.Core.Operations;
28+
using MongoDB.Shared;
2829

2930
namespace MongoDB.Driver.Core.Configuration
3031
{
@@ -492,7 +493,14 @@ private void ParseOption(string name, string value)
492493
switch (name.ToLower())
493494
{
494495
case "appname":
495-
_applicationName = value;
496+
try
497+
{
498+
_applicationName = ApplicationNameHelper.EnsureApplicationNameIsValid(value, nameof(value));
499+
}
500+
catch (Exception ex)
501+
{
502+
throw new MongoConfigurationException(ex.Message, ex);
503+
}
496504
break;
497505
case "authmechanism":
498506
_authMechanism = value;
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/* Copyright 2016 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Reflection;
18+
using System.Runtime.InteropServices;
19+
using System.Text.RegularExpressions;
20+
using MongoDB.Bson;
21+
22+
namespace MongoDB.Driver.Core.Connections
23+
{
24+
internal class ClientDocumentHelper
25+
{
26+
#region static
27+
// private static fields
28+
private static readonly Lazy<BsonDocument> __driverDocument = new Lazy<BsonDocument>(CreateDriverDocument);
29+
private static readonly Lazy<BsonDocument> __osDocument = new Lazy<BsonDocument>(CreateOSDocument);
30+
private static readonly Lazy<string> __platformString = new Lazy<string>(GetPlatformString);
31+
32+
// private static methods
33+
internal static BsonDocument CreateClientDocument(string applicationName)
34+
{
35+
return CreateClientDocument(applicationName, __driverDocument.Value, __osDocument.Value, __platformString.Value);
36+
}
37+
38+
internal static BsonDocument CreateClientDocument(string applicationName, BsonDocument driverDocument, BsonDocument osDocument, string platformString)
39+
{
40+
var clientDocument = new BsonDocument
41+
{
42+
{ "application", () => new BsonDocument("name", applicationName), applicationName != null },
43+
{ "driver", driverDocument },
44+
{ "os", osDocument.Clone() }, // clone because we might be removing optional fields from this particular clientDocument
45+
{ "platform", platformString }
46+
};
47+
48+
return RemoveOptionalFieldsUntilDocumentIsLessThan512Bytes(clientDocument);
49+
}
50+
51+
internal static BsonDocument CreateDriverDocument()
52+
{
53+
var assembly = typeof(ConnectionInitializer).GetTypeInfo().Assembly;
54+
var fileVersionAttribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
55+
var driverVersion = fileVersionAttribute.Version;
56+
57+
return CreateDriverDocument(driverVersion);
58+
}
59+
60+
internal static BsonDocument CreateDriverDocument(string driverVersion)
61+
{
62+
return new BsonDocument
63+
{
64+
{ "name", "mongo-csharp-driver" },
65+
{ "version", driverVersion }
66+
};
67+
}
68+
69+
internal static BsonDocument CreateOSDocument()
70+
{
71+
string osType;
72+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
73+
{
74+
osType = "Windows";
75+
}
76+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
77+
{
78+
osType = "Linux";
79+
}
80+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
81+
{
82+
osType = "macOS";
83+
}
84+
else
85+
{
86+
osType = "unknown";
87+
}
88+
89+
var osName = RuntimeInformation.OSDescription.Trim();
90+
91+
string architecture;
92+
switch (RuntimeInformation.ProcessArchitecture)
93+
{
94+
case Architecture.Arm: architecture = "arm"; break;
95+
case Architecture.Arm64: architecture = "arm64"; break;
96+
case Architecture.X64: architecture = "x86_64"; break;
97+
case Architecture.X86: architecture = "x86_32"; break;
98+
default: architecture = null; break;
99+
}
100+
101+
string osVersion;
102+
var match = Regex.Match(osName, @" (?<version>\d+\.\d[^ ]*)");
103+
if (match.Success)
104+
{
105+
osVersion = match.Groups["version"].Value;
106+
}
107+
else
108+
{
109+
osVersion = null;
110+
}
111+
112+
return CreateOSDocument(osType, osName, architecture, osVersion);
113+
}
114+
115+
internal static BsonDocument CreateOSDocument(string osType, string osName, string architecture, string osVersion)
116+
{
117+
return new BsonDocument
118+
{
119+
{ "type", osType },
120+
{ "name", osName },
121+
{ "architecture", architecture, architecture != null },
122+
{ "version", osVersion, osVersion != null }
123+
};
124+
}
125+
126+
internal static string GetPlatformString()
127+
{
128+
return RuntimeInformation.FrameworkDescription;
129+
}
130+
131+
internal static BsonDocument RemoveOneOptionalField(BsonDocument clientDocument)
132+
{
133+
if (clientDocument.Contains("application"))
134+
{
135+
clientDocument.Remove("application");
136+
return clientDocument;
137+
}
138+
139+
var os = clientDocument["os"].AsBsonDocument;
140+
if (os.Contains("version"))
141+
{
142+
os.Remove("version");
143+
return clientDocument;
144+
}
145+
if (os.Contains("architecture"))
146+
{
147+
os.Remove("architecture");
148+
return clientDocument;
149+
}
150+
if (os.Contains("name"))
151+
{
152+
os.Remove("name");
153+
return clientDocument;
154+
}
155+
156+
if (clientDocument.Contains("platform"))
157+
{
158+
clientDocument.Remove("platform");
159+
return clientDocument;
160+
}
161+
162+
// no optional fields left to remove
163+
return null;
164+
}
165+
166+
internal static BsonDocument RemoveOptionalFieldsUntilDocumentIsLessThan512Bytes(BsonDocument clientDocument)
167+
{
168+
while (clientDocument != null && clientDocument.ToBson().Length > 512)
169+
{
170+
clientDocument = RemoveOneOptionalField(clientDocument);
171+
}
172+
173+
return clientDocument;
174+
}
175+
#endregion
176+
177+
}
178+
}

src/MongoDB.Driver.Core/Core/Connections/ConnectionInitializer.cs

Lines changed: 2 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@
1313
* limitations under the License.
1414
*/
1515

16-
using System;
17-
using System.Reflection;
18-
using System.Runtime.InteropServices;
19-
using System.Text.RegularExpressions;
2016
using System.Threading;
2117
using System.Threading.Tasks;
2218
using MongoDB.Bson;
@@ -32,99 +28,11 @@ namespace MongoDB.Driver.Core.Connections
3228
/// </summary>
3329
internal class ConnectionInitializer : IConnectionInitializer
3430
{
35-
#region static
36-
// private static fields
37-
private static readonly Lazy<BsonDocument> __driverDocument = new Lazy<BsonDocument>(CreateDriverDocument);
38-
private static readonly Lazy<BsonDocument> __osDocument = new Lazy<BsonDocument>(CreateOSDocument);
39-
private static readonly Lazy<string> __platformString = new Lazy<string>(GetPlatformString);
40-
41-
// private static methods
42-
internal static BsonDocument CreateDriverDocument()
43-
{
44-
var assembly = typeof(ConnectionInitializer).GetTypeInfo().Assembly;
45-
var fileVersionAttribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
46-
var driverVersion = fileVersionAttribute.Version;
47-
48-
return CreateDriverDocument(driverVersion);
49-
}
50-
51-
internal static BsonDocument CreateDriverDocument(string driverVersion)
52-
{
53-
return new BsonDocument
54-
{
55-
{ "name", "dotnet" },
56-
{ "version", driverVersion }
57-
};
58-
}
59-
60-
internal static BsonDocument CreateOSDocument()
61-
{
62-
string osType;
63-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
64-
{
65-
osType = "Windows";
66-
}
67-
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
68-
{
69-
osType = "Linux";
70-
}
71-
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
72-
{
73-
osType = "macOS";
74-
}
75-
else
76-
{
77-
osType = "unknown";
78-
}
79-
80-
var osName = RuntimeInformation.OSDescription.Trim();
81-
82-
string architecture;
83-
switch (RuntimeInformation.ProcessArchitecture)
84-
{
85-
case Architecture.Arm: architecture = "arm"; break;
86-
case Architecture.Arm64: architecture = "arm64"; break;
87-
case Architecture.X64: architecture = "x86_64"; break;
88-
case Architecture.X86: architecture = "x86_32"; break;
89-
default: architecture = null; break;
90-
}
91-
92-
string osVersion;
93-
var match = Regex.Match(osName, @" (?<version>\d+\.\d[^ ]*)");
94-
if (match.Success)
95-
{
96-
osVersion = match.Groups["version"].Value;
97-
}
98-
else
99-
{
100-
osVersion = null;
101-
}
102-
103-
return CreateOSDocument(osType, osName, architecture, osVersion);
104-
}
105-
106-
internal static BsonDocument CreateOSDocument(string osType, string osName, string architecture, string osVersion)
107-
{
108-
return new BsonDocument
109-
{
110-
{ "type", osType },
111-
{ "name", osName },
112-
{ "architecture", architecture, architecture != null },
113-
{ "version", osVersion, osVersion != null }
114-
};
115-
}
116-
117-
internal static string GetPlatformString()
118-
{
119-
return RuntimeInformation.FrameworkDescription;
120-
}
121-
#endregion
122-
12331
private readonly BsonDocument _clientDocument;
12432

12533
public ConnectionInitializer(string applicationName)
12634
{
127-
_clientDocument = CreateClientDocument(applicationName);
35+
_clientDocument = ClientDocumentHelper.CreateClientDocument(applicationName);
12836
}
12937

13038
public ConnectionDescription InitializeConnection(IConnection connection, CancellationToken cancellationToken)
@@ -198,22 +106,6 @@ private CommandWireProtocol<BsonDocument> CreateBuildInfoProtocol()
198106
return buildInfoProtocol;
199107
}
200108

201-
internal BsonDocument CreateClientDocument(string applicationName)
202-
{
203-
return CreateClientDocument(applicationName, __driverDocument.Value, __osDocument.Value, __platformString.Value);
204-
}
205-
206-
internal BsonDocument CreateClientDocument(string applicationName, BsonDocument driverDocument, BsonDocument osDocument, string platformString)
207-
{
208-
return new BsonDocument
209-
{
210-
{ "application", () => new BsonDocument("name", applicationName), applicationName != null },
211-
{ "driver", driverDocument },
212-
{ "os", osDocument },
213-
{ "platform", platformString }
214-
};
215-
}
216-
217109
private CommandWireProtocol<BsonDocument> CreateGetLastErrorProtocol()
218110
{
219111
var getLastErrorCommand = new BsonDocument("getLastError", 1);
@@ -236,7 +128,7 @@ internal BsonDocument CreateIsMasterCommand(BsonDocument clientDocument)
236128
return new BsonDocument
237129
{
238130
{ "isMaster", 1 },
239-
{ "client", clientDocument }
131+
{ "client", clientDocument, clientDocument != null }
240132
};
241133
}
242134

src/MongoDB.Driver.Core/MongoDB.Driver.Core.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
</Reference>
4343
</ItemGroup>
4444
<ItemGroup>
45+
<Compile Include="..\MongoDB.Shared\ApplicationNameHelper.cs">
46+
<Link>Core\Configuration\ApplicationNameHelper.cs</Link>
47+
</Compile>
4548
<Compile Include="..\MongoDB.Shared\GlobalAssemblyInfo.cs">
4649
<Link>Properties\GlobalAssemblyInfo.cs</Link>
4750
</Compile>
@@ -73,6 +76,7 @@
7376
<Compile Include="Core\Bindings\ChannelReadBinding.cs" />
7477
<Compile Include="Core\Bindings\ChannelReadWriteBinding.cs" />
7578
<Compile Include="Core\Bindings\ChannelSourceReadWriteBinding.cs" />
79+
<Compile Include="Core\Connections\ClientDocumentHelper.cs" />
7680
<Compile Include="Core\Misc\CachedEnumerable.cs" />
7781
<Compile Include="Core\Misc\CollationFeature.cs" />
7882
<Compile Include="Core\Misc\DefaultRandomStringGenerator.cs" />

src/MongoDB.Driver.Dotnet/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"buildOptions": {
88
"compile": {
9-
"include": [ "../MongoDB.Driver/**/*.cs", "../MongoDB.Shared/Hasher.cs" ]
9+
"include": [ "../MongoDB.Driver/**/*.cs", "../MongoDB.Shared/ApplicationNameHelper.cs", "../MongoDB.Shared/Hasher.cs" ]
1010
},
1111
"warningsAsErrors": true,
1212
"outputName" : "MongoDB.Driver",

0 commit comments

Comments
 (0)