00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <iostream>
00025
00026 #include <omnetpp.h>
00027
00028 #include <NotificationBoard.h>
00029 #include <BinaryValue.h>
00030 #include <OverlayKey.h>
00031 #include <PeerInfo.h>
00032 #include <BaseOverlay.h>
00033 #include <GlobalStatisticsAccess.h>
00034 #include <hashWatch.h>
00035 #include <BootstrapList.h>
00036
00037 #include "GlobalNodeList.h"
00038
00039 Define_Module(GlobalNodeList);
00040
00041 std::ostream& operator<<(std::ostream& os, const bootstrapEntry entry)
00042 {
00043 NodeHandle* nodeHandle = dynamic_cast<NodeHandle*>(entry.node);
00044
00045 os << "Address: " << entry.node->getAddress()
00046 << " Port: " << entry.node->getPort();
00047
00048 if (nodeHandle) {
00049 os << " NodeId: " << nodeHandle->getKey();
00050 }
00051
00052 os << " ModuleID: "
00053 << entry.info->getModuleID() << " Bootstrapped: "
00054 << (entry.info->isBootstrapped() ? "true" : "false")
00055 << " NPS Layer: " << ((int) entry.info->getNpsLayer())
00056 << " TypeID: " << (entry.info->getTypeID());
00057
00058 return os;
00059 }
00060
00061 void GlobalNodeList::initialize()
00062 {
00063 maxNumberOfKeys = par("maxNumberOfKeys");
00064 keyProbability = par("keyProbability");
00065
00066 WATCH_UNORDERED_MAP(peerSet);
00067 WATCH_VECTOR(keyList);
00068 WATCH(bootstrappedPeerSize);
00069 WATCH(bootstrappedMaliciousNodes);
00070 WATCH(maliciousNodes);
00071 WATCH(landmarkPeerSize);
00072
00073 createKeyList(maxNumberOfKeys);
00074 bootstrappedPeerSize = 0;
00075 landmarkPeerSize = 0;
00076
00077 for (int i = 0; i < MAX_NODETYPES; i++) {
00078 bootstrappedPeerSizePerType[i] = 0;
00079 landmarkPeerSizePerType[i] = 0;
00080 }
00081
00082 bootstrappedMaliciousNodes = 0;
00083 maliciousNodes = 0;
00084 preKilledNodes = 0;
00085
00086 if (par("maliciousNodeChange")) {
00087 if ((double) par("maliciousNodeProbability") > 0)
00088 error("maliciousNodeProbability and maliciousNodeChange are not supported concurrently");
00089
00090 cMessage* msg = new cMessage("maliciousNodeChange");
00091 scheduleAt(simTime() + (int) par("maliciousNodeChangeStartTime"), msg);
00092 maliciousNodesVector.setName("MaliciousNodeRate");
00093 maliciousNodesVector.record(0);
00094 maliciousNodeRatio = 0;
00095 }
00096
00097 min_ip = 0xFFFFFFFF;
00098 max_ip = 0x00000000;
00099
00100 for (int i=0; i<MAX_NODETYPES; i++) {
00101 for (int j=0; j<MAX_NODETYPES; j++) {
00102 connectionMatrix[i][j] = true;
00103 }
00104 }
00105
00106 globalStatistics = GlobalStatisticsAccess().get();
00107
00108 cMessage* timer = new cMessage("oracleTimer");
00109
00110 scheduleAt(simTime(), timer);
00111 }
00112
00113 void GlobalNodeList::handleMessage(cMessage* msg)
00114 {
00115 if (msg->isName("maliciousNodeChange")) {
00116 double newRatio = maliciousNodeRatio + (double) par("maliciousNodeChangeRate");
00117 if (maliciousNodeRatio < (double) par("maliciousNodeChangeStartValue"))
00118 newRatio = (double) par("maliciousNodeChangeStartValue");
00119
00120 if (newRatio < (double) par("maliciousNodeChangeStopValue"))
00121 scheduleAt(simTime() + (int) par("maliciousNodeChangeInterval"), msg);
00122
00123 int nodesNeeded = (int) (((double) par("maliciousNodeChangeRate")) * peerSet.size());
00124
00125 EV << "[GlobalNodeList::handleMessage()]\n"
00126 << " Changing " << nodesNeeded << " nodes to be malicious"
00127 << endl;
00128
00129 for (int i = 0; i < nodesNeeded; i++) {
00130
00131 NodeHandle node;
00132 do {
00133 node = getRandomNode(0, false);
00134 } while (isMalicious(node));
00135
00136 setMalicious(node, true);
00137 }
00138
00139 maliciousNodesVector.record(newRatio);
00140 maliciousNodeRatio = newRatio;
00141
00142 return;
00143 }
00144
00145 else if (msg->isName("oracleTimer")) {
00146 RECORD_STATS(globalStatistics->recordOutVector(
00147 "GlobalNodeList: Number of nodes", peerSet.size()));
00148 RECORD_STATS(globalStatistics->recordOutVector(
00149 "GlobalNodeList: Number of bootstrapped malicious nodes",
00150 bootstrappedMaliciousNodes));
00151 scheduleAt(simTime() + 50, msg);
00152 } else {
00153 opp_error("GlobalNodeList::handleMessage: Unknown message type!");
00154 }
00155 }
00156
00157 const NodeHandle& GlobalNodeList::getBootstrapNode(const NodeHandle &node)
00158 {
00159 uint32_t nodeType;
00160 PeerHashMap::iterator it;
00161
00162
00163
00164
00165 if (!node.isUnspecified()) {
00166 it = peerSet.find(node.getAddress());
00167
00168
00169 if (it == peerSet.end()) {
00170 return getRandomNode(0, true);
00171 }
00172
00173 nodeType = it->second.info->getTypeID();
00174 const NodeHandle &tempNode1 = getRandomNode(nodeType, true);
00175
00176 if (tempNode1.isUnspecified()) {
00177 for (uint32_t i = 1; i < MAX_NODETYPES; i++) {
00178 if (i == nodeType)
00179 continue;
00180
00181 if (connectionMatrix[nodeType][i]) {
00182 const NodeHandle &tempNode2 = getRandomNode(i, true);
00183 if (!tempNode2.isUnspecified())
00184 return tempNode2;
00185 }
00186 }
00187 return NodeHandle::UNSPECIFIED_NODE;
00188 } else {
00189 return tempNode1;
00190 }
00191 } else {
00192 return getRandomNode(0, true);
00193 }
00194 }
00195
00196 const NodeHandle& GlobalNodeList::getRandomNode(uint32_t nodeType,
00197 bool bootstrappedNeeded,
00198 bool inoffensiveNeeded)
00199 {
00200 if (inoffensiveNeeded &&
00201 ((nodeType != 0) || (bootstrappedNeeded == false))) {
00202 throw cRuntimeError("GlobalNodeList::getRandomNode(): "
00203 "inoffensiveNeeded must only be used "
00204 "with nodeType = 0 and bootstrappedNeeded = true!");
00205 }
00206
00207 if (peerSet.size() == 0)
00208 return NodeHandle::UNSPECIFIED_NODE;
00209 if (bootstrappedNeeded && bootstrappedPeerSize == 0)
00210 return NodeHandle::UNSPECIFIED_NODE;
00211 if (nodeType && bootstrappedPeerSizePerType[nodeType] == 0)
00212 return NodeHandle::UNSPECIFIED_NODE;
00213 if (inoffensiveNeeded &&
00214 (bootstrappedPeerSize - bootstrappedMaliciousNodes <= 0))
00215 return NodeHandle::UNSPECIFIED_NODE;
00216 else {
00217
00218 PeerHashMap::iterator it = peerSet.end();
00219 bootstrapEntry tempEntry = {NULL, NULL};
00220
00221 while (it == peerSet.end() ||(nodeType && (it->second.info->getTypeID() != nodeType))
00222 || (bootstrappedNeeded && !it->second.info->isBootstrapped())
00223 || (inoffensiveNeeded && it->second.info->isMalicious())) {
00224
00225 IPvXAddress randomAddr(intuniform(min_ip, max_ip));
00226
00227 it = peerSet.find(randomAddr);
00228
00229 if (it == peerSet.end()) {
00230 it = peerSet.insert(std::make_pair(randomAddr,tempEntry)).first;
00231 peerSet.erase(it++);
00232 }
00233
00234 if (it == peerSet.end())
00235 it = peerSet.begin();
00236 }
00237
00238 if (dynamic_cast<NodeHandle*>(it->second.node)) {
00239 return *dynamic_cast<NodeHandle*>(it->second.node);
00240 } else {
00241 return NodeHandle::UNSPECIFIED_NODE;
00242 }
00243 }
00244 }
00245
00246 void GlobalNodeList::sendNotificationToAllPeers(int category)
00247 {
00248 PeerHashMap::iterator it;
00249 for (it = peerSet.begin(); it != peerSet.end(); it++) {
00250 NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00251 simulation.getModule(it->second.info->getModuleID())
00252 ->getSubmodule("notificationBoard"));
00253
00254 nb->fireChangeNotification(category);
00255 }
00256 }
00257
00258 void GlobalNodeList::addPeer(const IPvXAddress& ip, PeerInfo* info)
00259 {
00260 bootstrapEntry temp;
00261 temp.node = new TransportAddress(ip);
00262 temp.info = info;
00263 temp.info->setPreKilled(false);
00264
00265 peerSet.insert(std::make_pair(temp.node->getAddress(), temp));
00266
00267
00268 if (ip.get4().getInt() < min_ip) min_ip = ip.get4().getInt();
00269 if (ip.get4().getInt() > max_ip) max_ip = ip.get4().getInt();
00270
00271 if (uniform(0, 1) < (double) par("maliciousNodeProbability") ||
00272 (par("maliciousNodeChange") && uniform(0, 1) < maliciousNodeRatio)) {
00273 setMalicious(*temp.node, true);
00274 }
00275
00276 if (peerSet.size() == 1) {
00277
00278 setMalicious(*temp.node, false);
00279 }
00280 }
00281
00282 void GlobalNodeList::registerPeer(const TransportAddress& peer)
00283 {
00284 PeerHashMap::iterator it = peerSet.find(peer.getAddress());
00285 if (it == peerSet.end())
00286 error("unable to bootstrap peer, peer is not in peer set");
00287 else {
00288 PeerInfo* info = it->second.info;
00289
00290 if (!info->isBootstrapped()) {
00291 bootstrappedPeerSize++;
00292 bootstrappedPeerSizePerType[info->getTypeID()]++;
00293 info->setBootstrapped();
00294
00295 if (info->isMalicious())
00296 bootstrappedMaliciousNodes++;
00297 }
00298
00299 delete it->second.node;
00300 peerSet.erase(it);
00301
00302 bootstrapEntry temp;
00303 temp.node = new TransportAddress(peer);
00304 temp.info = info;
00305 peerSet.insert(std::make_pair(temp.node->getAddress(), temp));
00306 }
00307 }
00308
00309 void GlobalNodeList::registerPeer(const NodeHandle& peer)
00310 {
00311 PeerHashMap::iterator it = peerSet.find(peer.getAddress());
00312 if (it == peerSet.end())
00313 error("unable to bootstrap peer, peer is not in peer set");
00314 else {
00315 PeerInfo* info = it->second.info;
00316
00317 if (!info->isBootstrapped()) {
00318 bootstrappedPeerSize++;
00319 bootstrappedPeerSizePerType[info->getTypeID()]++;
00320 info->setBootstrapped();
00321
00322 if (info->isMalicious())
00323 bootstrappedMaliciousNodes++;
00324 }
00325
00326 delete it->second.node;
00327 peerSet.erase(it);
00328
00329 bootstrapEntry temp;
00330 temp.node = new NodeHandle(peer);
00331 temp.info = info;
00332 peerSet.insert(std::make_pair(temp.node->getAddress(), temp));
00333 }
00334 }
00335
00336 void GlobalNodeList::refreshEntry(const TransportAddress& peer)
00337 {
00338 PeerHashMap::iterator it = peerSet.find(peer.getAddress());
00339 if (it == peerSet.end()) {
00340 error("unable to refresh entry, peer is not in peer set");
00341 } else {
00342 PeerInfo* info = it->second.info;
00343
00344 delete it->second.node;
00345 peerSet.erase(it);
00346
00347 bootstrapEntry temp;
00348 temp.node = new TransportAddress(peer);
00349 temp.info = info;
00350 peerSet.insert(std::make_pair(temp.node->getAddress(), temp));
00351 }
00352 }
00353
00354 void GlobalNodeList::removePeer(const TransportAddress& peer)
00355 {
00356 PeerHashMap::iterator it = peerSet.find(peer.getAddress());
00357 if(it != peerSet.end() && it->second.info->isBootstrapped()) {
00358 bootstrappedPeerSize--;
00359 bootstrappedPeerSizePerType[it->second.info->getTypeID()]--;
00360 it->second.info->setBootstrapped(false);
00361
00362 if(it->second.info->isMalicious())
00363 bootstrappedMaliciousNodes--;
00364
00365 it->second.info->setBootstrapped(false);
00366 }
00367 }
00368
00369 void GlobalNodeList::killPeer(const IPvXAddress& ip)
00370 {
00371 PeerHashMap::iterator it = peerSet.find(ip);
00372 if(it != peerSet.end()) {
00373 if(it->second.info->isBootstrapped()) {
00374 bootstrappedPeerSize--;
00375 bootstrappedPeerSizePerType[it->second.info->getTypeID()]--;
00376
00377 if(it->second.info->isMalicious())
00378 bootstrappedMaliciousNodes--;
00379
00380 it->second.info->setBootstrapped(false);
00381 }
00382
00383 if (it->second.info->isPreKilled()) {
00384 it->second.info->setPreKilled(false);
00385 preKilledNodes--;
00386 }
00387
00388
00389 PeerInfo* peerInfo = getPeerInfo(ip);
00390 if (peerInfo->getNpsLayer() > -1) {
00391 landmarkPeerSize--;
00392 landmarkPeerSizePerType[it->second.info->getTypeID()]--;
00393 }
00394
00395 delete it->second.node;
00396 delete it->second.info;
00397 peerSet.erase(it);
00398 }
00399 }
00400
00401 void GlobalNodeList::createKeyList(uint32_t size)
00402 {
00403 for (uint32_t i = 0; i < size; i++)
00404 keyList.push_back(OverlayKey::random());
00405 }
00406
00407 GlobalNodeList::KeyList* GlobalNodeList::getKeyList(uint32_t maximumKeys)
00408 {
00409 if (maximumKeys > keyList.size()) {
00410 maximumKeys = keyList.size();
00411 }
00412
00413 KeyList tmpKeyList;
00414 tmpKeyList.clear();
00415
00416 for (uint32_t i=0; i < keyList.size(); i++) {
00417 tmpKeyList.push_back(keyList[i]);
00418 }
00419
00420 KeyList* returnList = new KeyList;
00421
00422 for (uint32_t i=0; i < ((float)maximumKeys * keyProbability); i++) {
00423 uint32_t index = intuniform(0, tmpKeyList.size()-1);
00424
00425 returnList->push_back(tmpKeyList[index]);
00426 tmpKeyList.erase(tmpKeyList.begin()+index);
00427 }
00428
00429 return returnList;
00430 }
00431
00432 const OverlayKey& GlobalNodeList::getRandomKeyListItem() const
00433 {
00434 return keyList[intuniform(0,keyList.size()-1)];
00435 }
00436
00437 PeerInfo* GlobalNodeList::getPeerInfo(const TransportAddress& peer)
00438 {
00439 PeerHashMap::iterator it = peerSet.find(peer.getAddress());
00440
00441 if (it == peerSet.end())
00442 return NULL;
00443 else
00444 return it->second.info;
00445 }
00446
00447 PeerInfo* GlobalNodeList::getPeerInfo(const IPvXAddress& ip)
00448 {
00449 PeerHashMap::iterator it = peerSet.find(ip);
00450
00451 if (it == peerSet.end())
00452 return NULL;
00453 else
00454 return it->second.info;
00455 }
00456
00457 PeerInfo* GlobalNodeList::getRandomPeerInfo(uint32_t nodeType,
00458 bool bootstrappedNeeded) {
00459
00460 PeerHashMap::iterator it;
00461 bootstrapEntry tempEntry = {NULL, NULL};
00462
00463 IPvXAddress randomAddr(intuniform(min_ip, max_ip));
00464
00465 it = peerSet.find(randomAddr);
00466 if (it == peerSet.end()) {
00467 it = peerSet.insert(std::make_pair(randomAddr,tempEntry)).first;
00468 peerSet.erase(it++);
00469 }
00470
00471 if (it == peerSet.end())
00472 it = peerSet.begin();
00473
00474
00475 if (nodeType) {
00476 while((nodeType && (it->second.info->getTypeID() != nodeType))
00477 || (bootstrappedNeeded && !it->second.info->isBootstrapped())) {
00478 ++it;
00479 if (it == peerSet.end()) it = peerSet.begin();
00480 }
00481 }
00482
00483 return it->second.info;
00484 }
00485
00486 void GlobalNodeList::setPreKilled(const TransportAddress& address)
00487 {
00488 PeerInfo* peer = getPeerInfo(address);
00489
00490 if ((peer != NULL) && !(peer->isPreKilled())) {
00491 preKilledNodes++;
00492 peer->setPreKilled(true);
00493 }
00494 }
00495
00496 TransportAddress* GlobalNodeList::getRandomAliveNode(uint32_t nodeType)
00497 {
00498 if (peerSet.size() <= preKilledNodes) {
00499
00500 return NULL;
00501 } else {
00502
00503 PeerHashMap::iterator it;
00504 bootstrapEntry tempEntry = {NULL, NULL};
00505
00506 IPvXAddress randomAddr(intuniform(min_ip, max_ip));
00507
00508 it = peerSet.find(randomAddr);
00509
00510 if (it == peerSet.end()) {
00511 it = peerSet.insert(std::make_pair(randomAddr,tempEntry)).first;
00512 peerSet.erase(it++);
00513 }
00514
00515 if (it == peerSet.end()) {
00516 it = peerSet.begin();
00517 }
00518
00519 while ((nodeType && (it->second.info->getTypeID() != nodeType))
00520 || it->second.info->isPreKilled()) {
00521 it++;
00522 if (it == peerSet.end()) {
00523 it = peerSet.begin();
00524 }
00525 }
00526
00527 return it->second.node;
00528 }
00529
00530 return NULL;
00531 }
00532
00533 void GlobalNodeList::setMalicious(const TransportAddress& address, bool malicious)
00534 {
00535 PeerInfo* peer = getPeerInfo(address);
00536
00537 if (peer != NULL) {
00538 if(malicious && !peer->isMalicious()) {
00539 maliciousNodes++;
00540 if (peer->isBootstrapped()) {
00541 bootstrappedMaliciousNodes++;
00542 }
00543 }
00544
00545 if (!malicious && peer->isMalicious()) {
00546 maliciousNodes--;
00547 if (peer->isBootstrapped()) {
00548 bootstrappedMaliciousNodes--;
00549 }
00550 }
00551 peer->setMalicious(malicious);
00552 }
00553 }
00554
00555 bool GlobalNodeList::isMalicious(const TransportAddress& address)
00556 {
00557 PeerInfo* peer = getPeerInfo(address);
00558
00559 if(peer != NULL)
00560 return peer->isMalicious();
00561
00562 return false;
00563 }
00564
00565 cObject** GlobalNodeList::getContext(const TransportAddress& address)
00566 {
00567 PeerInfo* peer = getPeerInfo(address);
00568
00569 if(peer != NULL)
00570 return peer->getContext();
00571
00572 return NULL;
00573 }
00574
00575 void GlobalNodeList::setOverlayReadyIcon(const TransportAddress& address,
00576 bool ready)
00577 {
00578 if (ev.isGUI()) {
00579 const char* color;
00580
00581 if (ready) {
00582
00583 color = isMalicious(address) ? "green" : "";
00584 } else {
00585 color = isMalicious(address) ? "yellow" : "red";
00586 }
00587
00588 PeerInfo* info = getPeerInfo(address);
00589
00590 if(info != NULL) {
00591 simulation.getModule(info->getModuleID())
00592 ->getDisplayString().setTagArg("i2", 1, color);
00593 }
00594 }
00595 }
00596
00597 bool GlobalNodeList::areNodeTypesConnected(uint32_t a, uint32_t b)
00598 {
00599 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00600 throw cRuntimeError("GlobalNodeList::areNodeTypesConnected(): nodeType "
00601 "bigger then MAX_NODETYPES");
00602 }
00603
00604 return connectionMatrix[a][b];
00605 }
00606
00607 void GlobalNodeList::connectNodeTypes(uint32_t a, uint32_t b)
00608 {
00609 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00610 throw cRuntimeError("GlobalNodeList::connectNodeTypes(): nodeType "
00611 "bigger then MAX_NODETYPES");
00612 }
00613
00614 connectionMatrix[a][b]=true;
00615
00616 EV << "[GlobalNodeList::connectNodeTypes()]\n"
00617 << " Connecting " << a << "->" << b
00618 << endl;
00619
00620 }
00621
00622 void GlobalNodeList::disconnectNodeTypes(uint32_t a, uint32_t b)
00623 {
00624 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00625 throw cRuntimeError("GlobalNodeList::disconnectNodeTypes(): nodeType "
00626 "bigger then MAX_NODETYPES");
00627 }
00628
00629 connectionMatrix[a][b]=false;
00630
00631 EV << "[GlobalNodeList::disconnectNodeTypes()]\n"
00632 << " Disconnecting " << a << "->" << b
00633 << endl;
00634
00635 }
00636
00637 void GlobalNodeList::mergeBootstrapNodes(int toPartition, int fromPartition,
00638 int numNodes)
00639 {
00640 BootstrapList* bootstrapList =
00641 check_and_cast<BootstrapList*>(simulation.getModule(
00642 getRandomPeerInfo(toPartition, false)->getModuleID())->
00643 getSubmodule("bootstrapList"));
00644
00645 bootstrapList->insertBootstrapCandidate(getRandomNode(fromPartition, true),
00646 DNSSD);
00647 }
00648
00649 GlobalNodeList::~GlobalNodeList()
00650 {
00651 PeerHashMap::iterator it;
00652 for(it = peerSet.begin(); it != peerSet.end(); ++it) {
00653 delete it->second.node;
00654 delete it->second.info;
00655 }
00656 }
00657