forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
LinkTablesav.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 
39 int LinkTable::addEntry(int lnk, ipa_t peerIp, ipp_t peerPort, uint64_t nonce) {
40  if (lnk == 0) lnk = links->firstOut();
41  if (lnk == 0 || !links->isOut(lnk)) return 0;
42  if (ht->lookup(nonce) != 0) return 0;
43  if (!ht->insert(nonce,lnk)) return 0;
44 
45  links->swap(lnk);
46  lnkTbl[lnk].status = false;
47  lnkTbl[lnk].peerIp = peerIp;
48  lnkTbl[lnk].peerPort = peerPort;
49  lnkTbl[lnk].nonce = nonce;
50  lnkTbl[lnk].peerAdr = 0;
51  setIface(lnk,0);
52  setPeerType(lnk,Forest::UNDEF_NODE);
53  getRates(lnk).set(Forest::MINBITRATE,Forest::MINBITRATE,
55  getAvailRates(lnk).set( Forest::MINBITRATE,Forest::MINBITRATE,
57  lnkTbl[lnk].comtSet = new set<int>();
58  return lnk;
59 }
60 
68 bool LinkTable::connect(int lnk, ipa_t peerIp, ipp_t peerPort) {
69  if (!links->isIn(lnk) || isConnected(lnk)) return false;
70  if (ht->lookup(lnkTbl[lnk].nonce) != lnk) return false;
71  ht->remove(lnkTbl[lnk].nonce);
72  if (!ht->insert(hashkey(peerIp, peerPort),lnk)) {
73  ht->insert(lnkTbl[lnk].nonce,lnk); return false;
74  }
75  lnkTbl[lnk].peerIp = peerIp;
76  lnkTbl[lnk].peerPort = peerPort;
77  lnkTbl[lnk].status = true;
78  return true;
79 }
80 
84 void LinkTable::removeEntry(int lnk) {
85  if (!links->isIn(lnk)) return;
86  if (isConnected(lnk)) {
87  ht->remove(hashkey(getPeerIpAdr(lnk),getPeerPort(lnk)));
88  } else {
89  ht->remove(getNonce(lnk));
90  }
91  delete lnkTbl[lnk].comtSet;
92  links->swap(lnk);
93 }
94 
99 void LinkTable::setPeerAdr(int lnk, fAdr_t adr) {
100  if (!valid(lnk)) return;
101  if (getPeerAdr(lnk) != 0 && getPeerType(lnk) != Forest::ROUTER) {
102  uint64_t x = lnkTbl[lnk].peerAdr; x <<= 32;
103  x |= lnkTbl[lnk].peerAdr;
104  padrMap->remove(x);
105  }
106  if (adr != 0 && getPeerType(lnk) != Forest::ROUTER) {
107  uint64_t x = adr; x <<= 32; x |= adr;
108  padrMap->insert(x,lnk);
109  }
110  lnkTbl[lnk].peerAdr = adr;
111 }
112 
117 bool LinkTable::checkEntry(int lnk) {
118  // the forest address of every peer must be a valid unicast address
119  if (!Forest::validUcastAdr(getPeerAdr(lnk))) return false;
120 
121  // only a router may use the forest port number
122  if (getPeerPort(lnk) == Forest::ROUTER_PORT &&
123  getPeerType(lnk) != Forest::ROUTER)
124  return false;
125 
126  return true;
127 }
128 
146 int LinkTable::readEntry(istream& in) {
147  int lnk, iface; RateSpec rs;
148  ipa_t peerIp; ipp_t peerPort;
149  Forest::ntyp_t peerType; int peerAdr;
150  string typStr;
151 
152  Misc::skipBlank(in);
153  if ( !Misc::readNum(in,lnk) ||
154  !Misc::readNum(in,iface) ||
155  !Np4d::readIpAdr(in,peerIp) || !Misc::verify(in,':') ||
156  !Misc::readNum(in,peerPort) ||
157  !Misc::readWord(in,typStr) ||
158  !Forest::readForestAdr(in,peerAdr) ||
159  !rs.read(in)) {
160  return 0;
161  }
162  Misc::cflush(in,'\n');
163 
164  peerType = Forest::getNodeType(typStr);
165  if (peerType == Forest::UNDEF_NODE) return 0;
166 
167  if (!addEntry(lnk,peerIp,peerPort,0)) return 0;
168  setIface(lnk,iface);
169  setPeerType(lnk, peerType);
170  setPeerAdr(lnk, peerAdr);
171  getRates(lnk) = rs; getAvailRates(lnk) = rs;
172 
173  if (!checkEntry(lnk)) { removeEntry(lnk); return 0; }
174 
175  return lnk;
176 }
177 
188 bool LinkTable::read(istream& in) {
189  int num;
190  Misc::skipBlank(in);
191  if (!Misc::readNum(in,num)) return false;
192  Misc::cflush(in,'\n');
193  for (int i = 1; i <= num; i++) {
194  if (readEntry(in) == 0) {
195  cerr << "LinkTable::read: could not read "
196  << i << "-th table entry" << endl;
197  return false;
198  }
199  }
200  return true;
201 }
202 
208 string& LinkTable::link2string(int lnk, string& s) const {
209  if (!valid(lnk)) { s = ""; return s; }
210  stringstream ss;
211  ss << setw(5) << right << lnk << setw(6) << getIface(lnk) << " ";
212 
213  ss << setw(12) << Np4d::ip2string(getPeerIpAdr(lnk),s)
214  << ":" << setw(5) << left << getPeerPort(lnk) << " ";
215  ss << setw(10) << left << Forest::nodeType2string(getPeerType(lnk),s);
216  ss << " " << setw(10) << left <<Forest::fAdr2string(getPeerAdr(lnk),s);
217  ss << " " << getRates(lnk).toString(s);
218  ss << " " << getAvailRates(lnk).toString(s);
219  ss << " " << lnkTbl[lnk].comtCount;
220  s = ss.str();
221  return s;
222 }
223 
228 string& LinkTable::toString(string& s) const {
229  stringstream ss;
230  ss << links->getNumIn() << endl;
231  ss << "# link iface peerIp:port peerType peerAdr ";
232  ss << " rates avail rates comtree count\n";
233  for (int i = firstLink(); i != 0; i = nextLink(i))
234  ss << link2string(i,s) << endl;
235  s = ss.str();
236  return s;
237 }
238 
239 #define pack8(x) (*buf = *((char*) x), buf += 1)
240 #define pack16(x) (*buf = *((char*) htons(x)), buf += sizeof(uint16_t))
241 #define pack32(x) (*buf = *((char*) htonl(x)), buf += sizeof(uint32_t))
242 #define pack64(x) ( pack32(((x)>>32)&0xffffffff), pack32((x)&0xffffffff))
243 #define packRspec(x) ( pack32(x.bitRateUp), pack32(x.bitRateDown), \
244  pack32(x.pktRateUp), pack32(x.pktRateDown) )
245 
250 char* LinkTable::pack(int lnk, char *buf) const {
251  if (!valid(lnk)) return 0;
252  pack32(lnk);
253  pack32(lnkTbl[lnk].iface);
254 
255  pack32(lnkTbl[lnk].peerIp);
256  pack16(lnkTbl[lnk].peerPort);
257  uint16_t x = lnkTbl[lnk].peerType; pack16(x);
258  pack16(lnkTbl[lnk].peerType);
259  pack32(lnkTbl[lnk].peerAdr);
260 
261  pack8(lnkTbl[lnk].status);
262  pack64(lnkTbl[lnk].nonce);
263 
264  packRspec(lnkTbl[lnk].rates);
265  packRspec(lnkTbl[lnk].availRates);
266 
267  pack32(lnkTbl[lnk].comtCount);
268  return buf;
269 }
270 
271 #define unpack8(x) (x = *buf, buf += 1)
272 #define unpack16(x) (x = ntohs(*((uint16_t*) buf)), buf += sizeof(uint16_t))
273 #define unpack32(x) (x = ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t))
274 #define unpack64(x) (x = ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t), \
275  x |= ntohl(*((uint32_t*) buf)), buf += sizeof(uint32_t))
276 #define unpackRspec(x) (pack32(x.bitRateUp), pack32(x.bitRateDown), \
277  pack32(x.pktRateUp), pack32(x.pktRateDown) )
278 
282 char* LinkTable::unpack(int lnk, char *buf) {
283  if (!valid(lnk)) return 0;
284  unpack32(lnk);
285  unpack32(lnkTbl[lnk].iface);
286 
287  unpack32(lnkTbl[lnk].peerIp);
288  unpack16(lnkTbl[lnk].peerPort);
289  uint16_t x; unpack16(x); lnkTbl[lnk].peerType = (Forest::ntyp_t) x;
290  unpack32(lnkTbl[lnk].peerAdr);
291 
292  unpack8(lnkTbl[lnk].status);
293  unpack64(lnkTbl[lnk].nonce);
294 
295  unpackRspec(lnkTbl[lnk].rates);
296  unpackRspec(lnkTbl[lnk].availRates);
297 
298  unpack32(lnkTbl[lnk].comtCount);
299  return buf;
300 }
301 
302 } // ends namespace
303