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->getIp()
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 isKeyListInitialized = false;
00066 WATCH_UNORDERED_MAP(peerStorage.getPeerHashMap());
00067 WATCH_VECTOR(keyList);
00068 WATCH(landmarkPeerSize);
00069
00070 landmarkPeerSize = 0;
00071
00072 for (int i = 0; i < MAX_NODETYPES; i++) {
00073 landmarkPeerSizePerType[i] = 0;
00074 }
00075
00076 preKilledNodes = 0;
00077
00078 if (par("maliciousNodeChange")) {
00079 if ((double) par("maliciousNodeProbability") > 0)
00080 error("maliciousNodeProbability and maliciousNodeChange are not supported concurrently");
00081
00082 cMessage* msg = new cMessage("maliciousNodeChange");
00083 scheduleAt(simTime() + (int) par("maliciousNodeChangeStartTime"), msg);
00084 maliciousNodesVector.setName("MaliciousNodeRate");
00085 maliciousNodesVector.record(0);
00086 maliciousNodeRatio = 0;
00087 }
00088
00089 for (int i=0; i<MAX_NODETYPES; i++) {
00090 for (int j=0; j<MAX_NODETYPES; j++) {
00091 connectionMatrix[i][j] = true;
00092 }
00093 }
00094
00095 globalStatistics = GlobalStatisticsAccess().get();
00096
00097 cMessage* timer = new cMessage("oracleTimer");
00098
00099 scheduleAt(simTime(), timer);
00100 }
00101
00102 void GlobalNodeList::handleMessage(cMessage* msg)
00103 {
00104 if (msg->isName("maliciousNodeChange")) {
00105 double newRatio = maliciousNodeRatio + (double) par("maliciousNodeChangeRate");
00106 if (maliciousNodeRatio < (double) par("maliciousNodeChangeStartValue"))
00107 newRatio = (double) par("maliciousNodeChangeStartValue");
00108
00109 if (newRatio < (double) par("maliciousNodeChangeStopValue"))
00110 scheduleAt(simTime() + (int) par("maliciousNodeChangeInterval"), msg);
00111
00112 int nodesNeeded = (int) (((double) par("maliciousNodeChangeRate")) * peerStorage.size());
00113
00114 EV << "[GlobalNodeList::handleMessage()]\n"
00115 << " Changing " << nodesNeeded << " nodes to be malicious"
00116 << endl;
00117
00118 for (int i = 0; i < nodesNeeded; i++) {
00119
00120 NodeHandle node;
00121 do {
00122 node = getRandomNode(0, false);
00123 } while (isMalicious(node));
00124
00125 setMalicious(node, true);
00126 }
00127
00128 maliciousNodesVector.record(newRatio);
00129 maliciousNodeRatio = newRatio;
00130
00131 return;
00132 }
00133
00134 else if (msg->isName("oracleTimer")) {
00135 RECORD_STATS(globalStatistics->recordOutVector(
00136 "GlobalNodeList: Number of nodes", peerStorage.size()));
00137 scheduleAt(simTime() + 50, msg);
00138 } else {
00139 opp_error("GlobalNodeList::handleMessage: Unknown message type!");
00140 }
00141 }
00142
00143 const NodeHandle& GlobalNodeList::getBootstrapNode(const NodeHandle &node)
00144 {
00145 uint32_t nodeType;
00146 PeerHashMap::iterator it;
00147
00148
00149
00150
00151 if (!node.isUnspecified()) {
00152 it = peerStorage.find(node.getIp());
00153
00154
00155 if (it == peerStorage.end()) {
00156 return getRandomNode(0, true);
00157 }
00158
00159 nodeType = it->second.info->getTypeID();
00160 const NodeHandle &tempNode1 = getRandomNode(nodeType, true);
00161
00162 if (tempNode1.isUnspecified()) {
00163 for (uint32_t i = 0; i < MAX_NODETYPES; i++) {
00164 if (i == nodeType)
00165 continue;
00166
00167 if (connectionMatrix[nodeType][i]) {
00168 const NodeHandle &tempNode2 = getRandomNode(i, true);
00169 if (!tempNode2.isUnspecified())
00170 return tempNode2;
00171 }
00172 }
00173 return NodeHandle::UNSPECIFIED_NODE;
00174 } else {
00175 return tempNode1;
00176 }
00177 } else {
00178 return getRandomNode(0, true);
00179 }
00180 }
00181
00182 const NodeHandle& GlobalNodeList::getRandomNode(int32_t nodeType,
00183 bool bootstrappedNeeded,
00184 bool inoffensiveNeeded)
00185 {
00186 PeerHashMap::iterator it = peerStorage.getRandomNode(nodeType,
00187 bootstrappedNeeded,
00188 inoffensiveNeeded);
00189 if (it == peerStorage.end()) {
00190 return NodeHandle::UNSPECIFIED_NODE;
00191 }
00192
00193 if (dynamic_cast<NodeHandle*>(it->second.node)) {
00194 return *dynamic_cast<NodeHandle*>(it->second.node);
00195 } else {
00196 return NodeHandle::UNSPECIFIED_NODE;
00197 }
00198 }
00199
00200 void GlobalNodeList::sendNotificationToAllPeers(int category)
00201 {
00202 PeerHashMap::iterator it;
00203 for (it = peerStorage.begin(); it != peerStorage.end(); it++) {
00204 NotificationBoard* nb = check_and_cast<NotificationBoard*>(
00205 simulation.getModule(it->second.info->getModuleID())
00206 ->getSubmodule("notificationBoard"));
00207
00208 nb->fireChangeNotification(category);
00209 }
00210 }
00211
00212 void GlobalNodeList::addPeer(const IPvXAddress& ip, PeerInfo* info)
00213 {
00214 BootstrapEntry temp;
00215 temp.node = new TransportAddress(ip);
00216 temp.info = info;
00217 temp.info->setPreKilled(false);
00218
00219 peerStorage.insert(std::make_pair(temp.node->getIp(), temp));
00220
00221 if (uniform(0, 1) < (double) par("maliciousNodeProbability") ||
00222 (par("maliciousNodeChange") && uniform(0, 1) < maliciousNodeRatio)) {
00223 setMalicious(*temp.node, true);
00224 }
00225
00226 if (peerStorage.size() == 1) {
00227
00228 setMalicious(*temp.node, false);
00229 }
00230 }
00231
00232 void GlobalNodeList::registerPeer(const TransportAddress& peer)
00233 {
00234 PeerHashMap::iterator it = peerStorage.find(peer.getIp());
00235
00236 if (it == peerStorage.end()) {
00237 throw cRuntimeError("GlobalNodeList::registerPeer(): "
00238 "Peer is not in peer set");
00239 } else {
00240 delete it->second.node;
00241 it->second.node = new TransportAddress(peer);
00242 peerStorage.setBootstrapped(it, true);
00243 }
00244 }
00245
00246 void GlobalNodeList::registerPeer(const NodeHandle& peer)
00247 {
00248 PeerHashMap::iterator it = peerStorage.find(peer.getIp());
00249
00250 if (it == peerStorage.end()) {
00251 throw cRuntimeError("GlobalNodeList::registerPeer(): "
00252 "Peer is not in peer set");
00253 } else {
00254 delete it->second.node;
00255 it->second.node = new NodeHandle(peer);
00256 peerStorage.setBootstrapped(it, true);
00257 }
00258 }
00259
00260 void GlobalNodeList::refreshEntry(const TransportAddress& peer)
00261 {
00262 PeerHashMap::iterator it = peerStorage.find(peer.getIp());
00263
00264 if (it == peerStorage.end()) {
00265 throw cRuntimeError("GlobalNodeList::refreshEntry(): "
00266 "Peer is not in peer set");
00267 } else {
00268 delete it->second.node;
00269 it->second.node = new TransportAddress(peer);
00270 }
00271 }
00272
00273 void GlobalNodeList::removePeer(const TransportAddress& peer)
00274 {
00275 PeerHashMap::iterator it = peerStorage.find(peer.getIp());
00276
00277 if (it != peerStorage.end()) {
00278 peerStorage.setBootstrapped(it, false);
00279 }
00280 }
00281
00282 void GlobalNodeList::killPeer(const IPvXAddress& ip)
00283 {
00284 PeerHashMap::iterator it = peerStorage.find(ip);
00285 if (it != peerStorage.end()) {
00286 if (it->second.info->isPreKilled()) {
00287 it->second.info->setPreKilled(false);
00288 preKilledNodes--;
00289 }
00290
00291
00292 PeerInfo* peerInfo = it->second.info;
00293 if (peerInfo->getNpsLayer() > -1) {
00294 landmarkPeerSize--;
00295 landmarkPeerSizePerType[it->second.info->getTypeID()]--;
00296 }
00297
00298 peerStorage.erase(it);
00299 }
00300 }
00301
00302 PeerInfo* GlobalNodeList::getPeerInfo(const TransportAddress& peer)
00303 {
00304 return getPeerInfo(peer.getIp());
00305 }
00306
00307 PeerInfo* GlobalNodeList::getPeerInfo(const IPvXAddress& ip)
00308 {
00309 PeerHashMap::iterator it = peerStorage.find(ip);
00310
00311 if (it == peerStorage.end())
00312 return NULL;
00313 else
00314 return it->second.info;
00315 }
00316
00317 PeerInfo* GlobalNodeList::getRandomPeerInfo(int32_t nodeType,
00318 bool bootstrappedNeeded)
00319 {
00320 PeerHashMap::iterator it = peerStorage.getRandomNode(nodeType,
00321 bootstrappedNeeded,
00322 false);
00323 if (it == peerStorage.end()) {
00324 return NULL;
00325 } else {
00326 return it->second.info;
00327 }
00328 }
00329
00330 void GlobalNodeList::setPreKilled(const TransportAddress& address)
00331 {
00332 PeerInfo* peer = getPeerInfo(address);
00333
00334 if ((peer != NULL) && !(peer->isPreKilled())) {
00335 preKilledNodes++;
00336 peer->setPreKilled(true);
00337 }
00338 }
00339
00340
00341 TransportAddress* GlobalNodeList::getRandomAliveNode(int32_t nodeType)
00342 {
00343 if (peerStorage.size() <= preKilledNodes) {
00344
00345 return NULL;
00346 } else {
00347 PeerHashMap::iterator it = peerStorage.getRandomNode(nodeType, false,
00348 false);
00349 while (it != peerStorage.end()) {
00350 if (!it->second.info->isPreKilled()) {
00351 return it->second.node;
00352 } else {
00353 it = peerStorage.getRandomNode(nodeType, false, false);
00354 }
00355 }
00356 return NULL;
00357 }
00358 }
00359
00360 void GlobalNodeList::setMalicious(const TransportAddress& address, bool malicious)
00361 {
00362 peerStorage.setMalicious(peerStorage.find(address.getIp()), malicious);
00363 }
00364
00365 bool GlobalNodeList::isMalicious(const TransportAddress& address)
00366 {
00367 PeerInfo* peer = getPeerInfo(address);
00368
00369 if (peer != NULL) {
00370 return peer->isMalicious();
00371 }
00372
00373 return false;
00374 }
00375
00376 cObject** GlobalNodeList::getContext(const TransportAddress& address)
00377 {
00378 PeerInfo* peer = getPeerInfo(address);
00379
00380 if (peer != NULL) {
00381 return peer->getContext();
00382 }
00383
00384 return NULL;
00385 }
00386
00387 void GlobalNodeList::setOverlayReadyIcon(const TransportAddress& address,
00388 bool ready)
00389 {
00390 if (ev.isGUI()) {
00391 const char* color;
00392
00393 if (ready) {
00394
00395 color = isMalicious(address) ? "green" : "";
00396 } else {
00397 color = isMalicious(address) ? "yellow" : "red";
00398 }
00399
00400 PeerInfo* info = getPeerInfo(address);
00401
00402 if (info != NULL) {
00403 simulation.getModule(info->getModuleID())->
00404 getDisplayString().setTagArg("i2", 1, color);
00405 }
00406 }
00407 }
00408
00409 bool GlobalNodeList::areNodeTypesConnected(int32_t a, int32_t b)
00410 {
00411 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00412 throw cRuntimeError("GlobalNodeList::areNodeTypesConnected(): nodeType "
00413 "bigger then MAX_NODETYPES");
00414 }
00415
00416 return connectionMatrix[a][b];
00417 }
00418
00419 void GlobalNodeList::connectNodeTypes(int32_t a, int32_t b)
00420 {
00421 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00422 throw cRuntimeError("GlobalNodeList::connectNodeTypes(): nodeType "
00423 "bigger then MAX_NODETYPES");
00424 }
00425
00426 connectionMatrix[a][b]=true;
00427
00428 EV << "[GlobalNodeList::connectNodeTypes()]\n"
00429 << " Connecting " << a << "->" << b
00430 << endl;
00431
00432 }
00433
00434 void GlobalNodeList::disconnectNodeTypes(int32_t a, int32_t b)
00435 {
00436 if ((a > MAX_NODETYPES) || (b > MAX_NODETYPES)) {
00437 throw cRuntimeError("GlobalNodeList::disconnectNodeTypes(): nodeType "
00438 "bigger then MAX_NODETYPES");
00439 }
00440
00441 connectionMatrix[a][b]=false;
00442
00443 EV << "[GlobalNodeList::disconnectNodeTypes()]\n"
00444 << " Disconnecting " << a << "->" << b
00445 << endl;
00446
00447 }
00448
00449 void GlobalNodeList::mergeBootstrapNodes(int toPartition, int fromPartition,
00450 int numNodes)
00451 {
00452 BootstrapList* bootstrapList =
00453 check_and_cast<BootstrapList*>(simulation.getModule(
00454 getRandomPeerInfo(toPartition, false)->getModuleID())->
00455 getSubmodule("bootstrapList"));
00456
00457 bootstrapList->insertBootstrapCandidate(getRandomNode(fromPartition, true),
00458 DNSSD);
00459 }
00460
00461
00462 void GlobalNodeList::createKeyList(uint32_t size)
00463 {
00464 for (uint32_t i = 0; i < size; i++)
00465 keyList.push_back(OverlayKey::random());
00466 }
00467
00468 GlobalNodeList::KeyList* GlobalNodeList::getKeyList(uint32_t maximumKeys)
00469 {
00470 if( !isKeyListInitialized ) createKeyList(maxNumberOfKeys);
00471 if (maximumKeys > keyList.size()) {
00472 maximumKeys = keyList.size();
00473 }
00474
00475 KeyList tmpKeyList;
00476 tmpKeyList.clear();
00477
00478 for (uint32_t i=0; i < keyList.size(); i++) {
00479 tmpKeyList.push_back(keyList[i]);
00480 }
00481
00482 KeyList* returnList = new KeyList;
00483
00484 for (uint32_t i=0; i < ((float)maximumKeys * keyProbability); i++) {
00485 uint32_t index = intuniform(0, tmpKeyList.size()-1);
00486
00487 returnList->push_back(tmpKeyList[index]);
00488 tmpKeyList.erase(tmpKeyList.begin()+index);
00489 }
00490
00491 return returnList;
00492 }
00493
00494 const OverlayKey& GlobalNodeList::getRandomKeyListItem()
00495 {
00496 if( !isKeyListInitialized ) createKeyList(maxNumberOfKeys);
00497 return keyList[intuniform(0,keyList.size()-1)];
00498 }