import io
import inspect
import itertools
+import random
import dns.wire
import dns.exception
# against *as_value*.
return tuple(as_value(v) for v in value)
+ # Processing order
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ items = list(iterable)
+ random.shuffle(items)
+ return items
+
class GenericRdata(Rdata):
return True
return False
+ def processing_order(self):
+ """Return rdatas in a valid processing order according to the type's
+ specification. For example, MX records are in preference order from
+ lowest to highest preferences, with items of the same perference
+ shuffled.
+
+ For types that do not define a processing order, the rdatas are
+ simply shuffled.
+ """
+ if len(self) == 0:
+ return []
+ else:
+ return self[0]._processing_order(iter(self))
+
@dns.immutable.immutable
class ImmutableRdataset(Rdataset):
if len(target) == 0:
raise dns.exception.FormError('URI target may not be empty')
return cls(rdclass, rdtype, priority, weight, target)
+
+ def _processing_priority(self):
+ return self.priority
+
+ def _processing_weight(self):
+ return self.weight
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.weighted_processing_order(iterable, False)
replacement = parser.get_name(origin)
return cls(rdclass, rdtype, order, preference, strings[0], strings[1],
strings[2], replacement)
+
+ def _processing_priority(self):
+ return (self.order, self.preference)
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.priority_processing_order(iterable)
map822 = parser.get_name(origin)
mapx400 = parser.get_name(origin)
return cls(rdclass, rdtype, preference, map822, mapx400)
+
+ def _processing_priority(self):
+ return self.preference
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.priority_processing_order(iterable)
(priority, weight, port) = parser.get_struct('!HHH')
target = parser.get_name(origin)
return cls(rdclass, rdtype, priority, weight, port, target)
+
+ def _processing_priority(self):
+ return self.priority
+
+ def _processing_weight(self):
+ return self.weight
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.weighted_processing_order(iterable, True)
import dns.immutable
import dns.rdata
import dns.name
+import dns.rdtypes.util
@dns.immutable.immutable
exchange = parser.get_name(origin)
return cls(rdclass, rdtype, preference, exchange)
+ def _processing_priority(self):
+ return self.preference
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.priority_processing_order(iterable)
+
@dns.immutable.immutable
class UncompressedMX(MXBase):
value = pcls.from_wire_parser(parser, origin)
params[key] = value
return cls(rdclass, rdtype, priority, target, params)
+
+ def _processing_priority(self):
+ return self.priority
+
+ @classmethod
+ def _processing_order(cls, iterable):
+ return dns.rdtypes.util.priority_processing_order(iterable)
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+import random
import struct
import dns.exception
bitmap = parser.get_counted_bytes()
windows.append((window, bitmap))
return cls(windows)
+
+
+def _priority_table(items):
+ by_priority = {}
+ for rdata in items:
+ key = rdata._processing_priority()
+ rdatas = by_priority.get(key)
+ if rdatas is None:
+ rdatas = []
+ by_priority[key] = rdatas
+ rdatas.append(rdata)
+ return by_priority
+
+def priority_processing_order(iterable):
+ items = list(iterable)
+ if len(items) == 1:
+ return [items[0]]
+ by_priority = _priority_table(items)
+ ordered = []
+ for k in sorted(by_priority.keys()):
+ rdatas = by_priority[k]
+ random.shuffle(rdatas)
+ ordered.extend(rdatas)
+ return ordered
+
+def _processing_weight(rdata, adjust_zero_weight):
+ weight = rdata._processing_weight()
+ if weight == 0 and adjust_zero_weight:
+ return 0.1
+ else:
+ return weight
+
+def weighted_processing_order(iterable, adjust_zero_weight=False):
+ items = list(iterable)
+ if len(items) == 1:
+ return [items[0]]
+ by_priority = _priority_table(items)
+ ordered = []
+ for k in sorted(by_priority.keys()):
+ weights_vary = False
+ weights = []
+ rdatas = by_priority[k]
+ for rdata in rdatas:
+ weight = _processing_weight(rdata, adjust_zero_weight)
+ if len(weights) > 0 and weight != weights[-1]:
+ weights_vary = True
+ weights.append(weight)
+ if weights_vary:
+ while len(rdatas) > 1:
+ items = random.choices(rdatas, weights)
+ rdata = items[0]
+ ordered.append(rdata)
+ rdatas.remove(rdata)
+ weight = _processing_weight(rdata, adjust_zero_weight)
+ weights.remove(weight)
+ ordered.append(rdatas[0])
+ else:
+ random.shuffle(rdatas)
+ ordered.extend(rdatas)
+ return ordered