XmlRpcInterface Class Reference

#include <XmlRpcInterface.h>

Inheritance diagram for XmlRpcInterface:

BaseApp XmlRpc::XmlRpcServer BaseRpc XmlRpc::XmlRpcSource RpcListener

List of all members.


Detailed Description

Applicaton that communicates with a realword application via a socket.

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 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.
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)

Protected Attributes

unsigned int mtu
cMessage * packetNotification
RealtimeScheduler::PacketBuffer packetBuffer
RealtimeSchedulerscheduler
std::map< int,
XmlRpcConnectionState
state
int curAppFd
XmlRpc::XmlRpcServerMethod_localLookup
XmlRpc::XmlRpcServerMethod_lookup
XmlRpc::XmlRpcServerMethod_register
XmlRpc::XmlRpcServerMethod_resolve
XmlRpc::XmlRpcServerMethod_put
XmlRpc::XmlRpcServerMethod_get
XmlRpc::XmlRpcServerMethod_dumpDht
XmlRpc::XmlRpcServerMethod_joinOverlay

Classes

struct  XmlRpcConnectionState

Member Enumeration Documentation

Possible IO states for the connection.

Enumerator:
READ_HEADER 
READ_REQUEST 
EXECUTE_REQUEST 
WRITE_RESPONSE 


Constructor & Destructor Documentation

XmlRpcInterface::XmlRpcInterface (  ) 

00391 {
00392     _localLookup = NULL;
00393     _lookup = NULL;
00394     _register = NULL;
00395     _resolve = NULL;
00396     _put = NULL;
00397     _get = NULL;
00398     _dumpDht = NULL;
00399     _joinOverlay = NULL;
00400 
00401     packetNotification = NULL;
00402 }

XmlRpcInterface::~XmlRpcInterface (  ) 

00405 {
00406     delete _localLookup;
00407     delete _lookup;
00408     delete _register;
00409     delete _resolve;
00410     delete _put;
00411     delete _get;
00412     delete _dumpDht;
00413     delete _joinOverlay;
00414 
00415     cancelAndDelete(packetNotification);
00416 }


Member Function Documentation

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

Reads the http header.

Referenced by handleRealworldPacket().

00734 {
00735     // Read available data
00736     bool eof = false;
00737 
00738     state[curAppFd]._header.append(std::string(buf, length));
00739 
00740     if (length <= 0) {
00741         // Its only an error if we already have read some data
00742         if (state[curAppFd]._header.length() > 0)
00743             XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error "
00744                 "while reading header.");
00745         return false;
00746     }
00747 
00748     XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.",
00749                     state[curAppFd]._header.length());
00750     char *hp = (char*)state[curAppFd]._header.c_str(); // Start of header
00751     char *ep = hp + state[curAppFd]._header.length(); // End of string
00752     char *bp = 0; // Start of body
00753     char *lp = 0; // Start of content-length value
00754     char *kp = 0; // Start of connection value
00755 
00756     for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
00757         if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
00758             lp = cp + 16;
00759         else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
00760             kp = cp + 12;
00761         else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
00762             bp = cp + 4;
00763         else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
00764             bp = cp + 2;
00765     }
00766 
00767     // If we haven't gotten the entire header yet, return (keep reading)
00768     if (bp == 0) {
00769         // EOF in the middle of a request is an error, otherwise its ok
00770         if (eof) {
00771             XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
00772             if (state[curAppFd]._header.length() > 0)
00773                 XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
00774             return false; // Either way we close the connection
00775         }
00776 
00777         return true; // Keep reading
00778     }
00779 
00780     // Decode content length
00781     if (lp == 0) {
00782         XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
00783         return false; // We could try to figure it out by parsing as we read, but for now...
00784     }
00785 
00786     state[curAppFd]._contentLength = atoi(lp);
00787     if (state[curAppFd]._contentLength <= 0) {
00788         XmlRpcUtil::error(
00789                           "XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).",
00790                           state[curAppFd]._contentLength);
00791         return false;
00792     }
00793 
00794     XmlRpcUtil::log(
00795                      3,
00796                     "XmlRpcServerConnection::readHeader: specified content length is %d.",
00797                     state[curAppFd]._contentLength);
00798 
00799     // Otherwise copy non-header data to request buffer and set state to read request.
00800     state[curAppFd]._request = bp;
00801 
00802     // Parse out any interesting bits from the header (HTTP version, connection)
00803     state[curAppFd]._keepAlive = true;
00804     if (state[curAppFd]._header.find("HTTP/1.0") != std::string::npos) {
00805         if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
00806             state[curAppFd]._keepAlive = false; // Default for HTTP 1.0 is to close the connection
00807     } else {
00808         if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
00809             state[curAppFd]._keepAlive = false;
00810     }
00811     XmlRpcUtil::log(3, "KeepAlive: %d", state[curAppFd]._keepAlive);
00812 
00813     state[curAppFd]._header = "";
00814     state[curAppFd]._connectionState = READ_REQUEST;
00815     return true; // Continue monitoring this source
00816 }

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

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

Referenced by handleRealworldPacket().

00819 {
00820     // If we dont have the entire request yet, read available data
00821     if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
00822         bool eof = false;
00823 
00824         state[curAppFd]._request.append(std::string(buf, length));
00825 
00826         if (length <= 0) {
00827             XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error.");
00828             return false;
00829         }
00830 
00831         // If we haven't gotten the entire request yet, return (keep reading)
00832         if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
00833             if (eof) {
00834                 XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
00835                 return false; // Either way we close the connection
00836             }
00837             return true;
00838         }
00839     }
00840 
00841     // Otherwise, parse and dispatch the request
00842     XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.",
00843                     state[curAppFd]._request.length());
00844     //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", state[curAppFd]._request.c_str());
00845 
00846     state[curAppFd]._connectionState = WRITE_RESPONSE;
00847 
00848     return true; // Continue monitoring this source
00849 }

bool XmlRpcInterface::writeResponse (  )  [protected]

Executes the request and writes the resulting response.

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

00852 {
00853     if (state[curAppFd]._response.length() == 0) {
00854         state[curAppFd]._response = executeRequest(state[curAppFd]._request);
00855         state[curAppFd]._bytesWritten = 0;
00856 
00857         if (state[curAppFd]._connectionState == EXECUTE_REQUEST)
00858             return true;
00859 
00860         if (state[curAppFd]._response.length() == 0) {
00861             XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
00862             return false;
00863         }
00864     }
00865 
00866     // Try to write the response
00867     int curBytesWritten = scheduler->sendBytes(state[curAppFd]._response.c_str(),
00868                                                state[curAppFd]._response.length(),
00869                                                0, 0, true, curAppFd);
00870 
00871     if (curBytesWritten <= 0) {
00872         XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error.");
00873         return false;
00874     } else {
00875         state[curAppFd]._bytesWritten += curBytesWritten;
00876     }
00877 
00878     XmlRpcUtil::log(
00879                      3,
00880                     "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.",
00881                     state[curAppFd]._bytesWritten, state[curAppFd]._response.length());
00882 
00883     // Prepare to read the next request
00884     if (state[curAppFd]._bytesWritten == int(state[curAppFd]._response.length())) {
00885         state[curAppFd]._header = "";
00886         state[curAppFd]._request = "";
00887         state[curAppFd]._response = "";
00888         state[curAppFd]._connectionState = READ_HEADER;
00889     }
00890 
00891     return state[curAppFd]._keepAlive; // Continue monitoring this source if true
00892 }

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

Referenced by handleMessage().

00543 {
00544     if (state[curAppFd]._connectionState == READ_HEADER) {
00545         if (!readHeader(buf, length)) {
00546             // discard data, if the header is invalid
00547             state[curAppFd]._header = "";
00548             state[curAppFd]._request = "";
00549             state[curAppFd]._response = "";
00550             state[curAppFd]._connectionState = READ_HEADER;
00551             return;
00552         }
00553     }
00554 
00555     if (state[curAppFd]._connectionState == READ_REQUEST)
00556         if (!readRequest(buf, length))
00557             return;
00558 
00559     if (state[curAppFd]._connectionState == WRITE_RESPONSE)
00560         if (!writeResponse() ) {
00561             closeConnection();
00562             return;
00563         }
00564 
00565     return;
00566 }

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

Referenced by handleMessage().

00729 {
00730     error("DHTXMLRealworldApp::handleCommonAPIPacket(): Unknown Packet!");
00731 }

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.

00572 {
00573     curAppFd = rpcId;
00574 
00575     if (state.count(curAppFd) == 0) {
00576         return;
00577     }
00578 
00579     RPC_SWITCH_START(msg)
00580     RPC_ON_RESPONSE(Lookup) {
00581         if (state[curAppFd]._connectionState != EXECUTE_REQUEST) break;
00582 
00583         XmlRpcValue resultValue;
00584         resultValue.setSize(_LookupResponse->getSiblingsArraySize());
00585 
00586         if (_LookupResponse->getIsValid() == true) {
00587             for (uint i=0; i < _LookupResponse->getSiblingsArraySize();
00588                     i++) {
00589                 resultValue[i].setSize(3);
00590                 resultValue[i][0] =
00591                 _LookupResponse->getSiblings(i).ip.str();
00592                 resultValue[i][1] =
00593                 _LookupResponse->getSiblings(i).port;
00594                 resultValue[i][2] =
00595                 _LookupResponse->getSiblings(i).key.toString(16);
00596             }
00597             state[curAppFd]._response = generateResponse(resultValue.toXml());
00598         } else {
00599             std::cout << "XmlRpcInterface(): lookup() failed!" << endl;
00600             state[curAppFd]._response = generateFaultResponse("lookup() failed", 22);
00601         }
00602 
00603         state[curAppFd]._connectionState = WRITE_RESPONSE;
00604         if (!writeResponse()) {
00605             closeConnection();
00606         }
00607         break;
00608     }
00609     RPC_ON_RESPONSE(P2pnsRegister) {
00610         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00611             break;
00612 
00613         XmlRpcValue resultValue;
00614 
00615         if (_P2pnsRegisterResponse->getIsSuccess() == true) {
00616             resultValue = 0;
00617             state[curAppFd]._response = generateResponse(resultValue.toXml());
00618         } else {
00619             std::cout << "XmlRpcInterface(): register() failed!" << endl;
00620             state[curAppFd]._response = generateFaultResponse("register() failed", 22);
00621         }
00622 
00623         state[curAppFd]._connectionState = WRITE_RESPONSE;
00624         if (!writeResponse() ) {
00625             closeConnection();
00626         }
00627         break;
00628     }
00629     RPC_ON_RESPONSE(P2pnsResolve) {
00630         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00631             break;
00632 
00633         XmlRpcValue resultValue;
00634         resultValue.setSize(1);
00635 
00636         if (_P2pnsResolveResponse->getIsSuccess() == true) {
00637             resultValue[0] = XmlRpcValue(
00638                                          &(*(_P2pnsResolveResponse->getAddress().begin())),
00639                                          _P2pnsResolveResponse->getAddress().size());
00640             state[curAppFd]._response = generateResponse(resultValue.toXml());
00641         } else {
00642             std::cout << "XmlRpcInterface(): resolve() failed!" << endl;
00643             state[curAppFd]._response = generateFaultResponse("resolve() failed: Name not found", 9);
00644         }
00645 
00646         state[curAppFd]._connectionState = WRITE_RESPONSE;
00647         if (!writeResponse() ) {
00648             closeConnection();
00649         }
00650         break;
00651     }
00652     RPC_ON_RESPONSE(DHTputCAPI) {
00653         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00654             break;
00655 
00656         XmlRpcValue resultValue;
00657 
00658         if (_DHTputCAPIResponse->getIsSuccess() == true) {
00659             resultValue = 0;
00660             state[curAppFd]._response = generateResponse(resultValue.toXml());
00661         } else {
00662             std::cout << "XmlRpcInterface(): put() failed!" << endl;
00663             state[curAppFd]._response = generateFaultResponse("put() failed", 22);
00664         }
00665 
00666         state[curAppFd]._connectionState = WRITE_RESPONSE;
00667         if (!writeResponse() ) {
00668             closeConnection();
00669         }
00670         break;
00671     }
00672     RPC_ON_RESPONSE(DHTgetCAPI) {
00673         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00674             break;
00675 
00676         XmlRpcValue resultValue;
00677         resultValue.setSize(2);
00678         resultValue[0].setSize(1);
00679 
00680         if (_DHTgetCAPIResponse->getIsSuccess() == true) {
00681             resultValue[0][0] = XmlRpcValue(
00682                       &(*(_DHTgetCAPIResponse->getValue().begin())),
00683                       _DHTgetCAPIResponse->getValue().size());
00684             resultValue[1] = std::string();
00685             state[curAppFd]._response = generateResponse(resultValue.toXml());
00686         } else {
00687             std::cout << "XmlRpcInterface(): get() failed!" << endl;
00688             state[curAppFd]._response = generateFaultResponse("get() failed", 22);
00689         }
00690 
00691         state[curAppFd]._connectionState = WRITE_RESPONSE;
00692         if (!writeResponse() ) {
00693             closeConnection();
00694         }
00695         break;
00696     }
00697     RPC_ON_RESPONSE(DHTdump) {
00698         if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
00699             break;
00700 
00701         XmlRpcValue resultValue;
00702         resultValue.setSize(_DHTdumpResponse->getRecordArraySize());
00703 
00704         for (uint i=0; i < _DHTdumpResponse->getRecordArraySize();
00705              i++) {
00706             resultValue[i].setSize(3);
00707             resultValue[i][0] =
00708                 _DHTdumpResponse->getRecord(i).key.toString(16);
00709             resultValue[i][1] = XmlRpcValue(
00710                  &(*(_DHTdumpResponse->getRecord(i).value.begin())),
00711                  _DHTdumpResponse->getRecord(i).value.size());
00712             resultValue[i][2] =
00713                 _DHTdumpResponse->getRecord(i).ttl;
00714         }
00715 
00716         state[curAppFd]._response = generateResponse(resultValue.toXml());
00717 
00718         state[curAppFd]._connectionState = WRITE_RESPONSE;
00719          if (!writeResponse()) {
00720              closeConnection();
00721          }
00722          break;
00723 
00724     }
00725     RPC_SWITCH_END( )
00726 }

void XmlRpcInterface::resetConnectionState (  )  [protected]

Reset the internal connection state.

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

Referenced by closeConnection(), and handleMessage().

00419 {
00420     if (state.count(curAppFd) && state[curAppFd].pendingRpc) {
00421         cancelRpcMessage(state[curAppFd].pendingRpc);
00422     }
00423 
00424     state[curAppFd].appFd = -1;
00425     state[curAppFd]._header = "";
00426     state[curAppFd]._request = "";
00427     state[curAppFd]._response = "";
00428     state[curAppFd]._connectionState = READ_HEADER;
00429     state[curAppFd]._keepAlive = true;
00430     state[curAppFd].pendingRpc = 0;
00431 }

void XmlRpcInterface::closeConnection (  )  [protected]

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

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

00441 {
00442     state[curAppFd].pendingRpc = sendInternalRpcCall(destComp, call, NULL,
00443                                                      XMLRPC_TIMEOUT, 0,
00444                                                      curAppFd);
00445 }

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

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

00362 {
00363     // all initialization is done in the first stage
00364     if (stage != MIN_STAGE_APP)
00365         return;
00366 
00367     packetNotification = new cMessage("packetNotification");
00368     mtu = par("mtu");
00369 
00370     scheduler = check_and_cast<RealtimeScheduler *>(simulation.scheduler());
00371     scheduler->setInterfaceModule(this, packetNotification, &packetBuffer, mtu,
00372                                    true);
00373 
00374     XmlRpc::setVerbosity(1);
00375 
00376     _localLookup = new LocalLookup(this);
00377     _lookup = new Lookup(this);
00378     _register = new P2pnsRegister(this);
00379     _resolve = new P2pnsResolve(this);
00380     _put = new Put(this);
00381     _get = new Get(this);
00382     _dumpDht = new DumpDht(this);
00383     _joinOverlay = new JoinOverlay(this);
00384 
00385     enableIntrospection(true);
00386 
00387     curAppFd = -1;
00388 }

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

The "main loop".

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

Reimplemented from BaseApp.

00448 {
00449     // Packet from the application...
00450     if (msg==packetNotification) {
00451         EV << "[DHTXMLRealworldApp::handleMessage() @ " << overlay->getThisNode().ip
00452         << " (" << overlay->getThisNode().key.toString(16) << ")]\n"
00453         << "    Message from application. Queue length = " << packetBuffer.size()
00454         << endl;
00455         while (packetBuffer.size() > 0) {
00456             // get packet from buffer and parse it
00457             RealtimeScheduler::PacketBufferEntry packet =
00458                     *(packetBuffer.begin());
00459             packetBuffer.pop_front();
00460             curAppFd = packet.fd;
00461 
00462             switch (packet.func) {
00463 
00464             case RealtimeScheduler::PacketBufferEntry::DATA:
00465 
00466                 if (state.count(curAppFd) == 0) {
00467                     throw new cRuntimeError("XmlRpcInterface::handleMessage(): "
00468                                             "Received packet "
00469                                             "from unknown socket!");
00470                 }
00471 
00472                 handleRealworldPacket(packet.data, packet.length);
00473                 break;
00474 
00475             case RealtimeScheduler::PacketBufferEntry::FD_NEW:
00476                 if (state.count(curAppFd)) {
00477                     throw new cRuntimeError("XmlRpcInterface::handleMessage(): "
00478                                             "Connection state table corrupt!");
00479                 }
00480 
00481                 resetConnectionState();
00482                 break;
00483 
00484             case RealtimeScheduler::PacketBufferEntry::FD_CLOSE:
00485                 if (state.count(curAppFd) == 0) {
00486                     throw new cRuntimeError("XmlRpcInterface::handleMessage(): "
00487                                             "Trying to close unknown "
00488                                             "connection!");
00489                 }
00490 
00491                 resetConnectionState();
00492                 state.erase(curAppFd);
00493             }
00494 
00495             if (packet.data) {
00496                 delete[] packet.data;
00497             }
00498         }
00499     } else if (msg->isSelfMessage()) {
00500         // process rpc self-messages
00501         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00502         if (rpcMessage!=NULL) {
00503             internalHandleRpcMessage(rpcMessage);
00504             return;
00505         }
00506 
00507         delete msg;
00508     } else {
00509         // RPCs
00510         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00511         if (rpcMessage!=NULL) {
00512             internalHandleRpcMessage(rpcMessage);
00513             return;
00514         }
00515         // common API
00516         CommonAPIMessage* commonAPIMsg = dynamic_cast<CommonAPIMessage*>(msg);
00517         if (commonAPIMsg != NULL)
00518             handleCommonAPIPacket(commonAPIMsg);
00519 
00520         delete msg;
00521     }
00522 }

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.

00528 {
00529     curAppFd = rpcId;
00530 
00531     if (state.count(curAppFd) == 0)
00532         return;
00533 
00534     std::cout << "DHTXMLRealworldApp(): XML-RPC failed!" << endl;
00535     state[curAppFd]._response = generateFaultResponse("XML-RPC timeout", 22);
00536     state[curAppFd]._connectionState = WRITE_RESPONSE;
00537     if (!writeResponse() ) {
00538         closeConnection();
00539     }
00540 }

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

00235 {
00236     if ((params.size() != 3)
00237             || (params[0].getType() != XmlRpcValue::TypeBase64)
00238             || (params[1].getType() != XmlRpcValue::TypeInt)
00239             || (params[2].getType() != XmlRpcValue::TypeBoolean))
00240         throw XmlRpcException("local_lookup(base64 key, int num, "
00241                 "boolean safe): Invalid argument type");
00242 
00243     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00244 
00245     NodeVector* nextHops = overlay->local_lookup(OverlayKey::sha1(keyString),
00246                                                  params[1], params[2]);
00247 
00248     for (uint i=0; i < nextHops->size(); i++) {
00249         result[i][0] = (*nextHops)[i].ip.str();
00250         result[i][1] = (*nextHops)[i].port;
00251         result[i][2] = (*nextHops)[i].key.toString(16);
00252     }
00253 
00254     delete nextHops;
00255 }

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

00258 {
00259     if ((params.size() != 2)
00260             || (params[0].getType() != XmlRpcValue::TypeBase64)
00261             || (params[1].getType() != XmlRpcValue::TypeInt))
00262         throw XmlRpcException("lookup(base64 key, int numSiblings): "
00263                 "Invalid argument type");
00264 
00265     if ((int)params[1] > overlay->getMaxNumSiblings())
00266         throw XmlRpcException("lookup(base64 key, int numSiblings): "
00267                 "numSibling to big");
00268 
00269     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00270 
00271     LookupCall* lookupCall = new LookupCall();
00272 
00273     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00274     lookupCall->setKey(OverlayKey::sha1(keyString));
00275     lookupCall->setNumSiblings(params[1]);
00276 
00277     sendInternalRpcWithTimeout(OVERLAY_COMP, lookupCall);
00278 }

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

00193 {
00194     if ((params.size() != 3) ||
00195             (params[0].getType() != XmlRpcValue::TypeBase64) ||
00196             (params[1].getType() != XmlRpcValue::TypeBase64) ||
00197             (params[2].getType() != XmlRpcValue::TypeInt))
00198         throw XmlRpcException("register(base64 name, base64 address, int ttl): "
00199                               "Invalid argument type");
00200 
00201     if (overlay->getCompModule(TIER2_COMP) == NULL)
00202         throw XmlRpcException("register(base64 name, base64 address, int ttl): "
00203                               "No P2PNS service");
00204 
00205     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00206 
00207     P2pnsRegisterCall* registerCall = new P2pnsRegisterCall();
00208 
00209     registerCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
00210     registerCall->setAddress(((const XmlRpcValue::BinaryData&)params[1]));
00211     registerCall->setTtl(params[2]);
00212 
00213     sendInternalRpcWithTimeout(TIER2_COMP, registerCall);
00214 }

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

00217 {
00218     if ((params.size() != 1) ||
00219             (params[0].getType() != XmlRpcValue::TypeBase64))
00220         throw XmlRpcException("resolve(base64 name): Invalid argument type");
00221 
00222     if (overlay->getCompModule(TIER2_COMP) == NULL)
00223         throw XmlRpcException("resolve(base64 name): No P2PNS service");
00224 
00225     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00226 
00227     P2pnsResolveCall* resolveCall = new P2pnsResolveCall();
00228 
00229     resolveCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
00230 
00231     sendInternalRpcWithTimeout(TIER2_COMP, resolveCall);
00232 }

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

00294 {
00295     if ((params.size() != 4)
00296             || (params[0].getType() != XmlRpcValue::TypeBase64)
00297             || (params[1].getType() != XmlRpcValue::TypeBase64)
00298             || (params[2].getType() != XmlRpcValue::TypeInt)
00299             || (params[3].getType() != XmlRpcValue::TypeString))
00300         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00301                 ", string application): Invalid argument type");
00302 
00303     if (overlay->getCompModule(TIER1_COMP) == NULL)
00304         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00305                 ", string application): No DHT service");
00306 
00307     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00308 
00309     DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00310 
00311     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00312 
00313     dhtPutMsg->setKey(OverlayKey::sha1(keyString));
00314     dhtPutMsg->setValue(((const XmlRpcValue::BinaryData&)params[1]));
00315     dhtPutMsg->setTtl(params[2]);
00316     dhtPutMsg->setIsModifiable(true);
00317 
00318     sendInternalRpcWithTimeout(TIER1_COMP, dhtPutMsg);
00319 }

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

00322 {
00323     if ((params.size() != 4)
00324             || (params[0].getType() != XmlRpcValue::TypeBase64)
00325             || (params[1].getType() != XmlRpcValue::TypeInt)
00326             || (params[2].getType() != XmlRpcValue::TypeBase64)
00327             || (params[3].getType() != XmlRpcValue::TypeString))
00328         throw XmlRpcException("get(base64 key, int num, base64 placemark "
00329                 ", string application): Invalid argument type");
00330 
00331     if (overlay->getCompModule(TIER1_COMP) == NULL)
00332         throw XmlRpcException("get(base64 key, int num, base64 placemark "
00333                 ", string application): No DHT service");
00334 
00335     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00336 
00337     DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00338 
00339     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00340     dhtGetMsg->setKey(OverlayKey::sha1(keyString));
00341 
00342     sendInternalRpcWithTimeout(TIER1_COMP, dhtGetMsg);
00343 }

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

00346 {
00347     if (params.size() != 1) {
00348         throw XmlRpcException("dump_dht(int dummy): Invalid argument type");
00349     }
00350 
00351     if (overlay->getCompModule(TIER1_COMP) == NULL)
00352         throw XmlRpcException("dump_dht(): No DHT service");
00353 
00354     state[curAppFd]._connectionState = EXECUTE_REQUEST;
00355 
00356     DHTdumpCall* call = new DHTdumpCall();
00357 
00358     sendInternalRpcWithTimeout(TIER1_COMP, call);
00359 }

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

00281 {
00282     if ((params.size() != 1)
00283             || (params[0].getType() != XmlRpcValue::TypeBase64))
00284         throw XmlRpcException("join(base64 nodeID): Invalid argument type");
00285 
00286     BinaryValue nodeID = (const XmlRpcValue::BinaryData&)params[0];
00287 
00288     overlay->join(OverlayKey::sha1(nodeID));
00289 
00290     result[0] = 0;
00291 }


Member Data Documentation

unsigned int XmlRpcInterface::mtu [protected]

Referenced by initializeApp().

cMessage* XmlRpcInterface::packetNotification [protected]

Referenced by handleMessage(), and initializeApp().

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

int XmlRpcInterface::curAppFd [protected]


The documentation for this class was generated from the following files:

Generated on Fri Sep 19 13:05:08 2008 for ITM OverSim by  doxygen 1.5.5