XmlRpcInterface Class Reference

Applicaton that communicates with a realword application via a socket. More...

#include <XmlRpcInterface.h>

Inheritance diagram for XmlRpcInterface:
BaseApp XmlRpc::XmlRpcServer BaseRpc XmlRpc::XmlRpcSource RpcListener

List of all members.

Classes

struct  XmlRpcConnectionState

Public Member Functions

 XmlRpcInterface ()
 ~XmlRpcInterface ()
virtual void initializeApp (int stage)
 initializes derived class-attributes
virtual void handleMessage (cMessage *msg)
 The "main loop".
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &)
 This method is called if an RPC timeout has been reached.
void deliverTunneledMessage (const BinaryValue &payload)
void localLookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void lookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void p2pnsRegister (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void p2pnsResolve (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void put (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void get (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void dumpDht (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void joinOverlay (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)

Protected Types

enum  ServerConnectionState { READ_HEADER, READ_REQUEST, EXECUTE_REQUEST, WRITE_RESPONSE }
 

Possible IO states for the connection.

More...

Protected Member Functions

bool readHeader (char *buf, uint32_t length)
 Reads the http header.
bool readRequest (char *buf, uint32_t length)
 Reads the request (based on the content-length header value).
bool writeResponse ()
 Executes the request and writes the resulting response.
bool isPrivileged ()
 Check if the connected application is allowed to call privileged methods.
void handleAppTunPacket (char *buf, uint32_t len)
void handleRealworldPacket (char *buf, uint32_t len)
void handleCommonAPIPacket (cMessage *msg)
void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
void resetConnectionState ()
 Reset the internal connection state.
void closeConnection ()
void sendInternalRpcWithTimeout (CompType destComp, BaseCallMessage *call)
virtual void handleReadyMessage (CompReadyMessage *msg)
 method to handle ready messages from the overlay

Protected Attributes

unsigned int mtu
cMessage * packetNotification
RealtimeScheduler::PacketBuffer packetBuffer
RealtimeSchedulerscheduler
std::map< int,
XmlRpcConnectionState
state
SOCKET curAppFd
bool limitAccess
XmlRpc::XmlRpcServerMethod_localLookup
XmlRpc::XmlRpcServerMethod_lookup
XmlRpc::XmlRpcServerMethod_register
XmlRpc::XmlRpcServerMethod_resolve
XmlRpc::XmlRpcServerMethod_put
XmlRpc::XmlRpcServerMethod_get
XmlRpc::XmlRpcServerMethod_dumpDht
XmlRpc::XmlRpcServerMethod_joinOverlay
SOCKET appTunFd
 FD of the application TUN socket used for tunneling.
P2pnsp2pns
 Pointer to the P2PNS module.

Detailed Description

Applicaton that communicates with a realword application via a socket.

Definition at line 44 of file XmlRpcInterface.h.


Member Enumeration Documentation

Possible IO states for the connection.

Enumerator:
READ_HEADER 
READ_REQUEST 
EXECUTE_REQUEST 
WRITE_RESPONSE 

Definition at line 63 of file XmlRpcInterface.h.


Constructor & Destructor Documentation

XmlRpcInterface::XmlRpcInterface (  ) 

Definition at line 467 of file XmlRpcInterface.cc.

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 }

XmlRpcInterface::~XmlRpcInterface (  ) 

Definition at line 483 of file XmlRpcInterface.cc.

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 }


Member Function Documentation

void XmlRpcInterface::closeConnection (  )  [protected]

Definition at line 513 of file XmlRpcInterface.cc.

Referenced by handleRealworldPacket(), handleRpcResponse(), and handleRpcTimeout().

00514 {
00515     scheduler->closeAppSocket(curAppFd);
00516     resetConnectionState();
00517 }

void XmlRpcInterface::deliverTunneledMessage ( const BinaryValue payload  ) 

Definition at line 722 of file XmlRpcInterface.cc.

Referenced by P2pns::deliver().

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 }

void XmlRpcInterface::dumpDht ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 404 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::get ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 380 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::handleAppTunPacket ( char *  buf,
uint32_t  len 
) [protected]

Definition at line 682 of file XmlRpcInterface.cc.

Referenced by handleMessage().

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 }

void XmlRpcInterface::handleCommonAPIPacket ( cMessage *  msg  )  [protected]

Definition at line 939 of file XmlRpcInterface.cc.

Referenced by handleMessage().

00940 {
00941     error("DHTXMLRealworldApp::handleCommonAPIPacket(): Unknown Packet!");
00942 }

void XmlRpcInterface::handleMessage ( cMessage *  msg  )  [virtual]

The "main loop".

Every message that is received or send is handled by this method

Reimplemented from BaseApp.

Definition at line 527 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::handleReadyMessage ( CompReadyMessage *  msg  )  [protected, virtual]

method to handle ready messages from the overlay

Parameters:
msg message to handle

Reimplemented from BaseApp.

Definition at line 637 of file XmlRpcInterface.cc.

Referenced by handleMessage().

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 }

void XmlRpcInterface::handleRealworldPacket ( char *  buf,
uint32_t  len 
) [protected]

Definition at line 742 of file XmlRpcInterface.cc.

Referenced by handleMessage().

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 }

void XmlRpcInterface::handleRpcResponse ( BaseResponseMessage *  msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [protected, virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Definition at line 768 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::handleRpcTimeout ( BaseCallMessage *  msg,
const TransportAddress dest,
cPolymorphic *  context,
int  rpcId,
const OverlayKey destKey 
) [virtual]

This method is called if an RPC timeout has been reached.

Parameters:
msg The original RPC message.
dest The destination node
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
destKey the destination OverlayKey

Reimplemented from RpcListener.

Definition at line 619 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::initializeApp ( int  stage  )  [virtual]

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

Definition at line 433 of file XmlRpcInterface.cc.

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 }

bool XmlRpcInterface::isPrivileged (  )  [protected]

Check if the connected application is allowed to call privileged methods.

Currently this is true for all applications connecting to localhost. If **.limitAccess = false there are no access restrictions.

Returns:
true, if the application is allowed to call privileged methods

Definition at line 424 of file XmlRpcInterface.cc.

Referenced by dumpDht(), joinOverlay(), p2pnsRegister(), and put().

00425 {
00426     if (limitAccess) {
00427         return state[curAppFd].localhost;
00428     } else {
00429         return true;
00430     }
00431 }

void XmlRpcInterface::joinOverlay ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 330 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::localLookup ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 256 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::lookup ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 286 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::p2pnsRegister ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 203 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::p2pnsResolve ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 235 of file XmlRpcInterface.cc.

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 }

void XmlRpcInterface::put ( XmlRpc::XmlRpcValue params,
XmlRpc::XmlRpcValue result 
)

Definition at line 347 of file XmlRpcInterface.cc.

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 }

bool XmlRpcInterface::readHeader ( char *  buf,
uint32_t  length 
) [protected]

Reads the http header.

Definition at line 944 of file XmlRpcInterface.cc.

Referenced by handleRealworldPacket().

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 }

bool XmlRpcInterface::readRequest ( char *  buf,
uint32_t  length 
) [protected]

Reads the request (based on the content-length header value).

Definition at line 1029 of file XmlRpcInterface.cc.

Referenced by handleRealworldPacket().

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 }

void XmlRpcInterface::resetConnectionState (  )  [protected]

Reset the internal connection state.

This is called after a RPC has finished and the socket was closed.

Definition at line 497 of file XmlRpcInterface.cc.

Referenced by closeConnection(), and handleMessage().

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 }

void XmlRpcInterface::sendInternalRpcWithTimeout ( CompType  destComp,
BaseCallMessage *  call 
) [protected]

Definition at line 519 of file XmlRpcInterface.cc.

Referenced by dumpDht(), get(), lookup(), p2pnsRegister(), p2pnsResolve(), and put().

00521 {
00522     state[curAppFd].pendingRpc = sendInternalRpcCall(destComp, call, NULL,
00523                                                      XMLRPC_TIMEOUT, 0,
00524                                                      curAppFd);
00525 }

bool XmlRpcInterface::writeResponse (  )  [protected]

Executes the request and writes the resulting response.

Definition at line 1062 of file XmlRpcInterface.cc.

Referenced by handleRealworldPacket(), handleRpcResponse(), and handleRpcTimeout().

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 }


Member Data Documentation

Definition at line 108 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 107 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 109 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 102 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 103 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 106 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 104 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

Definition at line 105 of file XmlRpcInterface.h.

Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

SOCKET XmlRpcInterface::appTunFd [protected]

FD of the application TUN socket used for tunneling.

Definition at line 137 of file XmlRpcInterface.h.

Referenced by deliverTunneledMessage(), handleReadyMessage(), and initializeApp().

SOCKET XmlRpcInterface::curAppFd [protected]
bool XmlRpcInterface::limitAccess [protected]

Definition at line 100 of file XmlRpcInterface.h.

Referenced by initializeApp(), and isPrivileged().

unsigned int XmlRpcInterface::mtu [protected]

Definition at line 47 of file XmlRpcInterface.h.

Referenced by initializeApp().

Pointer to the P2PNS module.

Definition at line 138 of file XmlRpcInterface.h.

Referenced by handleAppTunPacket(), handleReadyMessage(), initializeApp(), and XmlRpcInterface().

Definition at line 50 of file XmlRpcInterface.h.

Referenced by handleMessage(), and initializeApp().

cMessage* XmlRpcInterface::packetNotification [protected]

Definition at line 49 of file XmlRpcInterface.h.

Referenced by handleMessage(), initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().

std::map<int, XmlRpcConnectionState> XmlRpcInterface::state [protected]

The documentation for this class was generated from the following files:
Generated on Wed May 26 16:21:19 2010 for OverSim by  doxygen 1.6.3