Ejemplo n.º 1
0
        /// <summary>
        /// Finds the best matching SRV record.
        /// </summary>
        /// <param name="domain">The domain.</param>
        /// <returns>DnsSrvRecord(will be null if lookup failed).</returns>
        private DnsSrvRecord FindBestMatchingSrvRecord(string domain)
        {
            List <DnsSrvRecord> dnsSrvRecordList;

            try
            {
                // Make DnsQuery call to get collection of SRV records.
                dnsSrvRecordList = DnsClient.DnsQuery <DnsSrvRecord>(domain, this.service.DnsServerAddress);
            }
            catch (DnsException ex)
            {
                string dnsExcMessage = string.Format(
                    "DnsQuery returned error error '{0}' error code 0x{1:X8}.",
                    ex.Message,
                    ex.NativeErrorCode);
                this.service.TraceMessage(TraceFlags.AutodiscoverConfiguration, dnsExcMessage);
                return(null);
            }
            catch (SecurityException ex)
            {
                // In restricted environments, we may not be allowed to call unmanaged code.
                this.service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    string.Format("DnsQuery cannot be called. Security error: {0}.", ex.Message));
                return(null);
            }

            this.service.TraceMessage(
                TraceFlags.AutodiscoverConfiguration,
                string.Format("{0} SRV records were returned.", dnsSrvRecordList.Count));

            // If multiple records were returned, they will be returned sorted by priority
            // (and weight) order. Need to find the index of the first record that supports SSL.
            int  priority    = int.MinValue;
            int  weight      = int.MinValue;
            bool recordFound = false;

            foreach (DnsSrvRecord dnsSrvRecord in dnsSrvRecordList)
            {
                if (dnsSrvRecord.Port == SslPort)
                {
                    priority    = dnsSrvRecord.Priority;
                    weight      = dnsSrvRecord.Weight;
                    recordFound = true;
                    break;
                }
            }

            // Records were returned but nothing matched our criteria.
            if (!recordFound)
            {
                this.service.TraceMessage(
                    TraceFlags.AutodiscoverConfiguration,
                    "No appropriate SRV records were found.");

                return(null);
            }

            // Collect all records with the same (highest) priority.
            // (Aren't lambda expressions cool? ;-)
            List <DnsSrvRecord> bestDnsSrvRecordList = dnsSrvRecordList.FindAll(
                record => (record.Port == SslPort) && (record.Priority == priority) && (record.Weight == weight));

            // The list must contain at least one matching record since we found one earlier.
            EwsUtilities.Assert(
                dnsSrvRecordList.Count > 0,
                "AutodiscoverDnsClient.FindBestMatchingSrvRecord",
                "At least one DNS SRV record must match the criteria.");

            // If we have multiple records with the same priority and weight, randomly pick one.
            int recordIndex = (bestDnsSrvRecordList.Count > 1)
                ? randomTieBreakerSelector.Next(bestDnsSrvRecordList.Count)
                : 0;

            DnsSrvRecord bestDnsSrvRecord = bestDnsSrvRecordList[recordIndex];

            string traceMessage = string.Format(
                "Returning SRV record {0} of {1} records. Target: {2}, Priority: {3}, Weight: {4}",
                recordIndex,
                dnsSrvRecordList.Count,
                bestDnsSrvRecord.NameTarget,
                bestDnsSrvRecord.Priority,
                bestDnsSrvRecord.Weight);

            this.service.TraceMessage(TraceFlags.AutodiscoverConfiguration, traceMessage);

            return(bestDnsSrvRecord);
        }