Prepare required data folder for integration tests
[prosody.git] / util / rfc6724.lua
blob81f78d55f764bb14c227231fe25f7bae4124108d
1 -- Prosody IM
2 -- Copyright (C) 2011-2013 Florian Zeitz
3 --
4 -- This project is MIT/X11 licensed. Please see the
5 -- COPYING file in the source package for more information.
6 --
8 -- This is used to sort destination addresses by preference
9 -- during S2S connections.
10 -- We can't hand this off to getaddrinfo, since it blocks
12 local ip_commonPrefixLength = require"util.ip".commonPrefixLength
14 local function commonPrefixLength(ipA, ipB)
15 local len = ip_commonPrefixLength(ipA, ipB);
16 return len < 64 and len or 64;
17 end
19 local function t_sort(t, comp)
20 for i = 1, (#t - 1) do
21 for j = (i + 1), #t do
22 local a, b = t[i], t[j];
23 if not comp(a,b) then
24 t[i], t[j] = b, a;
25 end
26 end
27 end
28 end
30 local function source(dest, candidates)
31 local function comp(ipA, ipB)
32 -- Rule 1: Prefer same address
33 if dest == ipA then
34 return true;
35 elseif dest == ipB then
36 return false;
37 end
39 -- Rule 2: Prefer appropriate scope
40 if ipA.scope < ipB.scope then
41 if ipA.scope < dest.scope then
42 return false;
43 else
44 return true;
45 end
46 elseif ipA.scope > ipB.scope then
47 if ipB.scope < dest.scope then
48 return true;
49 else
50 return false;
51 end
52 end
54 -- Rule 3: Avoid deprecated addresses
55 -- XXX: No way to determine this
56 -- Rule 4: Prefer home addresses
57 -- XXX: Mobility Address related, no way to determine this
58 -- Rule 5: Prefer outgoing interface
59 -- XXX: Interface to address relation. No way to determine this
60 -- Rule 6: Prefer matching label
61 if ipA.label == dest.label and ipB.label ~= dest.label then
62 return true;
63 elseif ipB.label == dest.label and ipA.label ~= dest.label then
64 return false;
65 end
67 -- Rule 7: Prefer temporary addresses (over public ones)
68 -- XXX: No way to determine this
69 -- Rule 8: Use longest matching prefix
70 if commonPrefixLength(ipA, dest) > commonPrefixLength(ipB, dest) then
71 return true;
72 else
73 return false;
74 end
75 end
77 t_sort(candidates, comp);
78 return candidates[1];
79 end
81 local function destination(candidates, sources)
82 local sourceAddrs = {};
83 local function comp(ipA, ipB)
84 local ipAsource = sourceAddrs[ipA];
85 local ipBsource = sourceAddrs[ipB];
86 -- Rule 1: Avoid unusable destinations
87 -- XXX: No such information
88 -- Rule 2: Prefer matching scope
89 if ipA.scope == ipAsource.scope and ipB.scope ~= ipBsource.scope then
90 return true;
91 elseif ipA.scope ~= ipAsource.scope and ipB.scope == ipBsource.scope then
92 return false;
93 end
95 -- Rule 3: Avoid deprecated addresses
96 -- XXX: No way to determine this
97 -- Rule 4: Prefer home addresses
98 -- XXX: Mobility Address related, no way to determine this
99 -- Rule 5: Prefer matching label
100 if ipAsource.label == ipA.label and ipBsource.label ~= ipB.label then
101 return true;
102 elseif ipBsource.label == ipB.label and ipAsource.label ~= ipA.label then
103 return false;
106 -- Rule 6: Prefer higher precedence
107 if ipA.precedence > ipB.precedence then
108 return true;
109 elseif ipA.precedence < ipB.precedence then
110 return false;
113 -- Rule 7: Prefer native transport
114 -- XXX: No way to determine this
115 -- Rule 8: Prefer smaller scope
116 if ipA.scope < ipB.scope then
117 return true;
118 elseif ipA.scope > ipB.scope then
119 return false;
122 -- Rule 9: Use longest matching prefix
123 if commonPrefixLength(ipA, ipAsource) > commonPrefixLength(ipB, ipBsource) then
124 return true;
125 elseif commonPrefixLength(ipA, ipAsource) < commonPrefixLength(ipB, ipBsource) then
126 return false;
129 -- Rule 10: Otherwise, leave order unchanged
130 return true;
132 for _, ip in ipairs(candidates) do
133 sourceAddrs[ip] = source(ip, sources);
136 t_sort(candidates, comp);
137 return candidates;
140 return {source = source,
141 destination = destination};