OverSim
GlobalNodeList.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include <iostream>
25 
26 #include <omnetpp.h>
27 
28 #include <NotificationBoard.h>
29 #include <BinaryValue.h>
30 #include <OverlayKey.h>
31 #include <PeerInfo.h>
32 #include <BaseOverlay.h>
33 #include <GlobalStatisticsAccess.h>
34 #include <hashWatch.h>
35 #include <BootstrapList.h>
36 
37 #include "GlobalNodeList.h"
38 
40 
41 std::ostream& operator<<(std::ostream& os, const BootstrapEntry& entry)
42 {
43  for (AddrPerOverlayVector::const_iterator it2 = entry.addrVector.begin();
44  it2 != entry.addrVector.end(); it2++) {
45 
46  NodeHandle* nodeHandle = dynamic_cast<NodeHandle*>(it2->ta);
47 
48  os << "Overlay " << it2->overlayId << ": " << *(it2->ta);
49 
50  if (nodeHandle) {
51  os << " (" << nodeHandle->getKey() << ")";
52  }
53 
54  if (it2->bootstrapped == false) {
55  os << " [NOT BOOTSTRAPPED]";
56  }
57  }
58 
59  os << " " << *(entry.info);
60 
61  return os;
62 }
63 
65 {
66  maxNumberOfKeys = par("maxNumberOfKeys");
67  keyProbability = par("keyProbability");
68  isKeyListInitialized = false;
70  WATCH_VECTOR(keyList);
71  WATCH(landmarkPeerSize);
72 
73  landmarkPeerSize = 0;
74 
75  for (int i = 0; i < MAX_NODETYPES; i++) {
77  }
78 
79  preKilledNodes = 0;
80 
81  if (par("maliciousNodeChange")) {
82  if ((double) par("maliciousNodeProbability") > 0)
83  error("maliciousNodeProbability and maliciousNodeChange are not supported concurrently");
84 
85  cMessage* msg = new cMessage("maliciousNodeChange");
86  scheduleAt(simTime() + (int) par("maliciousNodeChangeStartTime"), msg);
87  maliciousNodesVector.setName("MaliciousNodeRate");
88  maliciousNodesVector.record(0);
90  }
91 
92  for (int i=0; i<MAX_NODETYPES; i++) {
93  for (int j=0; j<MAX_NODETYPES; j++) {
94  connectionMatrix[i][j] = true;
95  }
96  }
97 
99 
100  cMessage* timer = new cMessage("oracleTimer");
101 
102  scheduleAt(simTime(), timer);
103 }
104 
105 void GlobalNodeList::handleMessage(cMessage* msg)
106 {
107  if (msg->isName("maliciousNodeChange")) {
108  double newRatio = maliciousNodeRatio + (double) par("maliciousNodeChangeRate"); // ratio to obtain
109  if (maliciousNodeRatio < (double) par("maliciousNodeChangeStartValue"))
110  newRatio = (double) par("maliciousNodeChangeStartValue");
111 
112  if (newRatio < (double) par("maliciousNodeChangeStopValue")) // schedule next event
113  scheduleAt(simTime() + (int) par("maliciousNodeChangeInterval"), msg);
114 
115  int nodesNeeded = (int) (((double) par("maliciousNodeChangeRate")) * peerStorage.size());
116 
117  EV << "[GlobalNodeList::handleMessage()]\n"
118  << " Changing " << nodesNeeded << " nodes to be malicious"
119  << endl;
120 
121  for (int i = 0; i < nodesNeeded; i++) {
122  // search a node that is not yet malicious
123  NodeHandle node;
124  do {
125  node = getRandomNode(-1, -1, false, true);
126  } while (isMalicious(node));
127 
128  setMalicious(node, true);
129  }
130 
131  maliciousNodesVector.record(newRatio);
132  maliciousNodeRatio = newRatio;
133 
134  return;
135  }
136 
137  else if (msg->isName("oracleTimer")) {
139  "GlobalNodeList: Number of nodes", peerStorage.size()));
140  scheduleAt(simTime() + 50, msg);
141  } else {
142  opp_error("GlobalNodeList::handleMessage: Unknown message type!");
143  }
144 }
145 
147  const NodeHandle &node)
148 {
149  uint32_t nodeType;
150  PeerHashMap::iterator it;
151 
152  // always prefer boot node from the same TypeID
153  // if there is no such node, go through all
154  // connected partitions until a bootstrap node is found
155  if (!node.isUnspecified()) {
156  it = peerStorage.find(node.getIp());
157 
158  // this should never happen
159  if (it == peerStorage.end()) {
160  return getRandomNode(overlayId);
161  }
162 
163  nodeType = it->second.info->getTypeID();
164  const NodeHandle &tempNode1 = getRandomNode(overlayId, nodeType);
165 
166  if (tempNode1.isUnspecified()) {
167  for (uint32_t i = 0; i < MAX_NODETYPES; i++) {
168  if (i == nodeType)
169  continue;
170 
171  if (connectionMatrix[nodeType][i]) {
172  const NodeHandle &tempNode2 = getRandomNode(overlayId, i);
173 
174  if (!tempNode2.isUnspecified())
175  return tempNode2;
176  }
177  }
179  } else {
180  return tempNode1;
181  }
182  } else {
183  return getRandomNode(overlayId);
184  }
185 }
186 
187 const NodeHandle& GlobalNodeList::getRandomNode(int32_t overlayId,
188  int32_t nodeType,
189  bool bootstrappedNeeded,
190  bool inoffensiveNeeded)
191 {
192  PeerHashMap::iterator it = peerStorage.getRandomNode(overlayId,
193  nodeType,
194  bootstrappedNeeded,
195  inoffensiveNeeded);
196  if (it == peerStorage.end()) {
198  }
199 
200  TransportAddress* addr = NULL;
201 
202  if (overlayId >= 0) {
203  addr = it->second.addrVector.getAddrForOverlayId(overlayId);
204  } else {
205  // std::cout << "Info: " << *(it->second.info) << std::endl;
206  // std::cout << "Size: " << it->second.addrVector.size() << std::endl;
207  addr = it->second.addrVector[0].ta;
208  }
209 
210  if (dynamic_cast<NodeHandle*>(addr)) {
211  return *dynamic_cast<NodeHandle*>(addr);
212  } else {
214  }
215 }
216 
218 {
219  PeerHashMap::iterator it;
220  for (it = peerStorage.begin(); it != peerStorage.end(); it++) {
221  NotificationBoard* nb = check_and_cast<NotificationBoard*>(
222  simulation.getModule(it->second.info->getModuleID())
223  ->getSubmodule("notificationBoard"));
224 
225  nb->fireChangeNotification(category);
226  }
227 }
228 
229 void GlobalNodeList::addPeer(const IPvXAddress& ip, PeerInfo* info)
230 {
231  BootstrapEntry temp;
232  temp.info = info;
233  temp.info->setPreKilled(false);
234 
235  peerStorage.insert(std::make_pair(ip, temp));
236 
237  if (uniform(0, 1) < (double) par("maliciousNodeProbability") ||
238  (par("maliciousNodeChange") && uniform(0, 1) < maliciousNodeRatio)) {
239  setMalicious(TransportAddress(ip), true);
240  }
241 
242  if (peerStorage.size() == 1) {
243  // we need at least one inoffensive bootstrap node
244  setMalicious(TransportAddress(ip), false);
245  }
246 }
247 
249  int32_t overlayId)
250 {
251  PeerHashMap::iterator it = peerStorage.find(peer.getIp());
252 
253  if (it == peerStorage.end()) {
254  throw cRuntimeError("GlobalNodeList::registerPeer(): "
255  "Peer is not in peer set");
256  } else {
257  peerStorage.registerOverlay(it, peer, overlayId);
258  peerStorage.setBootstrapped(it, overlayId, true);
259  }
260 }
261 
263  int32_t overlayId)
264 {
265  PeerHashMap::iterator it = peerStorage.find(peer.getIp());
266 
267  if (it == peerStorage.end()) {
268  throw cRuntimeError("GlobalNodeList::refreshEntry(): "
269  "Peer is not in peer set");
270  } else {
271  it->second.addrVector.setAddrForOverlayId(new TransportAddress(peer),
272  overlayId);
273  }
274 }
275 
277  int32_t overlayId)
278 {
279  PeerHashMap::iterator it = peerStorage.find(peer.getIp());
280 
281  if (it != peerStorage.end()) {
282  peerStorage.setBootstrapped(it, overlayId, false);
283  }
284 }
285 
286 void GlobalNodeList::killPeer(const IPvXAddress& ip)
287 {
288  PeerHashMap::iterator it = peerStorage.find(ip);
289  if (it != peerStorage.end()) {
290  if (it->second.info->isPreKilled()) {
291  it->second.info->setPreKilled(false);
292  preKilledNodes--;
293  }
294 
295  // if valid NPS landmark: decrease landmarkPeerSize
296  PeerInfo* peerInfo = it->second.info;
297  if (peerInfo->getNpsLayer() > -1) {
299  landmarkPeerSizePerType[it->second.info->getTypeID()]--;
300  }
301 
302  peerStorage.erase(it);
303  }
304 }
305 
307 {
308  return getPeerInfo(peer.getIp());
309 }
310 
311 PeerInfo* GlobalNodeList::getPeerInfo(const IPvXAddress& ip)
312 {
313  PeerHashMap::iterator it = peerStorage.find(ip);
314 
315  if (it == peerStorage.end())
316  return NULL;
317  else
318  return it->second.info;
319 }
320 
322  int32_t nodeType,
323  bool bootstrappedNeeded)
324 {
325  PeerHashMap::iterator it = peerStorage.getRandomNode(overlayId,
326  nodeType,
327  bootstrappedNeeded,
328  false);
329  if (it == peerStorage.end()) {
330  return NULL;
331  } else {
332  return it->second.info;
333  }
334 }
335 
337 {
338  PeerInfo* peer = getPeerInfo(address);
339 
340  if ((peer != NULL) && !(peer->isPreKilled())) {
341  preKilledNodes++;
342  peer->setPreKilled(true);
343  }
344 }
345 
346 // TODO: this method should be removed in the future
348  int32_t nodeType)
349 {
350  if (peerStorage.size() <= preKilledNodes) {
351  // all nodes are already marked for deletion;
352  return NULL;
353  } else {
354  PeerHashMap::iterator it = peerStorage.getRandomNode(overlayId,
355  nodeType, false,
356  false);
357  while (it != peerStorage.end()) {
358  if (!it->second.info->isPreKilled()) {
359  // TODO: returns always the first node from addrVector
360  if (it->second.addrVector.size()) {
361  return it->second.addrVector[0].ta;
362  } else {
363  return NULL;
364  }
365  } else {
366  it = peerStorage.getRandomNode(overlayId, nodeType, false,
367  false);
368  }
369  }
370  return NULL;
371  }
372 }
373 
374 void GlobalNodeList::setMalicious(const TransportAddress& address, bool malicious)
375 {
376  peerStorage.setMalicious(peerStorage.find(address.getIp()), malicious);
377 }
378 
380 {
381  PeerInfo* peer = getPeerInfo(address);
382 
383  if (peer != NULL) {
384  return peer->isMalicious();
385  }
386 
387  return false;
388 }
389 
391 {
392  PeerInfo* peer = getPeerInfo(address);
393 
394  if (peer != NULL) {
395  return peer->getContext();
396  }
397 
398  return NULL;
399 }
400 
402  bool ready)
403 {
404  if (ev.isGUI()) {
405  const char* color;
406 
407  if (ready) {
408  // change color if node is malicious
409  color = isMalicious(address) ? "green" : "";
410  } else {
411  color = isMalicious(address) ? "yellow" : "red";
412  }
413 
414  PeerInfo* info = getPeerInfo(address);
415 
416  if (info != NULL) {
417  simulation.getModule(info->getModuleID())->
418  getDisplayString().setTagArg("i2", 1, color);
419  }
420  }
421 }
422 
423 bool GlobalNodeList::areNodeTypesConnected(int32_t a, int32_t b)
424 {
425  if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
426  throw cRuntimeError("GlobalNodeList::areNodeTypesConnected(): nodeType "
427  "bigger then MAX_NODETYPES");
428  }
429 
430  return connectionMatrix[a][b];
431 }
432 
433 void GlobalNodeList::connectNodeTypes(int32_t a, int32_t b)
434 {
435  if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
436  throw cRuntimeError("GlobalNodeList::connectNodeTypes(): nodeType "
437  "bigger then MAX_NODETYPES");
438  }
439 
440  connectionMatrix[a][b]=true;
441 
442  EV << "[GlobalNodeList::connectNodeTypes()]\n"
443  << " Connecting " << a << "->" << b
444  << endl;
445 
446 }
447 
448 void GlobalNodeList::disconnectNodeTypes(int32_t a, int32_t b)
449 {
450  if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
451  throw cRuntimeError("GlobalNodeList::disconnectNodeTypes(): nodeType "
452  "bigger then MAX_NODETYPES");
453  }
454 
455  connectionMatrix[a][b]=false;
456 
457  EV << "[GlobalNodeList::disconnectNodeTypes()]\n"
458  << " Disconnecting " << a << "->" << b
459  << endl;
460 
461 }
462 
463 void GlobalNodeList::mergeBootstrapNodes(int toPartition, int fromPartition,
464  int numNodes)
465 {
466  BootstrapList* bootstrapList =
467  check_and_cast<BootstrapList*>(simulation.getModule(
468  getRandomPeerInfo(toPartition, false)->getModuleID())->
469  getSubmodule("bootstrapList"));
470 
471  bootstrapList->insertBootstrapCandidate(getRandomNode(-1, fromPartition,
472  true, false),
473  DNSSD);
474 }
475 
476 
477 void GlobalNodeList::createKeyList(uint32_t size)
478 {
479  for (uint32_t i = 0; i < size; i++)
480  keyList.push_back(OverlayKey::random());
481 }
482 
484 {
486  if (maximumKeys > keyList.size()) {
487  maximumKeys = keyList.size();
488  }
489  // copy keylist to temporary keylist
490  KeyList tmpKeyList;
491  tmpKeyList.clear();
492 
493  for (uint32_t i=0; i < keyList.size(); i++) {
494  tmpKeyList.push_back(keyList[i]);
495  }
496 
497  KeyList* returnList = new KeyList;
498 
499  for (uint32_t i=0; i < ((float)maximumKeys * keyProbability); i++) {
500  uint32_t index = intuniform(0, tmpKeyList.size()-1);
501 
502  returnList->push_back(tmpKeyList[index]);
503  tmpKeyList.erase(tmpKeyList.begin()+index);
504  }
505 
506  return returnList;
507 }
508 
510 {
513 
514  return keyList[intuniform(0,keyList.size()-1)];
515 }
516 
517 std::vector<IPvXAddress>* GlobalNodeList::getAllIps()
518 {
519  std::vector<IPvXAddress>* ips = new std::vector<IPvXAddress>;
520 
521  const PeerHashMap::iterator it = peerStorage.begin();
522 
523  while (it != peerStorage.end()) {
524  ips->push_back(it->first);
525  }
526 
527  return ips;
528 }
529 
530 NodeHandle* GlobalNodeList::getNodeHandle(const IPvXAddress& address){
531  PeerHashMap::iterator it = peerStorage.find(address);
532  if (it == peerStorage.end()) {
533  throw cRuntimeError("GlobalNodeList::getNodeHandle(const IPvXAddress& address): "
534  "Peer is not in peer set");
535  }
536 
537  BootstrapEntry* tempEntry = &(it->second);
538 
539  if ((tempEntry == NULL) || (tempEntry->addrVector.empty()) ||
540  (tempEntry->addrVector[0].ta == NULL)) {
541  return NULL;
542  }
543 
544  NodeHandle* ret = dynamic_cast<NodeHandle*> (tempEntry->addrVector[0].ta);
545  return ret;
546 }
547