XmlRpcInterface.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2007 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include <platdep/sockets.h>
00025 #if not defined _WIN32
00026 #include <arpa/inet.h>
00027 #endif
00028 
00029 #if not defined _WIN32 && not defined __APPLE__
00030 #include <netinet/ip6.h>
00031 #endif
00032 
00033 #include <NodeVector.h>
00034 #include <P2pns.h>
00035 #include <sstream>
00036 #include "XmlRpcInterface.h"
00037 
00038 using namespace XmlRpc;
00039 
00040 Define_Module(XmlRpcInterface);
00041 
00042 // Register a name with P2PNS
00043 class P2pnsRegister : public XmlRpcServerMethod
00044 {
00045 public:
00046     P2pnsRegister(XmlRpcServer* s) :
00047         XmlRpcServerMethod("register", s)
00048     {
00049     }
00050 
00051     void execute(XmlRpcValue& params, XmlRpcValue& result)
00052     {
00053         (dynamic_cast<XmlRpcInterface*>(_server))->p2pnsRegister(params, result);
00054     }
00055 
00056     std::string help()
00057     {
00058         return std::string("Register a name with P2PNS");
00059     }
00060 };
00061 
00062 // Register a name with P2PNS
00063 class P2pnsResolve : public XmlRpcServerMethod
00064 {
00065 public:
00066     P2pnsResolve(XmlRpcServer* s) :
00067         XmlRpcServerMethod("resolve", s)
00068     {
00069     }
00070 
00071     void execute(XmlRpcValue& params, XmlRpcValue& result)
00072     {
00073         (dynamic_cast<XmlRpcInterface*>(_server))->p2pnsResolve(params, result);
00074     }
00075 
00076     std::string help()
00077     {
00078         return std::string("Resolve a name with P2PNS");
00079     }
00080 };
00081 
00082 // Common API: local_lookup()
00083 class LocalLookup : public XmlRpcServerMethod
00084 {
00085 public:
00086     LocalLookup(XmlRpcServer* s) :
00087         XmlRpcServerMethod("local_lookup", s)
00088     {
00089     }
00090 
00091     void execute(XmlRpcValue& params, XmlRpcValue& result)
00092     {
00093         (dynamic_cast<XmlRpcInterface*>(_server))->localLookup(params, result);
00094     }
00095 
00096     std::string help()
00097     {
00098         return std::string("Lookup key in local "
00099             "routing table");
00100     }
00101 };
00102 
00103 // Common API: lookup()
00104 class Lookup : public XmlRpcServerMethod
00105 {
00106 public:
00107     Lookup(XmlRpcServer* s) :
00108         XmlRpcServerMethod("lookup", s)
00109     {
00110     }
00111 
00112     void execute(XmlRpcValue& params, XmlRpcValue& result)
00113     {
00114         (dynamic_cast<XmlRpcInterface*>(_server))->lookup(params, result);
00115     }
00116 
00117     std::string help()
00118     {
00119         return std::string("Lookup key with KBR layer");
00120     }
00121 };
00122 
00123 // Store a value in the DHT
00124 class Put : public XmlRpcServerMethod
00125 {
00126 public:
00127     Put(XmlRpcServer* s) :
00128         XmlRpcServerMethod("put", s)
00129     {
00130     }
00131 
00132     void execute(XmlRpcValue& params, XmlRpcValue& result)
00133     {
00134         (dynamic_cast<XmlRpcInterface*>(_server))->put(params, result);
00135     }
00136 
00137     std::string help()
00138     {
00139         return std::string("Store a value in the DHT");
00140     }
00141 };
00142 
00143 // Get a value from the DHT
00144 class Get : public XmlRpcServerMethod
00145 {
00146 public:
00147     Get(XmlRpcServer* s) :
00148         XmlRpcServerMethod("get", s)
00149     {
00150     }
00151 
00152     void execute(XmlRpcValue& params, XmlRpcValue& result)
00153     {
00154         (dynamic_cast<XmlRpcInterface*>(_server))->get(params, result);
00155     }
00156 
00157     std::string help()
00158     {
00159         return std::string("Get a value from the DHT");
00160     }
00161 };
00162 
00163 // Dump all local records from the DHT
00164 class DumpDht : public XmlRpcServerMethod
00165 {
00166 public:
00167     DumpDht(XmlRpcServer* s) :
00168         XmlRpcServerMethod("dump_dht", s)
00169     {
00170     }
00171 
00172     void execute(XmlRpcValue& params, XmlRpcValue& result)
00173     {
00174         (dynamic_cast<XmlRpcInterface*>(_server))->dumpDht(params, result);
00175     }
00176 
00177     std::string help()
00178     {
00179         return std::string("Dump all local records from the DHT");
00180     }
00181 };
00182 
00183 // Join the overlay with a specific nodeID
00184 class JoinOverlay : public XmlRpcServerMethod
00185 {
00186 public:
00187     JoinOverlay(XmlRpcServer* s) :
00188         XmlRpcServerMethod("join", s)
00189     {
00190     }
00191 
00192     void execute(XmlRpcValue& params, XmlRpcValue& result)
00193     {
00194         (dynamic_cast<XmlRpcInterface*>(_server))->joinOverlay(params, result);
00195     }
00196 
00197     std::string help()
00198     {
00199         return std::string("Join the overlay with a specific nodeID");
00200     }
00201 };
00202 
00203 void XmlRpcInterface::p2pnsRegister(XmlRpcValue& params, XmlRpcValue& result)
00204 {
00205     if ((params.size() != 5) ||
00206             (params[0].getType() != XmlRpcValue::TypeBase64) ||
00207             (params[1].getType() != XmlRpcValue::TypeInt) ||
00208             (params[2].getType() != XmlRpcValue::TypeInt) ||
00209             (params[3].getType() != XmlRpcValue::TypeBase64) ||
00210             (params[4].getType() != XmlRpcValue::TypeInt))
00211         throw XmlRpcException("register(base64 name, int kind, int id, base64 address, int ttl): "
00212                               "Invalid argument type");
00213 
00214     if (overlay->getCompModule(TIER2_COMP) == NULL)
00215         throw XmlRpcException("register(base64 name, int kind, int id, base64 address, int ttl): "
00216                               "No P2PNS service");
00217 
00218     if (!isPrivileged()) {
00219         throw XmlRpcException("register(base64 name, int kind, base64 address, "
00220                               "int ttl): Not allowed");
00221     }
00222 
00223     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00224 
00225     P2pnsRegisterCall* registerCall = new P2pnsRegisterCall();
00226     registerCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
00227     registerCall->setKind((int)params[1]);
00228     registerCall->setId((int)params[2]);
00229     registerCall->setAddress(((const XmlRpcValue::BinaryData&)params[3]));
00230     registerCall->setTtl(params[4]);
00231 
00232     sendInternalRpcWithTimeout(TIER2_COMP, registerCall);
00233 }
00234 
00235 void XmlRpcInterface::p2pnsResolve(XmlRpcValue& params, XmlRpcValue& result)
00236 {
00237     if ((params.size() != 2) ||
00238             (params[0].getType() != XmlRpcValue::TypeBase64) ||
00239             (params[1].getType() != XmlRpcValue::TypeInt))
00240         throw XmlRpcException("resolve(base64 name, int kind): Invalid argument type");
00241 
00242     if (overlay->getCompModule(TIER2_COMP) == NULL)
00243         throw XmlRpcException("resolve(base64 name, int kind): No P2PNS service");
00244 
00245     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00246 
00247     P2pnsResolveCall* resolveCall = new P2pnsResolveCall();
00248 
00249     resolveCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
00250     resolveCall->setKind((int)params[1]);
00251     resolveCall->setId(0);
00252 
00253     sendInternalRpcWithTimeout(TIER2_COMP, resolveCall);
00254 }
00255 
00256 void XmlRpcInterface::localLookup(XmlRpcValue& params, XmlRpcValue& result)
00257 {
00258     if ((params.size() != 3)
00259             || (params[0].getType() != XmlRpcValue::TypeBase64)
00260             || (params[1].getType() != XmlRpcValue::TypeInt)
00261             || (params[2].getType() != XmlRpcValue::TypeBoolean))
00262         throw XmlRpcException("local_lookup(base64 key, int num, "
00263                 "boolean safe): Invalid argument type");
00264 
00265     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00266 
00267     NodeVector* nextHops = NULL;
00268 
00269     if (keyString.size() > 0) {
00270         nextHops = overlay->local_lookup(OverlayKey::sha1(keyString),
00271                                                      params[1], params[2]);
00272     } else {
00273         nextHops = overlay->local_lookup(overlay->getThisNode().getKey(),
00274                                                      params[1], params[2]);
00275     }
00276 
00277     for (uint32_t i=0; i < nextHops->size(); i++) {
00278         result[i][0] = (*nextHops)[i].getAddress().str();
00279         result[i][1] = (*nextHops)[i].getPort();
00280         result[i][2] = (*nextHops)[i].getKey().toString(16);
00281     }
00282 
00283     delete nextHops;
00284 }
00285 
00286 void XmlRpcInterface::lookup(XmlRpcValue& params, XmlRpcValue& result)
00287 {
00288     if (((params.size() != 2)
00289             || (params[0].getType() != XmlRpcValue::TypeBase64)
00290             || (params[1].getType() != XmlRpcValue::TypeInt))
00291         && ((params.size() != 3)
00292             || (params[0].getType() != XmlRpcValue::TypeBase64)
00293             || (params[1].getType() != XmlRpcValue::TypeInt)
00294             || (params[2].getType() != XmlRpcValue::TypeInt)))
00295         throw XmlRpcException("lookup(base64 key, int numSiblings(, "
00296                               "int RoutingType)): Invalid argument type");
00297 
00298     if ((int)params[1] > overlay->getMaxNumSiblings())
00299         throw XmlRpcException("lookup(base64 key, int numSiblings(, "
00300                               "int RoutingType)): numSibling to big");
00301 
00302     if (params.size() == 3) {
00303         if (((int)params[2] != DEFAULT_ROUTING) &&
00304             ((int)params[2] != ITERATIVE_ROUTING) &&
00305             ((int)params[2] != EXHAUSTIVE_ITERATIVE_ROUTING) &&
00306             ((int)params[2] != SEMI_RECURSIVE_ROUTING) &&
00307             ((int)params[2] != FULL_RECURSIVE_ROUTING) &&
00308             ((int)params[2] != RECURSIVE_SOURCE_ROUTING)) {
00309 
00310             throw XmlRpcException("lookup(base64 key, int numSiblings(, "
00311                                   "int RoutingType)): invalid routingType");
00312         }
00313     }
00314 
00315     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00316 
00317     LookupCall* lookupCall = new LookupCall();
00318 
00319     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00320     lookupCall->setKey(OverlayKey::sha1(keyString));
00321     lookupCall->setNumSiblings(params[1]);
00322 
00323     if (params.size() == 3) {
00324         lookupCall->setRoutingType(params[2]);
00325     }
00326 
00327     sendInternalRpcWithTimeout(OVERLAY_COMP, lookupCall);
00328 }
00329 
00330 void XmlRpcInterface::joinOverlay(XmlRpcValue& params, XmlRpcValue& result)
00331 {
00332     if ((params.size() != 1)
00333             || (params[0].getType() != XmlRpcValue::TypeBase64))
00334         throw XmlRpcException("join(base64 nodeID): Invalid argument type");
00335 
00336     if (!isPrivileged()) {
00337         throw XmlRpcException("join(base64 nodeID): Not allowed");
00338     }
00339 
00340     BinaryValue nodeID = (const XmlRpcValue::BinaryData&)params[0];
00341 
00342     overlay->join(OverlayKey::sha1(nodeID));
00343 
00344     result[0] = 0;
00345 }
00346 
00347 void XmlRpcInterface::put(XmlRpcValue& params, XmlRpcValue& result)
00348 {
00349     if ((params.size() != 4)
00350             || (params[0].getType() != XmlRpcValue::TypeBase64)
00351             || (params[1].getType() != XmlRpcValue::TypeBase64)
00352             || (params[2].getType() != XmlRpcValue::TypeInt)
00353             || (params[3].getType() != XmlRpcValue::TypeString))
00354         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00355                 ", string application): Invalid argument type");
00356 
00357     if (!isPrivileged()) {
00358         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00359                 ", string application): Not allowed");
00360     }
00361 
00362     if (overlay->getCompModule(TIER1_COMP) == NULL)
00363         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00364                 ", string application): No DHT service");
00365 
00366     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00367 
00368     DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00369 
00370     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00371 
00372     dhtPutMsg->setKey(OverlayKey::sha1(keyString));
00373     dhtPutMsg->setValue(((const XmlRpcValue::BinaryData&)params[1]));
00374     dhtPutMsg->setTtl(params[2]);
00375     dhtPutMsg->setIsModifiable(true);
00376 
00377     sendInternalRpcWithTimeout(TIER1_COMP, dhtPutMsg);
00378 }
00379 
00380 void XmlRpcInterface::get(XmlRpcValue& params, XmlRpcValue& result)
00381 {
00382     if ((params.size() != 4)
00383             || (params[0].getType() != XmlRpcValue::TypeBase64)
00384             || (params[1].getType() != XmlRpcValue::TypeInt)
00385             || (params[2].getType() != XmlRpcValue::TypeBase64)
00386             || (params[3].getType() != XmlRpcValue::TypeString))
00387         throw XmlRpcException("get(base64 key, int num, base64 placemark "
00388                 ", string application): Invalid argument type");
00389 
00390     if (overlay->getCompModule(TIER1_COMP) == NULL)
00391         throw XmlRpcException("get(base64 key, int num, base64 placemark "
00392                 ", string application): No DHT service");
00393 
00394     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00395 
00396     DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00397 
00398     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00399     dhtGetMsg->setKey(OverlayKey::sha1(keyString));
00400 
00401     sendInternalRpcWithTimeout(TIER1_COMP, dhtGetMsg);
00402 }
00403 
00404 void XmlRpcInterface::dumpDht(XmlRpcValue& params, XmlRpcValue& result)
00405 {
00406     if (params.size() != 1) {
00407         throw XmlRpcException("dump_dht(int dummy): Invalid argument type");
00408     }
00409 
00410     if (!isPrivileged()) {
00411          throw XmlRpcException("dump_dht(int dummy): Not allowed");
00412      }
00413 
00414     if (overlay->getCompModule(TIER1_COMP) == NULL)
00415         throw XmlRpcException("dump_dht(): No DHT service");
00416 
00417     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00418 
00419     DHTdumpCall* call = new DHTdumpCall();
00420 
00421     sendInternalRpcWithTimeout(TIER1_COMP, call);
00422 }
00423 
00424 bool XmlRpcInterface::isPrivileged()
00425 {
00426     if (limitAccess) {
00427         return state[curAppFd].localhost;
00428     } else {
00429         return true;
00430     }
00431 }
00432 
00433 void XmlRpcInterface::initializeApp(int stage)
00434 {
00435     // all initialization is done in the first stage
00436     if (stage != MAX_STAGE_APP)
00437         return;
00438 
00439     packetNotification = new cMessage("packetNotification");
00440     mtu = par("mtu");
00441     limitAccess = par("limitAccess");
00442 
00443     scheduler = check_and_cast<RealtimeScheduler *>(simulation.getScheduler());
00444     scheduler->setInterfaceModule(this, packetNotification, &packetBuffer, mtu,
00445                                   true);
00446 
00447     appTunFd = scheduler->getAppTunFd();
00448 
00449     p2pns = dynamic_cast<P2pns*>(overlay->getCompModule(TIER2_COMP));
00450 
00451     XmlRpc::setVerbosity(1);
00452 
00453     _localLookup = new LocalLookup(this);
00454     _lookup = new Lookup(this);
00455     _register = new P2pnsRegister(this);
00456     _resolve = new P2pnsResolve(this);
00457     _put = new Put(this);
00458     _get = new Get(this);
00459     _dumpDht = new DumpDht(this);
00460     _joinOverlay = new JoinOverlay(this);
00461 
00462     enableIntrospection(true);
00463 
00464     curAppFd = INVALID_SOCKET;
00465 }
00466 
00467 XmlRpcInterface::XmlRpcInterface()
00468 {
00469     p2pns = NULL;
00470 
00471     _localLookup = NULL;
00472     _lookup = NULL;
00473     _register = NULL;
00474     _resolve = NULL;
00475     _put = NULL;
00476     _get = NULL;
00477     _dumpDht = NULL;
00478     _joinOverlay = NULL;
00479 
00480     packetNotification = NULL;
00481 }
00482 
00483 XmlRpcInterface::~XmlRpcInterface()
00484 {
00485     delete _localLookup;
00486     delete _lookup;
00487     delete _register;
00488     delete _resolve;
00489     delete _put;
00490     delete _get;
00491     delete _dumpDht;
00492     delete _joinOverlay;
00493 
00494     cancelAndDelete(packetNotification);
00495 }
00496 
00497 void XmlRpcInterface::resetConnectionState()
00498 {
00499     if (state.count(curAppFd) && state[curAppFd].pendingRpc) {
00500         cancelRpcMessage(state[curAppFd].pendingRpc);
00501     }
00502 
00503     state[curAppFd].appFd = INVALID_SOCKET;
00504     state[curAppFd].localhost = false;
00505     state[curAppFd]._header = "";
00506     state[curAppFd]._request = "";
00507     state[curAppFd]._response = "";
00508     state[curAppFd]._connectionState = READ_HEADER;
00509     state[curAppFd]._keepAlive = true;
00510     state[curAppFd].pendingRpc = 0;
00511 }
00512 
00513 void XmlRpcInterface::closeConnection()
00514 {
00515     scheduler->closeAppSocket(curAppFd);
00516     resetConnectionState();
00517 }
00518 
00519 void XmlRpcInterface::sendInternalRpcWithTimeout(CompType destComp,
00520                                                  BaseCallMessage *call)
00521 {
00522     state[curAppFd].pendingRpc = sendInternalRpcCall(destComp, call, NULL,
00523                                                      XMLRPC_TIMEOUT, 0,
00524                                                      curAppFd);
00525 }
00526 
00527 void XmlRpcInterface::handleMessage(cMessage *msg)
00528 {
00529     // Packet from the application...
00530     if (msg==packetNotification) {
00531         EV << "[XmlRpcInterface::handleMessage() @ " << overlay->getThisNode().getAddress()
00532         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00533         << "    Message from application. Queue length = " << packetBuffer.size()
00534         << endl;
00535         while (packetBuffer.size() > 0) {
00536             // get packet from buffer and parse it
00537             RealtimeScheduler::PacketBufferEntry packet =
00538                     *(packetBuffer.begin());
00539             packetBuffer.pop_front();
00540             curAppFd = packet.fd;
00541 
00542             switch (packet.func) {
00543             case RealtimeScheduler::PacketBufferEntry::PACKET_APPTUN_DATA:
00544                 handleAppTunPacket(packet.data, packet.length);
00545                 break;
00546 
00547             case RealtimeScheduler::PacketBufferEntry::PACKET_DATA:
00548                 if (state.count(curAppFd) == 0) {
00549                     throw cRuntimeError("XmlRpcInterface::handleMessage(): "
00550                                             "Received packet "
00551                                             "from unknown socket!");
00552                 }
00553 
00554                 handleRealworldPacket(packet.data, packet.length);
00555                 break;
00556 
00557             case RealtimeScheduler::PacketBufferEntry::PACKET_FD_NEW:
00558                 if (state.count(curAppFd)) {
00559                     throw cRuntimeError("XmlRpcInterface::handleMessage(): "
00560                                             "Connection state table corrupt!");
00561                 }
00562 
00563                 resetConnectionState();
00564 
00565                 if (packet.addr != NULL) {
00566                     if (((sockaddr_in*)packet.addr)->sin_addr.s_addr
00567                             == inet_addr("127.0.0.1")) {
00568                         state[curAppFd].localhost = true;
00569                     }
00570                     delete packet.addr;
00571                     packet.addr = NULL;
00572                 }
00573                 break;
00574 
00575             case RealtimeScheduler::PacketBufferEntry::PACKET_FD_CLOSE:
00576                 if (state.count(curAppFd) == 0) {
00577                     throw cRuntimeError("XmlRpcInterface::handleMessage(): "
00578                                             "Trying to close unknown "
00579                                             "connection!");
00580                 }
00581 
00582                 resetConnectionState();
00583                 state.erase(curAppFd);
00584             }
00585 
00586             if (packet.data) {
00587                 delete[] packet.data;
00588             }
00589         }
00590     } else if (msg->isSelfMessage()) {
00591         // process rpc self-messages
00592         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00593         if (rpcMessage!=NULL) {
00594             internalHandleRpcMessage(rpcMessage);
00595             return;
00596         }
00597 
00598         delete msg;
00599     } else {
00600         // RPCs
00601         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00602         if (rpcMessage!=NULL) {
00603             internalHandleRpcMessage(rpcMessage);
00604             return;
00605         }
00606         // common API
00607         CommonAPIMessage* commonAPIMsg = dynamic_cast<CommonAPIMessage*>(msg);
00608         if (commonAPIMsg != NULL)
00609             handleCommonAPIPacket(commonAPIMsg);
00610 
00611         CompReadyMessage* readyMsg = dynamic_cast<CompReadyMessage*>(msg);
00612         if (readyMsg != NULL)
00613             handleReadyMessage(readyMsg);
00614 
00615         delete msg;
00616     }
00617 }
00618 
00619 void XmlRpcInterface::handleRpcTimeout(BaseCallMessage* msg,
00620                                        const TransportAddress& dest,
00621                                        cPolymorphic* context, int rpcId,
00622                                        const OverlayKey&)
00623 {
00624     curAppFd = rpcId;
00625 
00626     if (state.count(curAppFd) == 0)
00627         return;
00628 
00629     std::cout << "XmlRpcInterface(): XML-RPC failed!" << endl;
00630     state[curAppFd]._response = generateFaultResponse("XML-RPC timeout", 22);
00631     state[curAppFd]._connectionState = WRITE_RESPONSE;
00632     if (!writeResponse() ) {
00633         closeConnection();
00634     }
00635 }
00636 
00637 void XmlRpcInterface::handleReadyMessage(CompReadyMessage* msg)
00638 {
00639     if ((msg->getReady() == false) || (msg->getComp() != OVERLAY_COMP)) {
00640         return;
00641     }
00642 
00643     if (appTunFd != INVALID_SOCKET) {
00644         // set TUN interface address using the current NodeId
00645         // TODO: this is ugly
00646         const OverlayKey& key = overlay->getThisNode().getKey();
00647 
00648         if (OverlayKey::getLength() < 100) {
00649             throw cRuntimeError("XmlRpcInterface::handleReadyMessage(): "
00650                     "P2PNS needs at least 100 bit nodeIds!");
00651         }
00652 
00653         std::stringstream addr;
00654         addr << "2001:001";
00655         for (int i = 0; i < 100/4; i++) {
00656             if (((i + 3) % 4) == 0) {
00657                 addr << ":";
00658             }
00659             addr << std::hex << key.getBitRange(OverlayKey::getLength() -
00660                                                 4 * (i + 1), 4);
00661         }
00662 
00663         std::string cmd = "/sbin/ip addr add " + addr.str() + "/28 dev tun0";
00664 
00665         EV << "XmlRpcInterface::handleOverlayReady(): "
00666               "Setting TUN interface address " << addr.str() << endl;
00667 
00668         if (system(cmd.c_str()) != 0) {
00669             EV << "XmlRpcInterface::handleOverlayReady(): "
00670                   "Failed to set TUN interface address!" << endl;
00671         }
00672 
00673         if (system("/sbin/ip link set tun0 up") != 0) {
00674             EV << "XmlRpcInterface::handleOverlayReady(): "
00675                   "Failed to set TUN interface up!" << endl;
00676         }
00677 
00678         p2pns->registerId(addr.str());
00679     }
00680 }
00681 
00682 void XmlRpcInterface::handleAppTunPacket(char *buf, uint32_t length)
00683 {
00684 #if not defined _WIN32 && not defined __APPLE__
00685     EV << "XmlRpcInterface::handleAppTunPacket(): packet of "
00686        << "length " << length << endl;
00687 
00688     if (!p2pns) {
00689         throw cRuntimeError("XmlRpcInterface::handleAppTunPacket(): "
00690                 "P2PNS module missing on tier2!");
00691     }
00692 
00693     if (OverlayKey::getLength() < 100) {
00694         throw cRuntimeError("XmlRpcInterface::handleAppTunPacket(): "
00695                 "P2PNS needs at least 100 bit nodeIds!");
00696     }
00697 
00698     if (length < 40) {
00699         EV << "XmlRpcInterface::handleAppTunPacket(): packet too "
00700            << "short - discarding packet!" << endl;
00701         return;
00702     }
00703 
00704     ip6_hdr* ip_buf = (ip6_hdr*) buf;
00705     if (((ip_buf->ip6_vfc & 0xf0) >> 4) != 6) {
00706         EV << "XmlRpcInterface::handleAppTunPacket(): received packet "
00707               "is no IPv6 - discarding packet!" << endl;
00708         return;
00709     }
00710 
00711     OverlayKey destKey = OverlayKey(ntohl(ip_buf->ip6_dst.s6_addr32[0]));
00712 
00713     for (int i = 1; i < 4; i++) {
00714         destKey = (destKey << 32) + OverlayKey(ntohl(ip_buf->ip6_dst.s6_addr32[i]));
00715     }
00716     destKey = destKey << (OverlayKey::getLength() - 100);
00717 
00718     p2pns->tunnel(destKey, BinaryValue(buf, buf + length));
00719 #endif
00720 }
00721 
00722 void XmlRpcInterface::deliverTunneledMessage(const BinaryValue& payload)
00723 {
00724 #if not defined _WIN32 && not defined __APPLE__
00725     Enter_Method_Silent();
00726 
00727     if (payload.size() == 0) {
00728         return;
00729     }
00730 
00731     int curBytesWritten = scheduler->sendBytes(&payload[0],
00732                                                payload.size(),
00733                                                0, 0, true, appTunFd);
00734 
00735     if (curBytesWritten <= 0) {
00736         throw cRuntimeError("XmlRpcServerConnection::deliverTunneledMessage(): "
00737                             "Error writing to application TUN device.");
00738     }
00739 #endif
00740 }
00741 
00742 void XmlRpcInterface::handleRealworldPacket(char *buf, uint32_t length)
00743 {
00744     if (state[curAppFd]._connectionState == READ_HEADER) {
00745         if (!readHeader(buf, length)) {
00746             // discard data, if the header is invalid
00747             state[curAppFd]._header = "";
00748             state[curAppFd]._request = "";
00749             state[curAppFd]._response = "";
00750             state[curAppFd]._connectionState = READ_HEADER;
00751             return;
00752         }
00753     }
00754 
00755     if (state[curAppFd]._connectionState == READ_REQUEST)
00756         if (!readRequest(buf, length))
00757             return;
00758 
00759     if (state[curAppFd]._connectionState == WRITE_RESPONSE)
00760         if (!writeResponse() ) {
00761             closeConnection();
00762             return;
00763         }
00764 
00765     return;
00766 }
00767 
00768 void XmlRpcInterface::handleRpcResponse(BaseResponseMessage* msg,
00769                                         cPolymorphic* context,
00770                                         int rpcId,
00771                                         simtime_t rtt)
00772 {
00773     curAppFd = rpcId;
00774 
00775     if (state.count(curAppFd) == 0) {
00776         return;
00777     }
00778 
00779     RPC_SWITCH_START(msg)
00780     RPC_ON_RESPONSE(Lookup) {
00781         if (state[curAppFd]._connectionState != EXECUTE_REQUEST) break;
00782 
00783         XmlRpcValue resultValue;
00784         resultValue.setSize(_LookupResponse->getSiblingsArraySize());
00785 
00786         if (_LookupResponse->getIsValid() == true) {
00787             for (uint32_t i=0; i < _LookupResponse->getSiblingsArraySize();
00788                     i++) {
00789                 resultValue[i].setSize(3);
00790                 resultValue[i][0] =
00791                     _LookupResponse->getSiblings(i).getAddress().str();
00792                 resultValue[i][1] =
00793                     _LookupResponse->getSiblings(i).getPort();
00794                 resultValue[i][2] =
00795                     _LookupResponse->getSiblings(i).getKey().toString(16);
00796             }
00797             state[curAppFd]._response = generateResponse(resultValue.toXml());
00798         } else {
00799             std::cout << "XmlRpcInterface(): lookup() failed!" << endl;
00800             state[curAppFd]._response = generateFaultResponse("lookup() failed", 22);
00801         }
00802 
00803         state[curAppFd]._connectionState = WRITE_RESPONSE;
00804         if (!writeResponse()) {
00805             closeConnection();
00806         }
00807         break;
00808     }
00809     RPC_ON_RESPONSE(P2pnsRegister) {
00810         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00811             break;
00812 
00813         XmlRpcValue resultValue;
00814 
00815         if (_P2pnsRegisterResponse->getIsSuccess() == true) {
00816             resultValue = 0;
00817             state[curAppFd]._response = generateResponse(resultValue.toXml());
00818         } else {
00819             std::cout << "XmlRpcInterface(): register() failed!" << endl;
00820             state[curAppFd]._response = generateFaultResponse("register() failed", 22);
00821         }
00822 
00823         state[curAppFd]._connectionState = WRITE_RESPONSE;
00824         if (!writeResponse() ) {
00825             closeConnection();
00826         }
00827         break;
00828     }
00829     RPC_ON_RESPONSE(P2pnsResolve) {
00830         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00831             break;
00832 
00833         XmlRpcValue resultValue;
00834         resultValue.setSize(_P2pnsResolveResponse->getAddressArraySize());
00835 
00836         if (_P2pnsResolveResponse->getIsSuccess() == true) {
00837             for (uint i=0; i < _P2pnsResolveResponse->getAddressArraySize(); i++) {
00838                 resultValue[i].setSize(3);
00839                 BinaryValue& addr = _P2pnsResolveResponse->getAddress(i);
00840                 resultValue[i][0] = XmlRpcValue(&addr[0], addr.size());
00841                 resultValue[i][1] = (int)_P2pnsResolveResponse->getKind(i);
00842                 resultValue[i][2] = (int)_P2pnsResolveResponse->getId(i);
00843             }
00844             state[curAppFd]._response = generateResponse(resultValue.toXml());
00845         } else {
00846             std::cout << "XmlRpcInterface(): resolve() failed!" << endl;
00847             state[curAppFd]._response = generateFaultResponse("resolve() failed: Name not found", 9);
00848         }
00849 
00850         state[curAppFd]._connectionState = WRITE_RESPONSE;
00851         if (!writeResponse() ) {
00852             closeConnection();
00853         }
00854         break;
00855     }
00856     RPC_ON_RESPONSE(DHTputCAPI) {
00857         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00858             break;
00859 
00860         XmlRpcValue resultValue;
00861 
00862         if (_DHTputCAPIResponse->getIsSuccess() == true) {
00863             resultValue = 0;
00864             state[curAppFd]._response = generateResponse(resultValue.toXml());
00865         } else {
00866             std::cout << "XmlRpcInterface(): put() failed!" << endl;
00867             state[curAppFd]._response = generateFaultResponse("put() failed", 22);
00868         }
00869 
00870         state[curAppFd]._connectionState = WRITE_RESPONSE;
00871         if (!writeResponse() ) {
00872             closeConnection();
00873         }
00874         break;
00875     }
00876     RPC_ON_RESPONSE(DHTgetCAPI) {
00877         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00878             break;
00879 
00880         XmlRpcValue resultValue;
00881         resultValue.setSize(2);
00882         resultValue[0].setSize(_DHTgetCAPIResponse->getResultArraySize());
00883 
00884         if (_DHTgetCAPIResponse->getIsSuccess() == true) {
00885             for (uint i=0; i < _DHTgetCAPIResponse->getResultArraySize(); i++) {
00886                 resultValue[i].setSize(2);
00887                 DhtDumpEntry& entry = _DHTgetCAPIResponse->getResult(i);
00888                 resultValue[0][i] = XmlRpcValue(&(*(entry.getValue().begin())),
00889                                                 entry.getValue().size());
00890             }
00891             resultValue[1] = std::string();
00892 
00893 //            resultValue[0][0] = XmlRpcValue(
00894 //                      &(*(_DHTgetCAPIResponse->getValue().begin())),
00895 //                      _DHTgetCAPIResponse->getValue().size());
00896             state[curAppFd]._response = generateResponse(resultValue.toXml());
00897         } else {
00898             std::cout << "XmlRpcInterface(): get() failed!" << endl;
00899             state[curAppFd]._response = generateFaultResponse("get() failed", 22);
00900         }
00901 
00902         state[curAppFd]._connectionState = WRITE_RESPONSE;
00903         if (!writeResponse() ) {
00904             closeConnection();
00905         }
00906         break;
00907     }
00908     RPC_ON_RESPONSE(DHTdump) {
00909         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00910             break;
00911 
00912         XmlRpcValue resultValue;
00913         resultValue.setSize(_DHTdumpResponse->getRecordArraySize());
00914 
00915         for (uint32_t i=0; i < _DHTdumpResponse->getRecordArraySize();
00916              i++) {
00917             resultValue[i].setSize(3);
00918             resultValue[i][0] =
00919                 _DHTdumpResponse->getRecord(i).getKey().toString(16);
00920             resultValue[i][1] = XmlRpcValue(
00921                  &(*(_DHTdumpResponse->getRecord(i).getValue().begin())),
00922                  _DHTdumpResponse->getRecord(i).getValue().size());
00923             resultValue[i][2] =
00924                 _DHTdumpResponse->getRecord(i).getTtl();
00925         }
00926 
00927         state[curAppFd]._response = generateResponse(resultValue.toXml());
00928 
00929         state[curAppFd]._connectionState = WRITE_RESPONSE;
00930          if (!writeResponse()) {
00931              closeConnection();
00932          }
00933          break;
00934 
00935     }
00936     RPC_SWITCH_END( )
00937 }
00938 
00939 void XmlRpcInterface::handleCommonAPIPacket(cMessage *msg)
00940 {
00941     error("DHTXMLRealworldApp::handleCommonAPIPacket(): Unknown Packet!");
00942 }
00943 
00944 bool XmlRpcInterface::readHeader(char* buf, uint32_t length)
00945 {
00946     // Read available data
00947     bool eof = false;
00948 
00949     state[curAppFd]._header.append(std::string(buf, length));
00950 
00951     if (length <= 0) {
00952         // Its only an error if we already have read some data
00953         if (state[curAppFd]._header.length() > 0)
00954             XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error "
00955                 "while reading header.");
00956         return false;
00957     }
00958 
00959     XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.",
00960                     state[curAppFd]._header.length());
00961     char *hp = (char*)state[curAppFd]._header.c_str(); // Start of header
00962     char *ep = hp + state[curAppFd]._header.length(); // End of string
00963     char *bp = 0; // Start of body
00964     char *lp = 0; // Start of content-length value
00965     char *kp = 0; // Start of connection value
00966 
00967     for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
00968         if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
00969             lp = cp + 16;
00970         else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
00971             kp = cp + 12;
00972         else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
00973             bp = cp + 4;
00974         else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
00975             bp = cp + 2;
00976     }
00977 
00978     // If we haven't gotten the entire header yet, return (keep reading)
00979     if (bp == 0) {
00980         // EOF in the middle of a request is an error, otherwise its ok
00981         if (eof) {
00982             XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
00983             if (state[curAppFd]._header.length() > 0)
00984                 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
00985             return false; // Either way we close the connection
00986         }
00987 
00988         return true; // Keep reading
00989     }
00990 
00991     // Decode content length
00992     if (lp == 0) {
00993         XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
00994         return false; // We could try to figure it out by parsing as we read, but for now...
00995     }
00996 
00997     state[curAppFd]._contentLength = atoi(lp);
00998     if (state[curAppFd]._contentLength <= 0) {
00999         XmlRpcUtil::error(
01000                           "XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).",
01001                           state[curAppFd]._contentLength);
01002         return false;
01003     }
01004 
01005     XmlRpcUtil::log(
01006                      3,
01007                     "XmlRpcServerConnection::readHeader: specified content length is %d.",
01008                     state[curAppFd]._contentLength);
01009 
01010     // Otherwise copy non-header data to request buffer and set state to read request.
01011     state[curAppFd]._request = bp;
01012 
01013     // Parse out any interesting bits from the header (HTTP version, connection)
01014     state[curAppFd]._keepAlive = true;
01015     if (state[curAppFd]._header.find("HTTP/1.0") != std::string::npos) {
01016         if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
01017             state[curAppFd]._keepAlive = false; // Default for HTTP 1.0 is to close the connection
01018     } else {
01019         if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
01020             state[curAppFd]._keepAlive = false;
01021     }
01022     XmlRpcUtil::log(3, "KeepAlive: %d", state[curAppFd]._keepAlive);
01023 
01024     state[curAppFd]._header = "";
01025     state[curAppFd]._connectionState = READ_REQUEST;
01026     return true; // Continue monitoring this source
01027 }
01028 
01029 bool XmlRpcInterface::readRequest(char *buf, uint32_t length)
01030 {
01031     // If we dont have the entire request yet, read available data
01032     if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
01033         bool eof = false;
01034 
01035         state[curAppFd]._request.append(std::string(buf, length));
01036 
01037         if (length <= 0) {
01038             XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error.");
01039             return false;
01040         }
01041 
01042         // If we haven't gotten the entire request yet, return (keep reading)
01043         if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
01044             if (eof) {
01045                 XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
01046                 return false; // Either way we close the connection
01047             }
01048             return true;
01049         }
01050     }
01051 
01052     // Otherwise, parse and dispatch the request
01053     XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.",
01054                     state[curAppFd]._request.length());
01055     //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", state[curAppFd]._request.c_str());
01056 
01057     state[curAppFd]._connectionState = WRITE_RESPONSE;
01058 
01059     return true; // Continue monitoring this source
01060 }
01061 
01062 bool XmlRpcInterface::writeResponse()
01063 {
01064     if (state[curAppFd]._response.length() == 0) {
01065         state[curAppFd]._response = executeRequest(state[curAppFd]._request);
01066         state[curAppFd]._bytesWritten = 0;
01067 
01068         if (state[curAppFd]._connectionState == EXECUTE_REQUEST)
01069             return true;
01070 
01071         if (state[curAppFd]._response.length() == 0) {
01072             XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
01073             return false;
01074         }
01075     }
01076 
01077     // Try to write the response
01078     int curBytesWritten = scheduler->sendBytes(state[curAppFd]._response.c_str(),
01079                                                state[curAppFd]._response.length(),
01080                                                0, 0, true, curAppFd);
01081 
01082     if (curBytesWritten <= 0) {
01083         XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error.");
01084         return false;
01085     } else {
01086         state[curAppFd]._bytesWritten += curBytesWritten;
01087     }
01088 
01089     XmlRpcUtil::log(3,
01090                 "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.",
01091                 state[curAppFd]._bytesWritten, state[curAppFd]._response.length());
01092 
01093     // Prepare to read the next request
01094     if (state[curAppFd]._bytesWritten == int(state[curAppFd]._response.length())) {
01095         state[curAppFd]._header = "";
01096         state[curAppFd]._request = "";
01097         state[curAppFd]._response = "";
01098         state[curAppFd]._connectionState = READ_HEADER;
01099     }
01100 
01101     return state[curAppFd]._keepAlive; // Continue monitoring this source if true
01102 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3