forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
LinkTable.cpp
1 
9 #include "LinkTable.h"
10 
11 namespace forest {
12 
14 LinkTable::LinkTable(int maxLnk1) : maxLnk(maxLnk1) {
15  lnkTbl = new LinkInfo[maxLnk+1];
16  links = new UiSetPair(maxLnk);
17  ht = new UiHashTbl(maxLnk);
18  padrMap = new UiHashTbl(maxLnk);
19 };
20 
23  delete [] lnkTbl; delete links; delete ht; delete padrMap;
24 }
25 
34 int LinkTable::addEntry(int lnk, ipa_t peerIp, ipp_t peerPort, uint64_t nonce) {
35  if (lnk == 0) lnk = links->firstOut();
36  if (lnk == 0 || !links->isOut(lnk)) return 0;
37  if (peerIp != 0 && peerPort != 0) {
38  if (ht->lookup(hashkey(peerIp, peerPort)) != 0) return 0;
39  if (!ht->insert(hashkey(peerIp, peerPort),lnk)) return 0;
40  } else {
41  if (ht->lookup(nonce) != 0) return 0;
42  if (!ht->insert(nonce,lnk)) return 0;
43  }
44  links->swap(lnk);
45  lnkTbl[lnk].peerIp = peerIp;
46  lnkTbl[lnk].peerPort = peerPort;
47  lnkTbl[lnk].nonce = nonce;
48  lnkTbl[lnk].peerAdr = 0;
49  setIface(lnk,0);
50  setPeerType(lnk,Forest::UNDEF_NODE);
51  getRates(lnk).set(Forest::MINBITRATE,Forest::MINBITRATE,
53  getAvailRates(lnk).set( Forest::MINBITRATE,Forest::MINBITRATE,
55  lnkTbl[lnk].comtSet = new set<int>();
56  return lnk;
57 }
58 
64 bool LinkTable::remapEntry(int lnk, ipa_t peerIp, ipp_t peerPort) {
65  if (!links->isIn(lnk)) return false;
66  if (ht->lookup(lnkTbl[lnk].nonce) != lnk) return false;
67  ht->remove(lnkTbl[lnk].nonce);
68  if (!ht->insert(hashkey(peerIp, peerPort),lnk)) {
69  ht->insert(lnkTbl[lnk].nonce,lnk); return false;
70  }
71  lnkTbl[lnk].peerIp = peerIp;
72  lnkTbl[lnk].peerPort = peerPort;
73  return true;
74 }
75 
79 bool LinkTable::revertEntry(int lnk) {
80  if (!links->isIn(lnk)) return false;
81  ipa_t peerIp = lnkTbl[lnk].peerIp;
82  ipp_t peerPort = lnkTbl[lnk].peerPort;
83  if (ht->lookup(hashkey(peerIp, peerPort)) != lnk) return false;
84  ht->remove(hashkey(peerIp, peerPort));
85  if (!ht->insert(lnkTbl[lnk].nonce,lnk)) {
86  ht->insert(hashkey(peerIp, peerPort),lnk);
87  return false;
88  }
89  lnkTbl[lnk].peerIp = 0;
90  lnkTbl[lnk].peerPort = 0;
91  return true;
92 }
93 
115 void LinkTable::setPeerAdr(int lnk, fAdr_t adr) {
116  if (!valid(lnk)) return;
117  if (getPeerAdr(lnk) != 0 && getPeerType(lnk) != Forest::ROUTER) {
118  uint64_t x = lnkTbl[lnk].peerAdr; x <<= 32;
119  x |= lnkTbl[lnk].peerAdr;
120  padrMap->remove(x);
121  }
122  if (adr != 0 && getPeerType(lnk) != Forest::ROUTER) {
123  uint64_t x = adr; x <<= 32; x |= adr;
124  padrMap->insert(x,lnk);
125  }
126  lnkTbl[lnk].peerAdr = adr;
127 }
128 
129 
133 void LinkTable::removeEntry(int lnk) {
134  if (!links->isIn(lnk)) return;
135  ht->remove(hashkey(getPeerIpAdr(lnk),getPeerPort(lnk)));
136  delete lnkTbl[lnk].comtSet;
137  links->swap(lnk);
138 }
139 
144 bool LinkTable::checkEntry(int lnk) {
145  // the forest address of every peer must be a valid unicast address
146  if (!Forest::validUcastAdr(getPeerAdr(lnk))) return false;
147 
148  // only a router may use the forest port number
149  if (getPeerPort(lnk) == Forest::ROUTER_PORT &&
150  getPeerType(lnk) != Forest::ROUTER)
151  return false;
152 
153  return true;
154 }
155 
173 int LinkTable::readEntry(istream& in) {
174  int lnk, iface; RateSpec rs;
175  ipa_t peerIp; ipp_t peerPort;
176  Forest::ntyp_t peerType; int peerAdr;
177  string typStr;
178 
179  Misc::skipBlank(in);
180  if ( !Misc::readNum(in,lnk) ||
181  !Misc::readNum(in,iface) ||
182  !Np4d::readIpAdr(in,peerIp) || !Misc::verify(in,':') ||
183  !Misc::readNum(in,peerPort) ||
184  !Misc::readWord(in,typStr) ||
185  !Forest::readForestAdr(in,peerAdr) ||
186  !rs.read(in)) {
187  return 0;
188  }
189  Misc::cflush(in,'\n');
190 
191  peerType = Forest::getNodeType(typStr);
192  if (peerType == Forest::UNDEF_NODE) return 0;
193 
194  if (!addEntry(lnk,peerIp,peerPort,0)) return 0;
195  setIface(lnk,iface);
196  setPeerType(lnk, peerType);
197  setPeerAdr(lnk, peerAdr);
198  getRates(lnk) = rs; getAvailRates(lnk) = rs;
199 
200  if (!checkEntry(lnk)) { removeEntry(lnk); return 0; }
201 
202  return lnk;
203 }
204 
215 bool LinkTable::read(istream& in) {
216  int num;
217  Misc::skipBlank(in);
218  if (!Misc::readNum(in,num)) return false;
219  Misc::cflush(in,'\n');
220  for (int i = 1; i <= num; i++) {
221  if (readEntry(in) == 0) {
222  cerr << "LinkTable::read: could not read "
223  << i << "-th table entry" << endl;
224  return false;
225  }
226  }
227  return true;
228 }
229 
235 string& LinkTable::link2string(int lnk, string& s) const {
236  if (!valid(lnk)) { s = ""; return s; }
237  stringstream ss;
238  ss << setw(5) << right << lnk << setw(6) << getIface(lnk) << " ";
239 
240  ss << setw(12) << Np4d::ip2string(getPeerIpAdr(lnk),s)
241  << ":" << setw(5) << left << getPeerPort(lnk) << " ";
242  ss << setw(10) << left << Forest::nodeType2string(getPeerType(lnk),s);
243  ss << " " << setw(10) << left <<Forest::fAdr2string(getPeerAdr(lnk),s);
244  ss << " " << getRates(lnk).toString(s);
245  ss << " " << getAvailRates(lnk).toString(s);
246  ss << " " << lnkTbl[lnk].comtCount;
247  s = ss.str();
248  return s;
249 }
250 
255 string& LinkTable::toString(string& s) const {
256  stringstream ss;
257  ss << links->getNumIn() << endl;
258  ss << "# link iface peerIp:port peerType peerAdr ";
259  ss << " rates avail rates comtree count\n";
260  for (int i = firstLink(); i != 0; i = nextLink(i))
261  ss << link2string(i,s) << endl;
262  s = ss.str();
263  return s;
264 }
265 
266 #define pack8(x) (*buf = *((char*) x), buf += 1)
267 #define pack16(x) (*buf = *((char*) htons(x)), buf += sizeof(uint16_t))
268 #define pack32(x) (*buf = *((char*) htonl(x)), buf += sizeof(uint32_t))
269 #define pack64(x) ( pack32(((x)>>32)&0xffffffff), pack32((x)&0xffffffff))
270 #define packRspec(x) ( pack32(x.bitRateUp), pack32(x.bitRateDown), \
271  pack32(x.pktRateUp), pack32(x.pktRateDown) )
272 
277 char* LinkTable::pack(int lnk, char *buf) const {
278  if (!valid(lnk)) return 0;
279  pack32(lnk);
280  pack32(lnkTbl[lnk].iface);
281 
282  pack32(lnkTbl[lnk].peerIp);
283  pack16(lnkTbl[lnk].peerPort);
284  uint16_t x = lnkTbl[lnk].peerType; pack16(x);
285  pack16(lnkTbl[lnk].peerType);
286  pack32(lnkTbl[lnk].peerAdr);
287 
288  pack8(lnkTbl[lnk].status);
289  pack64(lnkTbl[lnk].nonce);
290 
291  packRspec(lnkTbl[lnk].rates);
292  packRspec(lnkTbl[lnk].availRates);
293 
294  pack32(lnkTbl[lnk].comtCount);
295  return buf;
296 }
297 
298 #define unpack8(x) (x = *buf, buf += 1)
299 #define unpack16(x) (x = ntohs(*((uint16_t*) buf)), buf += sizeof(uint16_t))
300 #define unpack32(x) (x = ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t))
301 #define unpack64(x) (x = ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t), \
302  x |= ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t))
303 #define unpackRspec(x) (pack32(x.bitRateUp), pack32(x.bitRateDown), \
304  pack32(x.pktRateUp), pack32(x.pktRateDown) )
305 
309 char* LinkTable::unpack(int lnk, char *buf) {
310  if (!valid(lnk)) return 0;
311  unpack32(lnk);
312  unpack32(lnkTbl[lnk].iface);
313 
314  unpack32(lnkTbl[lnk].peerIp);
315  unpack16(lnkTbl[lnk].peerPort);
316  uint16_t x; unpack16(x); lnkTbl[lnk].peerType = (Forest::ntyp_t) x;
317  unpack32(lnkTbl[lnk].peerAdr);
318 
319  unpack8(lnkTbl[lnk].status);
320  unpack64(lnkTbl[lnk].nonce);
321 
322  unpackRspec(lnkTbl[lnk].rates);
323  unpackRspec(lnkTbl[lnk].availRates);
324 
325  unpack32(lnkTbl[lnk].comtCount);
326  return buf;
327 }
328 
329 } // ends namespace
330