Not logged in. · Lost password · Register
Forum: agsXMPP SDK Support RSS
Avatar
Goofster #1
Member since Feb 2006 · 3 posts
Group memberships: Members
Show profile · Link to this post
Subject: Resolving SRV records with correct prorities and randomization between weights
As promised, here is the resolvsrv function I created myself to
not only use priorities when resolving srv records but to also
do correct randomization between the weights of the records.

When all the weights are the same it just picks at random, but
when the weights differ I do a calculation so that if server A has
weight 3 and server B has weight 5, 3 out of 8 times server A will be
used and 5 out of 8 times server B will be used (aproximately)

                /// <summary>
        /// Resolves a connectserver based on the SRV records of the specified domain
        /// </summary>
        /// <param name="server"></param>
        /// <returns></returns>
        private string ResolveSrv(string server)
        {   
            SRVRecord srv1 = null;           

            try
            {
                bool serverfound = false;

                // get the machine's default DNS servers
                string[] dnsServers = IPConfigurationInformation.DnsServers;                               

                for(int dnscount = 0; dnscount < dnsServers.Length && !serverfound; dnscount++)
                {

                    // Take the 1st DNS Server for our query
                    IPAddress dnsServer = IPAddress.Parse(dnsServers[dnscount]);               

                    // Information
                    string SRV_RECORD_PREFIX = "_xmpp-client._tcp.";
                    string queryDomain = SRV_RECORD_PREFIX + server;               

                    SRVRecord[] records = Resolver.SRVLookup(queryDomain, dnsServer);

                    int weightcount =  0 ; // total weight of the highservs
                    ArrayList highservs = new ArrayList();                   


                    // check we have a response
                    if (records != null && records.Length > 0)
                    {
                        // This loop gets the highest priority records
                        foreach(SRVRecord srv in records)
                        {   
                            if(srv1 == null)
                            {
                                srv1 = srv;
                                highservs.Add(srv1);
                                weightcount = srv1.Weight;
                            }
                            else
                            {
                                if(srv.Priority > srv1.Priority)
                                {
                                    highservs.Clear();
                                    srv1 = srv;
                                    highservs.Add(srv1);
                                    weightcount = srv1.Weight;
                                }
                                else if(srv.Priority == srv1.Priority)
                                {
                                    highservs.Add(srv);
                                    weightcount += srv.Weight;
                                }
                            }
                        }
                    }
                               
                    if(highservs.Count > 1)
                    {   
                        // First we check if all records have the same weight
                        SRVRecord last = null;
                        bool sameweights = true;
                        foreach(SRVRecord s in highservs)
                        {                       
                            if(last != null && s.Weight != last.Weight)
                                sameweights = false;

                            last = s;
                        }
                       
                        if(sameweights)
                        {    // All servers have the same weight, just random between the number of servers
                            Random rand = new Random();
                            int rnum = rand.Next(highservs.Count);                       
                            srv1 = (SRVRecord)highservs[rnum];
                        }
                        else
                        {   
                            /*    Weights differ, use super-cool algorithm:
                             *    if server A has
                             *    weight 3 and server B has weight 5, 3 out of 8 times server A will be
                             *    used and 5 out of 8 times server B will be used (aproximately)
                             */
                            Random rand = new Random();
                            int rnum = rand.Next(1, weightcount);                           

                            int i = 0;
                            foreach(SRVRecord s in highservs)
                            {
                                if(rnum > i && rnum <= (i + s.Weight))
                                    srv1 = s;
                                else
                                    i += s.Weight;
                            }
                        }
                    }
                    if(srv1 != null)
                        serverfound = true;

                } // end of dns server loop
            }
            catch (Exception ex)
            { 
                Debug.Instance.INFO(this, "EXCEPTION "+ex.Message+" "+ex.StackTrace);
            }

            if(srv1 != null)
                return srv1.Target;
            else
                return null;
        }
Avatar
Alex #2
Member since Feb 2003 · 4245 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Helo Goofster,

sorry for the delay, i just got back to the srv stuff. Your function looks of, but i think there is an error.
You look for the servers with the highest priority which is wrong. You have to start with the servers which have the lowest priority.
see also: http://en.wikipedia.org/wiki/SRV_record

Alex
Alexander Gnauck
AG-Software
Avatar
Alex #3
Member since Feb 2003 · 4245 posts · Location: Germany
Group memberships: Administrators, Members
Show profile · Link to this post
Hello,

we did lot's of work on this topic in the last days and optimized the SRV Record handling and usage. The code is commited to SVN.

  • it's choosing the correct record now by evaluating priority and weight
  • if tries to connect to the next record now if the previous failed.

Alex
Alexander Gnauck
AG-Software
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Forum: agsXMPP SDK Support RSS