moduleapi: in module:provides(), add the name of the module in item._provided_by
[prosody.git] / util / rfc3484.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2011 Florian Zeitz
3 --
4 -- This project is MIT/X11 licensed. Please see the
5 -- COPYING file in the source package for more information.
6 --
7
8 local commonPrefixLength = require"util.ip".commonPrefixLength
9 local new_ip = require"util.ip".new_ip;
10
11 local function t_sort(t, comp)
12         for i = 1, (#t - 1) do
13                 for j = (i + 1), #t do
14                         local a, b = t[i], t[j];
15                         if not comp(a,b) then
16                                 t[i], t[j] = b, a;
17                         end
18                 end
19         end
20 end
21
22 local function source(dest, candidates)
23         local function comp(ipA, ipB)
24                 -- Rule 1: Prefer same address
25                 if dest == ipA then
26                         return true;
27                 elseif dest == ipB then
28                         return false;
29                 end
30
31                 -- Rule 2: Prefer appropriate scope
32                 if ipA.scope < ipB.scope then
33                         if ipA.scope < dest.scope then
34                                 return false;
35                         else
36                                 return true;
37                         end
38                 elseif ipA.scope > ipB.scope then
39                         if ipB.scope < dest.scope then
40                                 return true;
41                         else
42                                 return false;
43                         end
44                 end
45
46                 -- Rule 3: Avoid deprecated addresses
47                 -- XXX: No way to determine this
48                 -- Rule 4: Prefer home addresses
49                 -- XXX: Mobility Address related, no way to determine this
50                 -- Rule 5: Prefer outgoing interface
51                 -- XXX: Interface to address relation. No way to determine this
52                 -- Rule 6: Prefer matching label
53                 if ipA.label == dest.label and ipB.label ~= dest.label then
54                         return true;
55                 elseif ipB.label == dest.label and ipA.label ~= dest.label then
56                         return false;
57                 end
58
59                 -- Rule 7: Prefer public addresses (over temporary ones)
60                 -- XXX: No way to determine this
61                 -- Rule 8: Use longest matching prefix
62                 if commonPrefixLength(ipA, dest) > commonPrefixLength(ipB, dest) then
63                         return true;
64                 else
65                         return false;
66                 end
67         end
68
69         t_sort(candidates, comp);
70         return candidates[1];
71 end
72
73 local function destination(candidates, sources)
74         local sourceAddrs = {};
75         local function comp(ipA, ipB)
76                 local ipAsource = sourceAddrs[ipA];
77                 local ipBsource = sourceAddrs[ipB];
78                 -- Rule 1: Avoid unusable destinations
79                 -- XXX: No such information
80                 -- Rule 2: Prefer matching scope
81                 if ipA.scope == ipAsource.scope and ipB.scope ~= ipBsource.scope then
82                         return true;
83                 elseif ipA.scope ~= ipAsource.scope and ipB.scope == ipBsource.scope then
84                         return false;
85                 end
86
87                 -- Rule 3: Avoid deprecated addresses
88                 -- XXX: No way to determine this
89                 -- Rule 4: Prefer home addresses
90                 -- XXX: Mobility Address related, no way to determine this
91                 -- Rule 5: Prefer matching label
92                 if ipAsource.label == ipA.label and ipBsource.label ~= ipB.label then
93                         return true;
94                 elseif ipBsource.label == ipB.label and ipAsource.label ~= ipA.label then
95                         return false;
96                 end
97
98                 -- Rule 6: Prefer higher precedence
99                 if ipA.precedence > ipB.precedence then
100                         return true;
101                 elseif ipA.precedence < ipB.precedence then
102                         return false;
103                 end
104
105                 -- Rule 7: Prefer native transport
106                 -- XXX: No way to determine this
107                 -- Rule 8: Prefer smaller scope
108                 if ipA.scope < ipB.scope then
109                         return true;
110                 elseif ipA.scope > ipB.scope then
111                         return false;
112                 end
113
114                 -- Rule 9: Use longest matching prefix
115                 if commonPrefixLength(ipA, ipAsource) > commonPrefixLength(ipB, ipBsource) then
116                         return true;
117                 elseif commonPrefixLength(ipA, ipAsource) < commonPrefixLength(ipB, ipBsource) then
118                         return false;
119                 end
120
121                 -- Rule 10: Otherwise, leave order unchanged
122                 return true;
123         end
124         for _, ip in ipairs(candidates) do
125                 sourceAddrs[ip] = source(ip, sources);
126         end
127
128         t_sort(candidates, comp);
129         return candidates;
130 end
131
132 return {source = source,
133         destination = destination};