00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <IPAddressResolver.h>
00025 #include <XmlRpcInterface.h>
00026 #include <P2pnsMessage_m.h>
00027
00028 #include "P2pns.h"
00029
00030 Define_Module(P2pns);
00031
00032 using namespace std;
00033
00034 P2pns::P2pns()
00035 {
00036 p2pnsCache = NULL;
00037 }
00038
00039 P2pns::~P2pns()
00040 {
00041 }
00042
00043 void P2pns::initializeApp(int stage)
00044 {
00045 if (stage != MIN_STAGE_APP)
00046 return;
00047
00048 twoStageResolution = par("twoStageResolution");
00049 keepaliveInterval = par("keepaliveInterval");
00050 idCacheLifetime = par("idCacheLifetime");
00051
00052 p2pnsCache = check_and_cast<P2pnsCache*> (getParentModule()->
00053 getSubmodule("p2pnsCache"));
00054
00055 xmlRpcInterface = dynamic_cast<XmlRpcInterface*>(overlay->
00056 getCompModule(TIER3_COMP));
00057 }
00058
00059 void P2pns::handleReadyMessage(CompReadyMessage* msg)
00060 {
00061 if ((msg->getReady() == false) || (msg->getComp() != OVERLAY_COMP)) {
00062 delete msg;
00063 return;
00064 }
00065
00066 thisId = (overlay->getThisNode().getKey() >> (OverlayKey::getLength() - 100))
00067 << (OverlayKey::getLength() - 100);
00068 delete msg;
00069 }
00070
00071 void P2pns::tunnel(const OverlayKey& destKey, const BinaryValue& payload)
00072 {
00073 Enter_Method_Silent();
00074
00075 P2pnsIdCacheEntry* entry = p2pnsCache->getIdCacheEntry(destKey);
00076
00077 if (entry == NULL) {
00078
00079
00080 EV << "[P2pns::tunnel()]\n"
00081 << " Establishing new cache entry for key: " << destKey
00082 << endl;
00083
00084 LookupCall* lookupCall = new LookupCall();
00085 lookupCall->setKey(destKey);
00086 lookupCall->setNumSiblings(1);
00087 sendInternalRpcCall(OVERLAY_COMP, lookupCall, NULL, -1, 0,
00088 TUNNEL_LOOKUP);
00089 p2pnsCache->addIdCacheEntry(destKey, &payload);
00090 } else if (entry->state == CONNECTION_PENDING) {
00091
00092 EV << "[P2pns::tunnel()]\n"
00093 << " Queuing packet since lookup is still pending for key: "
00094 << destKey << endl;
00095
00096 entry->lastUsage = simTime();
00097 entry->payloadQueue.push_back(payload);
00098 } else {
00099 entry->lastUsage = simTime();
00100 sendTunnelMessage(entry->addr, payload);
00101 }
00102 }
00103
00104 void P2pns::handleTunnelLookupResponse(LookupResponse* lookupResponse)
00105 {
00106 P2pnsIdCacheEntry* entry =
00107 p2pnsCache->getIdCacheEntry(lookupResponse->getKey());
00108
00109 if ((entry == NULL) || (entry->state == CONNECTION_ACTIVE)) {
00110
00111
00112 return;
00113 }
00114
00115 if (lookupResponse->getIsValid()) {
00116
00117 if (lookupResponse->getKey().sharedPrefixLength(lookupResponse->
00118 getSiblings(0).getKey()) < (OverlayKey::getLength() - 100)) {
00119 EV << "[P2pns::handleTunnelLookupResponse()]\n"
00120 << " Lookup response " << lookupResponse->getSiblings(0)
00121 << " doesn't match requested id " << lookupResponse->getKey()
00122 << endl;
00123
00124 p2pnsCache->removeIdCacheEntry(lookupResponse->getKey());
00125
00126 return;
00127 }
00128
00129
00130 entry->addr = lookupResponse->getSiblings(0);
00131 entry->state = CONNECTION_ACTIVE;
00132
00133
00134 P2pnsKeepaliveTimer* msg =
00135 new P2pnsKeepaliveTimer("P2pnsKeepaliveTimer");
00136 msg->setKey(lookupResponse->getKey());
00137 scheduleAt(simTime() + keepaliveInterval, msg);
00138
00139
00140 while (!entry->payloadQueue.empty()) {
00141 sendTunnelMessage(entry->addr, entry->payloadQueue.front());
00142 entry->payloadQueue.pop_front();
00143 }
00144 } else {
00145
00146 p2pnsCache->removeIdCacheEntry(lookupResponse->getKey());
00147 }
00148 }
00149
00150 void P2pns::sendTunnelMessage(const TransportAddress& addr,
00151 const BinaryValue& payload)
00152 {
00153 EV << "[P2pns::sendTunnelMessage()]\n"
00154 << " Sending TUNNEL message to " << addr << endl;
00155
00156 P2pnsTunnelMessage* msg = new P2pnsTunnelMessage("P2pnsTunnelMsg");
00157 msg->setPayload(payload);
00158 msg->setSrcId(thisId);
00159 msg->setBitLength(P2PNSTUNNELMESSAGE_L(msg));
00160
00161 callRoute(OverlayKey::UNSPECIFIED_KEY, msg, addr);
00162 }
00163
00164 void P2pns::registerId(const std::string& addr)
00165 {
00166 Enter_Method_Silent();
00167
00168 std::string name = par("registerName").stdstringValue();
00169 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00170
00171 EV << "[P2pns::p2pnsRegisterRpc()]\n"
00172 << " registerId(): name: " << name << " addr: " << addr
00173 << endl;
00174
00175 dhtPutMsg->setKey(OverlayKey::sha1(BinaryValue(name)));
00176
00177 dhtPutMsg->setValue(BinaryValue(addr));
00178 dhtPutMsg->setKind(28);
00179 dhtPutMsg->setId(1);
00180 dhtPutMsg->setTtl(60*60*24*7);
00181 dhtPutMsg->setIsModifiable(true);
00182
00183 sendInternalRpcCall(TIER1_COMP, dhtPutMsg);
00184 }
00185
00186 void P2pns::deliver(OverlayKey& key, cMessage* msg)
00187 {
00188 P2pnsTunnelMessage* tunnelMsg = check_and_cast<P2pnsTunnelMessage*>(msg);
00189
00190 if (xmlRpcInterface) {
00191 xmlRpcInterface->deliverTunneledMessage(tunnelMsg->getPayload());
00192 }
00193
00194 updateIdCacheWithNewTransport(msg);
00195
00196 delete msg;
00197 }
00198
00199 void P2pns::pingRpcResponse(PingResponse* response, cPolymorphic* context,
00200 int rpcId, simtime_t rtt)
00201 {
00202 delete context;
00203 }
00204
00205 void P2pns::pingTimeout(PingCall* call, const TransportAddress& dest,
00206 cPolymorphic* context, int rpcId)
00207 {
00208 OverlayKeyObject* key = dynamic_cast<OverlayKeyObject*>(context);
00209 P2pnsIdCacheEntry* entry = NULL;
00210
00211
00212 if ((key != NULL) &&
00213 (entry = p2pnsCache->getIdCacheEntry(*key))) {
00214
00215
00216 if (!entry->addr.isUnspecified() && (entry->addr != dest)) {
00217 EV << "[P2pns::pingTimeout()]\n"
00218 << " Removing id " << key << " from idCache (ping timeout)"
00219 << endl;
00220 p2pnsCache->removeIdCacheEntry(*key);
00221 }
00222 }
00223
00224 delete context;
00225 }
00226
00227 void P2pns::handleTimerEvent(cMessage* msg)
00228 {
00229 P2pnsKeepaliveTimer* timer = dynamic_cast<P2pnsKeepaliveTimer*>(msg);
00230
00231 if (timer) {
00232 P2pnsIdCacheEntry* entry = p2pnsCache->getIdCacheEntry(timer->getKey());
00233
00234 if (entry == NULL) {
00235
00236 delete msg;
00237 return;
00238 }
00239
00240 if ((entry->lastUsage + idCacheLifetime) < simTime()) {
00241
00242 EV << "[P2pns::handleTimerEvent()]\n"
00243 << " Removing id " << timer->getKey()
00244 << " from idCache (connection idle)"
00245 << endl;
00246 p2pnsCache->removeIdCacheEntry(timer->getKey());
00247 delete msg;
00248 return;
00249 }
00250
00251 if (!entry->addr.isUnspecified()) {
00252
00253 pingNode(entry->addr, -1, 2, new OverlayKeyObject(timer->getKey()));
00254 }
00255
00256
00257 scheduleAt(simTime() + keepaliveInterval, msg);
00258
00259
00260 LookupCall* lookupCall = new LookupCall();
00261 lookupCall->setKey(overlay->getThisNode().getKey());
00262 lookupCall->setNumSiblings(1);
00263 lookupCall->setRoutingType(EXHAUSTIVE_ITERATIVE_ROUTING);
00264 sendInternalRpcCall(OVERLAY_COMP, lookupCall, NULL, -1, 0,
00265 TUNNEL_LOOKUP);
00266 }
00267 }
00268
00269 void P2pns::updateIdCacheWithNewTransport(cMessage* msg)
00270 {
00271
00272 OverlayCtrlInfo* ctrlInfo =
00273 dynamic_cast<OverlayCtrlInfo*>(msg->getControlInfo());
00274
00275 OverlayKey srcId;
00276
00277 if (!ctrlInfo) {
00278
00279 EV << "[P2pns::updateCacheWithNewTransport()]\n"
00280 << " Can't update cache without knowing the originator id"
00281 << endl;
00282 return;
00283 }
00284
00285 if (ctrlInfo->getSrcRoute().isUnspecified()) {
00286 P2pnsTunnelMessage* tunnelMsg = dynamic_cast<P2pnsTunnelMessage*>(msg);
00287 if (tunnelMsg) {
00288 srcId = tunnelMsg->getSrcId();
00289 } else {
00290
00291 EV << "[P2pns::updateCacheWithNewTransport()]\n"
00292 << " Can't update cache without knowing the originator id"
00293 << endl;
00294 return;
00295 }
00296 } else {
00297 srcId = (ctrlInfo->getSrcRoute().getKey() >> (OverlayKey::getLength() - 100))
00298 << (OverlayKey::getLength() - 100);
00299 }
00300
00301 P2pnsIdCacheEntry* entry = p2pnsCache->getIdCacheEntry(srcId);
00302
00303 if (entry == NULL) {
00304 EV << "[P2pns::updateCacheWithNewTransport()]\n"
00305 << " Adding new cache entry for id " << srcId
00306 << " with addr " << (const TransportAddress&)ctrlInfo->getSrcRoute()
00307 << endl;
00308 entry = p2pnsCache->addIdCacheEntry(srcId);
00309 entry->addr = ctrlInfo->getSrcRoute();
00310
00311
00312 P2pnsKeepaliveTimer* msg =
00313 new P2pnsKeepaliveTimer("P2pnsKeepaliveTimer");
00314 msg->setKey(srcId);
00315 scheduleAt(simTime() + keepaliveInterval, msg);
00316 }
00317
00318
00319
00320 if (entry->addr.isUnspecified() ||
00321 (entry->addr != ctrlInfo->getSrcRoute())) {
00322 EV << "[P2pns::handleRpcCall()]\n"
00323 << " Ping with new transport address received: "
00324 << " Changing from " << entry->addr << " to "
00325 << static_cast<TransportAddress>(ctrlInfo->getSrcRoute())
00326 << " for id " << srcId << endl;
00327 entry->addr = ctrlInfo->getSrcRoute();
00328 }
00329
00330 entry->state = CONNECTION_ACTIVE;
00331 }
00332
00333 bool P2pns::handleRpcCall(BaseCallMessage* msg)
00334 {
00335
00336 RPC_SWITCH_START(msg)
00337 RPC_ON_CALL(Ping) {
00338 updateIdCacheWithNewTransport(msg);
00339 return false;
00340 }
00341 RPC_DELEGATE( P2pnsRegister, p2pnsRegisterRpc );
00342 RPC_DELEGATE( P2pnsResolve, p2pnsResolveRpc );
00343 RPC_SWITCH_END()
00344
00345 return RPC_HANDLED;
00346 }
00347
00348
00349 void P2pns::handleRpcResponse(BaseResponseMessage* msg,
00350 cPolymorphic* context, int rpcId, simtime_t rtt)
00351 {
00352 RPC_SWITCH_START(msg)
00353 RPC_ON_RESPONSE( DHTputCAPI ) {
00354 EV << "[P2pns::handleRpcResponse()]\n"
00355 << " DHTputCAPI RPC Response received: id=" << rpcId
00356 << " msg=" << *_DHTputCAPIResponse << " rtt=" << rtt
00357 << endl;
00358 if (dynamic_cast<P2pnsRegisterCall*>(context)) {
00359 handleDHTputCAPIResponse(_DHTputCAPIResponse,
00360 check_and_cast<P2pnsRegisterCall*>(context));
00361 }
00362 break;
00363 }
00364 RPC_ON_RESPONSE( DHTgetCAPI ) {
00365 EV << "[P2pns::handleRpcResponse()]\n"
00366 << " DHTgetCAPI RPC Response received: id=" << rpcId
00367 << " msg=" << *_DHTgetCAPIResponse << " rtt=" << rtt
00368 << endl;
00369 handleDHTgetCAPIResponse(_DHTgetCAPIResponse,
00370 check_and_cast<P2pnsResolveCall*>(context));
00371 break;
00372 }
00373 RPC_ON_RESPONSE( Lookup ) {
00374 EV << "[P2pns::handleRpcResponse()]\n"
00375 << " Lookup RPC Response received: id=" << rpcId
00376 << " msg=" << *_LookupResponse << " rtt=" << rtt
00377 << endl;
00378 handleLookupResponse(_LookupResponse, context, rpcId);
00379 break;
00380 }
00381 RPC_SWITCH_END()
00382 }
00383
00384 void P2pns::p2pnsRegisterRpc(P2pnsRegisterCall* registerCall)
00385 {
00386 p2pnsCache->addData(registerCall->getP2pName(),
00387 registerCall->getAddress());
00388
00389 DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00390
00391 EV << "[P2pns::p2pnsRegisterRpc()]\n"
00392 << " RegisterRpc: name: " << registerCall->getP2pName()
00393 << " addr: " << registerCall->getAddress()
00394 << endl;
00395
00396 dhtPutMsg->setKey(OverlayKey::sha1(registerCall->getP2pName()));
00397 if (twoStageResolution) {
00398 dhtPutMsg->setValue(overlay->getThisNode().getKey().toString());
00399 } else {
00400 dhtPutMsg->setValue(registerCall->getAddress());
00401 }
00402
00403 dhtPutMsg->setKind(registerCall->getKind());
00404 dhtPutMsg->setId(registerCall->getId());
00405 dhtPutMsg->setTtl(registerCall->getTtl());
00406 dhtPutMsg->setIsModifiable(true);
00407
00408 sendInternalRpcCall(TIER1_COMP, dhtPutMsg, registerCall);
00409 }
00410
00411 void P2pns::p2pnsResolveRpc(P2pnsResolveCall* resolveCall)
00412 {
00413 DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00414
00415 EV << "[P2pns::p2pnsResolveRpc()]\n"
00416 << " ResolveRpc: name: " << resolveCall->getP2pName()
00417 << endl;
00418
00419 dhtGetMsg->setKey(OverlayKey::sha1(resolveCall->getP2pName()));
00420 dhtGetMsg->setKind(resolveCall->getKind());
00421 dhtGetMsg->setId(resolveCall->getId());
00422
00423 sendInternalRpcCall(TIER1_COMP, dhtGetMsg, resolveCall);
00424 }
00425
00426 void P2pns::handleDHTputCAPIResponse(DHTputCAPIResponse* putResponse,
00427 P2pnsRegisterCall* registerCall)
00428 {
00429 P2pnsRegisterResponse* registerResponse = new P2pnsRegisterResponse();
00430 registerResponse->setP2pName(registerCall->getP2pName());
00431 registerResponse->setAddress(registerCall->getAddress());
00432 registerResponse->setIsSuccess(putResponse->getIsSuccess());
00433 sendRpcResponse(registerCall, registerResponse);
00434 }
00435
00436 void P2pns::handleDHTgetCAPIResponse(DHTgetCAPIResponse* getResponse,
00437 P2pnsResolveCall* resolveCall)
00438 {
00439 if ((!getResponse->getIsSuccess())
00440 || (getResponse->getResultArraySize() == 0)) {
00441 P2pnsResolveResponse* resolveResponse = new P2pnsResolveResponse();
00442 resolveResponse->setAddressArraySize(1);
00443 resolveResponse->setKindArraySize(1);
00444 resolveResponse->setIdArraySize(1);
00445 resolveResponse->setP2pName(resolveCall->getP2pName());
00446 resolveResponse->setAddress(0, BinaryValue(""));
00447 resolveResponse->setKind(0, 0);
00448 resolveResponse->setId(0, 0);
00449 resolveResponse->setIsSuccess(false);
00450 sendRpcResponse(resolveCall, resolveResponse);
00451 return;
00452 }
00453
00454
00455
00456
00457
00458 if (twoStageResolution) {
00459 if (getResponse->getResultArraySize() != 1) {
00460 throw cRuntimeError("P2pns::handleDHTgetCAPIResponse: "
00461 "Two-stage name resolution currently only "
00462 "works with unique keys!");
00463 }
00464 std::stringstream valueStream;
00465 valueStream << getResponse->getResult(0).getValue();
00466 OverlayKey key(valueStream.str(), 16);
00467
00468 LookupCall* lookupCall = new LookupCall();
00469
00470 lookupCall->setKey(key);
00471 lookupCall->setNumSiblings(1);
00472
00473 sendInternalRpcCall(OVERLAY_COMP, lookupCall, resolveCall, -1, 0,
00474 RESOLVE_LOOKUP);
00475
00476 return;
00477 }
00478
00479 EV << "[P2pns::handleDHTgetCAPIResponse()]\n"
00480 << " ResolveRpcResponse: name: " << resolveCall->getP2pName();
00481
00482 P2pnsResolveResponse* resolveResponse = new P2pnsResolveResponse();
00483 resolveResponse->setP2pName(resolveCall->getP2pName());
00484 resolveResponse->setIsSuccess(getResponse->getIsSuccess());
00485 resolveResponse->setAddressArraySize(getResponse->getResultArraySize());
00486 resolveResponse->setKindArraySize(getResponse->getResultArraySize());
00487 resolveResponse->setIdArraySize(getResponse->getResultArraySize());
00488
00489 for (uint i = 0; i < getResponse->getResultArraySize(); i++) {
00490 EV << " addr: " << getResponse->getResult(i).getValue();
00491 resolveResponse->setAddress(i, getResponse->getResult(i).getValue());
00492 resolveResponse->setKind(i, getResponse->getResult(i).getKind());
00493 resolveResponse->setId(i, getResponse->getResult(i).getId());
00494 }
00495
00496 EV << endl;
00497 sendRpcResponse(resolveCall, resolveResponse);
00498 }
00499
00500 void P2pns::handleLookupResponse(LookupResponse* lookupResponse,
00501 cObject* context,
00502 int rpcId)
00503 {
00504 switch (rpcId) {
00505 case RESOLVE_LOOKUP: {
00506 P2pnsResolveCall* resolveCall =
00507 check_and_cast<P2pnsResolveCall*>(context);
00508
00509 stringstream sstream;
00510 sstream << lookupResponse->getSiblings(0);
00511
00512 P2pnsResolveResponse* resolveResponse = new P2pnsResolveResponse();
00513 resolveResponse->setP2pName(resolveCall->getP2pName());
00514 resolveResponse->setAddressArraySize(1);
00515 resolveResponse->setKindArraySize(1);
00516 resolveResponse->setIdArraySize(1);
00517
00518 resolveResponse->setAddress(0, sstream.str());
00519 resolveResponse->setKind(0, 0);
00520 resolveResponse->setId(0, 0);
00521 resolveResponse->setIsSuccess(lookupResponse->getIsValid());
00522 sendRpcResponse(resolveCall, resolveResponse);
00523 break;
00524 }
00525 case TUNNEL_LOOKUP:
00526 handleTunnelLookupResponse(lookupResponse);
00527 break;
00528 case REFRESH_LOOKUP:
00529 break;
00530 default:
00531 throw cRuntimeError("P2pns::handleLookupResponse(): invalid rpcId!");
00532 }
00533 }
00534
00535
00536 void P2pns::finishApp()
00537 {
00538 }
00539