1
2 /* Web Polygraph http://www.web-polygraph.org/
3 * Copyright 2003-2011 The Measurement Factory
4 * Licensed under the Apache License, Version 2.0 */
5
6 #include "base/polygraph.h"
7
8 #include "runtime/AddrMap.h"
9 #include "runtime/HostMap.h"
10
11 HostMap *TheHostMap = 0;
12
13
14 /* HostCfg */
15
HostCfg(const NetAddr & anAddr)16 HostCfg::HostCfg(const NetAddr &anAddr)
17 : theAddr(anAddr), theProtocol(Agent::pUnknown),
18 theContent(0), theServerRep(0), theUniverse(0),
19 theHostsBasedCfg(0), isSslActive(false) {
20 }
21
22
23 /* HostMap */
24
HostMap(int aCapacity)25 HostMap::HostMap(int aCapacity):
26 theStaticIndex((aCapacity + aCapacity/3 + 7) | 1), theCount(0) {
27 HostCfg *const h = 0;
28 while (!theStaticIndex.full())
29 theStaticIndex.push(h);
30 }
31
~HostMap()32 HostMap::~HostMap() {
33 while (theStaticIndex.count())
34 delete theStaticIndex.pop();
35 while (theDynamicIndex.count())
36 delete theDynamicIndex.pop();
37 }
38
at(int idx) const39 HostCfg *HostMap::at(int idx) const {
40 if (0 <= idx && idx < capacity())
41 return theStaticIndex[idx];
42 else
43 if (capacity() <= idx && idx < 2*capacity()) {
44 Assert(theDynamicIndex.capacity() == capacity());
45 return theDynamicIndex[idx - capacity()];
46 }
47 return 0;
48 }
49
at(const NetAddr & addr)50 HostCfg *HostMap::at(const NetAddr &addr) {
51 int idx = -1;
52 Assert(findIdx(addr, idx));
53 return at(idx);
54 }
55
serverRepAt(int idx)56 ServerRep *HostMap::serverRepAt(int idx) {
57 if (HostCfg *cfg = at(idx))
58 return cfg->theServerRep;
59 return 0;
60 }
61
sslActive(const NetAddr & addr)62 bool HostMap::sslActive(const NetAddr &addr) {
63 int idx = -1;
64 if (findIdx(addr, idx))
65 return at(idx)->isSslActive;
66 return false;
67 }
68
findUniverse(const NetAddr & addr)69 ObjUniverse *HostMap::findUniverse(const NetAddr &addr) {
70 int idx = -1;
71 if (findIdx(addr, idx))
72 return at(idx)->theUniverse;
73 return 0;
74 }
75
findUniverseAt(int idx)76 ObjUniverse *HostMap::findUniverseAt(int idx) {
77 if (const HostCfg *const h = at(idx))
78 return h->theUniverse;
79 return 0;
80 }
81
find(const NetAddr & addr)82 HostCfg *HostMap::find(const NetAddr &addr) {
83 int idx = -1;
84 return find(addr, idx);
85 }
86
find(const NetAddr & addr,int & idx)87 HostCfg *HostMap::find(const NetAddr &addr, int &idx) {
88 if (findIdx(addr, idx))
89 return at(idx);
90
91 return 0;
92 }
93
mapAndFind(const NetAddr & addr,int & idx)94 HostCfg *HostMap::mapAndFind(const NetAddr &addr, int &idx) {
95 if (HostCfg * const hcfg = find(addr, idx))
96 return hcfg;
97
98 if (!addr.isDomainName())
99 return 0;
100
101 int ipIdx = -1;
102 if (!TheAddrMap->find(addr, ipIdx))
103 return 0;
104
105 const NetAddr ip(TheAddrMap->selectAddr(ipIdx).addrA(), addr.port());
106 return find(ip, idx);
107 }
108
findIdx(const NetAddr & addr,int & idx)109 bool HostMap::findIdx(const NetAddr &addr, int &idx) {
110 if (addr.isDynamicName() && theDynamicIndex.empty()) {
111 // this is the first dynamic name, create dynamic index
112 theDynamicIndex.stretch(capacity());
113 HostCfg *const h = 0;
114 while (!theDynamicIndex.full())
115 theDynamicIndex.push(h);
116 }
117
118 if (!theDynamicIndex.empty() && addr.isDomainName())
119 // for domain names, check theDynamicIndex first
120 if (const char *dot = addr.addrA().chr('.')) {
121 NetAddr suffixAddr(dot, addr.port());
122 if (findIdxInIndex(theDynamicIndex, suffixAddr, idx)) {
123 idx += capacity();
124 return true;
125 } else
126 if (addr.isDynamicName()) {
127 idx += capacity();
128 return false;
129 }
130 }
131
132 Assert(!addr.isDynamicName());
133
134 return findIdxInIndex(theStaticIndex, addr, idx);
135 }
136
findIdxInIndex(const Array<HostCfg * > & arr,const NetAddr & addr,int & idx) const137 bool HostMap::findIdxInIndex(const Array<HostCfg*> &arr, const NetAddr &addr, int &idx) const {
138 bool res = false;
139
140 idx = hash0(addr);
141 if (endSearch(arr, addr, idx, res))
142 return res;
143
144 // try hash1 followed by linear search
145 idx = hash1(addr);
146 for (int i = arr.capacity(); i; --i) {
147 if (endSearch(arr, addr, idx, res))
148 return res;
149 idx++;
150 idx %= arr.capacity();
151 }
152
153 Assert(false); // no empty slots left!
154 return res;
155 }
156
addAt(int idx,const NetAddr & addr)157 HostCfg *HostMap::addAt(int idx, const NetAddr &addr) {
158 Assert(0 <= idx && idx < 2*capacity());
159 Assert(addr);
160 Assert(!at(idx));
161 HostCfg *const h = new HostCfg(addr);
162 if (idx < capacity())
163 theStaticIndex[idx] = h;
164 else {
165 Assert(addr.isDynamicName());
166 Assert(!theDynamicIndex.empty());
167 theDynamicIndex[idx - capacity()] = h;
168 }
169 ++theCount;
170 return h;
171 }
172
173 // returns true if there is no reason to search further (match or empty)
endSearch(const Array<HostCfg * > & arr,const NetAddr & addr,int idx,bool & res) const174 bool HostMap::endSearch(const Array<HostCfg*> &arr, const NetAddr &addr, int idx, bool &res) const {
175 if (HostCfg *h = arr[idx]) {
176 if (h->theAddr == addr)
177 return res = true;
178 return res = false;
179 }
180
181 // found empty slot
182 res = false;
183 return true;
184 }
185
hash0(const NetAddr & addr) const186 int HostMap::hash0(const NetAddr &addr) const {
187 return addr.hash0() % capacity();
188 //return abs((int)(addr.lna() + addr.port())) % capacity();
189 }
190
hash1(const NetAddr & addr) const191 int HostMap::hash1(const NetAddr &addr) const {
192 return addr.hash1() % capacity();
193 //return abs((int)(addr.lna() ^ addr.port() + addr.net())) % capacity();
194 }
195