2121using System . Text . RegularExpressions ;
2222using System . Threading ;
2323using System . Threading . Tasks ;
24- using DnsClient ;
2524using MongoDB . Bson ;
2625using MongoDB . Bson . IO ;
2726using MongoDB . Driver . Core . Clusters ;
@@ -62,6 +61,7 @@ public sealed class ConnectionString
6261 private readonly NameValueCollection _unknownOptions ;
6362 private readonly Dictionary < string , string > _authMechanismProperties ;
6463 private readonly CompressorsOptions _compressorsOptions ;
64+ private readonly IDnsResolver _dnsResolver ;
6565
6666 // these are all readonly, but since they are not assigned
6767 // from the ctor, they cannot be marked as such.
@@ -110,14 +110,19 @@ public sealed class ConnectionString
110110 /// Initializes a new instance of the <see cref="ConnectionString" /> class.
111111 /// </summary>
112112 /// <param name="connectionString">The connection string.</param>
113- public ConnectionString ( string connectionString )
113+ public ConnectionString ( string connectionString ) : this ( connectionString , DnsClientWrapper . Instance )
114+ {
115+ }
116+
117+ internal ConnectionString ( string connectionString , IDnsResolver dnsResolver )
114118 {
115119 _originalConnectionString = Ensure . IsNotNull ( connectionString , nameof ( connectionString ) ) ;
116120
117121 _allOptions = new NameValueCollection ( StringComparer . OrdinalIgnoreCase ) ;
118122 _unknownOptions = new NameValueCollection ( StringComparer . OrdinalIgnoreCase ) ;
119123 _authMechanismProperties = new Dictionary < string , string > ( StringComparer . OrdinalIgnoreCase ) ;
120124 _compressorsOptions = new CompressorsOptions ( ) ;
125+ _dnsResolver = Ensure . IsNotNull ( dnsResolver , nameof ( dnsResolver ) ) ;
121126 Parse ( ) ;
122127
123128 _isResolved = _scheme != ConnectionStringScheme . MongoDBPlusSrv ;
@@ -511,19 +516,21 @@ public string GetOption(string name)
511516 /// Resolves a connection string. If the connection string indicates more information is available
512517 /// in the DNS system, it will acquire that information as well.
513518 /// </summary>
519+ /// <param name="cancellationToken">The cancellation token.</param>
514520 /// <returns>A resolved ConnectionString.</returns>
515- public ConnectionString Resolve ( )
521+ public ConnectionString Resolve ( CancellationToken cancellationToken = default ( CancellationToken ) )
516522 {
517- return Resolve ( resolveHosts : true ) ;
523+ return Resolve ( resolveHosts : true , cancellationToken ) ;
518524 }
519525
520526 /// <summary>
521527 /// Resolves a connection string. If the connection string indicates more information is available
522528 /// in the DNS system, it will acquire that information as well.
523529 /// </summary>
524530 /// <param name="resolveHosts">Whether to resolve hosts.</param>
531+ /// <param name="cancellationToken">The cancellation token.</param>
525532 /// <returns>A resolved ConnectionString.</returns>
526- public ConnectionString Resolve ( bool resolveHosts )
533+ public ConnectionString Resolve ( bool resolveHosts , CancellationToken cancellationToken = default ( CancellationToken ) )
527534 {
528535 if ( _isResolved )
529536 {
@@ -532,15 +539,13 @@ public ConnectionString Resolve(bool resolveHosts)
532539
533540 var host = GetHostNameForDns ( ) ;
534541
535- var client = new LookupClient ( ) ;
536-
537542 ConnectionStringScheme resolvedScheme ;
538543 List < string > hosts ;
539544 if ( resolveHosts )
540545 {
541546 resolvedScheme = ConnectionStringScheme . MongoDB ;
542- var srvResponse = client . Query ( srvPrefix + host , QueryType . SRV , QueryClass . IN ) ;
543- hosts = GetHostsFromResponse ( srvResponse ) ;
547+ var srvRecords = _dnsResolver . ResolveSrvRecords ( srvPrefix + host , cancellationToken ) ;
548+ hosts = GetHostsFromSrvRecords ( srvRecords ) ;
544549 ValidateResolvedHosts ( host , hosts ) ;
545550 }
546551 else
@@ -549,8 +554,8 @@ public ConnectionString Resolve(bool resolveHosts)
549554 hosts = new List < string > { host } ;
550555 }
551556
552- var txtResponse = client . Query ( host , QueryType . TXT , QueryClass . IN ) ;
553- var options = GetOptionsFromResponse ( txtResponse ) ;
557+ var txtRecords = _dnsResolver . ResolveTxtRecords ( host , cancellationToken ) ;
558+ var options = GetOptionsFromTxtRecords ( txtRecords ) ;
554559
555560 var resolvedOptions = GetResolvedOptions ( options ) ;
556561
@@ -584,15 +589,13 @@ public ConnectionString Resolve(bool resolveHosts)
584589
585590 var host = GetHostNameForDns ( ) ;
586591
587- var client = new LookupClient ( ) ;
588-
589592 ConnectionStringScheme resolvedScheme ;
590593 List < string > hosts ;
591594 if ( resolveHosts )
592595 {
593596 resolvedScheme = ConnectionStringScheme . MongoDB ;
594- var srvResponse = await client . QueryAsync ( srvPrefix + host , QueryType . SRV , QueryClass . IN ) . ConfigureAwait ( false ) ;
595- hosts = GetHostsFromResponse ( srvResponse ) ;
597+ var srvRecords = await _dnsResolver . ResolveSrvRecordsAsync ( srvPrefix + host , cancellationToken ) . ConfigureAwait ( false ) ;
598+ hosts = GetHostsFromSrvRecords ( srvRecords ) ;
596599 ValidateResolvedHosts ( host , hosts ) ;
597600 }
598601 else
@@ -601,8 +604,8 @@ public ConnectionString Resolve(bool resolveHosts)
601604 hosts = new List < string > { host } ;
602605 }
603606
604- var txtResponse = await client . QueryAsync ( host , QueryType . TXT , QueryClass . IN ) . ConfigureAwait ( false ) ;
605- var options = GetOptionsFromResponse ( txtResponse ) ;
607+ var txtRecords = await _dnsResolver . ResolveTxtRecordsAsync ( host , cancellationToken ) . ConfigureAwait ( false ) ;
608+ var options = GetOptionsFromTxtRecords ( txtRecords ) ;
606609
607610 var resolvedOptions = GetResolvedOptions ( options ) ;
608611
@@ -1196,33 +1199,30 @@ private bool EnsureTlsInsecureIsValid(bool value)
11961199 return value ;
11971200 }
11981201
1199- private List < string > GetHostsFromResponse ( IDnsQueryResponse response )
1202+ private List < string > GetHostsFromSrvRecords ( IEnumerable < SrvRecord > srvRecords )
12001203 {
12011204 var hosts = new List < string > ( ) ;
1202- foreach ( var srvRecord in response . Answers . SrvRecords ( ) )
1205+ foreach ( var srvRecord in srvRecords )
12031206 {
1204- var h = srvRecord . Target . ToString ( ) ;
1207+ var h = srvRecord . EndPoint . Host ;
12051208 if ( h . EndsWith ( "." , StringComparison . Ordinal ) )
12061209 {
12071210 h = h . Substring ( 0 , h . Length - 1 ) ;
12081211 }
1209- hosts . Add ( h + ":" + srvRecord . Port ) ;
1212+ hosts . Add ( h + ":" + srvRecord . EndPoint . Port ) ;
12101213 }
12111214
12121215 return hosts ;
12131216 }
12141217
1215- private List < string > GetOptionsFromResponse ( IDnsQueryResponse response )
1218+ private List < string > GetOptionsFromTxtRecords ( List < TxtRecord > txtRecords )
12161219 {
1217- var txtRecords = response . Answers
1218- . TxtRecords ( ) . ToList ( ) ;
1219-
12201220 if ( txtRecords . Count > 1 )
12211221 {
12221222 throw new MongoConfigurationException ( "Only 1 TXT record is allowed when using the SRV protocol." ) ;
12231223 }
12241224
1225- return txtRecords . Select ( tr => tr . Text . Aggregate ( "" , ( acc , s ) => acc + Uri . UnescapeDataString ( s ) ) ) . ToList ( ) ;
1225+ return txtRecords . Select ( tr => tr . Strings . Aggregate ( "" , ( acc , s ) => acc + Uri . UnescapeDataString ( s ) ) ) . ToList ( ) ;
12261226 }
12271227
12281228 private NameValueCollection GetResolvedOptions ( List < string > options )
0 commit comments