Ejemplo n.º 1
0
        private static SRVRecord PickSRV(SRVRecord[] srv)
        {
            // TODO: keep track of connection failures, and try the next priority down.

            if ((srv == null) || (srv.Length == 0))
                throw new ArgumentException();
            if (srv.Length == 1)
                return srv[0];

            // randomize order.  One might wish that the OS would have done this for us.
            // cf. Bob Schriter's Grandfather.
            Random rnd = new Random();
            byte[] keys = new byte[srv.Length];
            rnd.NextBytes(keys);
            Array.Sort(keys, srv);  // Permute me, Knuth!  (I wish I had a good anagram for that)

            int minpri = int.MaxValue;
            foreach (SRVRecord rec in srv)
            {
                if (rec.Priority < minpri)
                    minpri = rec.Priority;
            }

            int weight = 0;
            foreach (SRVRecord rec in srv)
            {
                if (rec.Priority == minpri)
                    weight += rec.Weight;
            }

            int pos = rnd.Next(weight);
            weight = 0;

            foreach (SRVRecord rec in srv)
            {
                if (rec.Priority == minpri)
                {
                    weight += rec.Weight;

                    if ((pos < weight) || (weight == 0))
                        return rec;
                }
            }

            throw new DnsException("No matching SRV");
        }
Ejemplo n.º 2
0
        public static SRVRecord[] ResolveSRV(string query)
        {
            byte[] buffer = new byte[1024];
            byte[] name = new byte[256];
            ushort type, dlen, priority, weight, port;
            int size;
            GCHandle handle;
            List<SRVRecord> results = new List<SRVRecord>();

            size = res_query(query, C_IN, T_SRV, buffer, buffer.Length);

            handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

            try
            {
                HEADER header = (HEADER)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(HEADER));

                int qdcount = ntohs(header.qdcount);
                int ancount = ntohs(header.ancount);

                int headerSize = Marshal.SizeOf(header);

                unsafe
                {
                    fixed (byte* pBuffer = buffer)
                    {

                        byte* pos = pBuffer + headerSize;
                        byte* end = pBuffer + size;

                        // We don't care about the question section.
                        while (qdcount-- > 0 && pos < end)
                        {
                            size = dn_expand(pBuffer, end, pos, name, 256);
                            if (size < 0) return null;
                            pos += size + 4;
                        }

                        // The answers, however, we do care about!
                        while (ancount-- > 0 && pos < end)
                        {
                            size = dn_expand(pBuffer, end, pos, name, 256);
                            if (size < 0) return null;

                            pos += size;

                            type = GETSHORT(ref pos);

                            // Skip TTL
                            pos += 6;

                            dlen = GETSHORT(ref pos);

                            if (type == T_SRV)
                            {
                                priority = GETSHORT(ref pos);
                                weight = GETSHORT(ref pos);
                                port = GETSHORT(ref pos);

                                size = dn_expand(pBuffer, end, pos, name, 256);
                                if (size < 0) return null;

                                string nameStr = null;
                                fixed (byte* pName = name)
                                {
                                    nameStr = new String((sbyte*)pName);
                                }

                                var record = new SRVRecord();
                                record.NameNext = nameStr;
                                record.Priority = priority;
                                record.Weight = weight;
                                record.Port = port;
                                results.Add(record);

                                pos += size;
                            }
                            else
                            {
                                pos += dlen;
                            }
                        }
                    }
                }

            }
            finally
            {
                handle.Free();
            }

            return results.ToArray();
        }