DHTXMLRealworldApp Class Reference

#include <DHTXMLRealworldApp.h>

Inheritance diagram for DHTXMLRealworldApp:

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

virtual int numInitStages () const
 method to set InitStage
virtual void initialize (int stage)
 Initialization of the module.
virtual void handleMessage (cMessage *msg)
 The "main loop".
void localLookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void lookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void put (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void get (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, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.

Protected Attributes

unsigned int mtu
int gateIndexNetwOut
cMessage * timeout_msg
BaseOverlayoverlay
 pointer to the overlay module of this node
cMessage * packetNotification
RealtimeScheduler::PacketBuffer packetBuffer
RealtimeSchedulerscheduler
ServerConnectionState _connectionState
 Current IO state for the connection.
std::string _header
 Request headers.
int _contentLength
 Number of bytes expected in the request body (parsed from header).
std::string _request
 Request body.
std::string _response
 Response.
int _bytesWritten
 Number of bytes of the response written so far.
bool _keepAlive
 Whether to keep the current client connection open for further requests.
XmlRpc::XmlRpcServerMethod_localLookup
XmlRpc::XmlRpcServerMethod_lookup
XmlRpc::XmlRpcServerMethod_put
XmlRpc::XmlRpcServerMethod_get
XmlRpc::XmlRpcServerMethod_joinOverlay


Member Enumeration Documentation

enum DHTXMLRealworldApp::ServerConnectionState [protected]

Possible IO states for the connection.

Enumerator:
READ_HEADER 
READ_REQUEST 
EXECUTE_REQUEST 
WRITE_RESPONSE 


Member Function Documentation

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

Reads the http header.

00429 {
00430   // Read available data
00431   bool eof = false;
00432 
00433   _header.append(std::string(buf, length));
00434 
00435   if ( length <= 0 ) {
00436     // Its only an error if we already have read some data
00437     if (_header.length() > 0)
00438       XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error "
00439                         "while reading header.");
00440     return false;
00441   }
00442 
00443   XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.", _header.length());
00444   char *hp = (char*)_header.c_str();  // Start of header
00445   char *ep = hp + _header.length();   // End of string
00446   char *bp = 0;                       // Start of body
00447   char *lp = 0;                       // Start of content-length value
00448   char *kp = 0;                       // Start of connection value
00449 
00450   for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
00451         if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
00452           lp = cp + 16;
00453         else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
00454           kp = cp + 12;
00455         else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
00456           bp = cp + 4;
00457         else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
00458           bp = cp + 2;
00459   }
00460 
00461   // If we haven't gotten the entire header yet, return (keep reading)
00462   if (bp == 0) {
00463     // EOF in the middle of a request is an error, otherwise its ok
00464     if (eof) {
00465       XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
00466       if (_header.length() > 0)
00467         XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
00468       return false;   // Either way we close the connection
00469     }
00470     
00471     return true;  // Keep reading
00472   }
00473 
00474   // Decode content length
00475   if (lp == 0) {
00476     XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
00477     return false;   // We could try to figure it out by parsing as we read, but for now...
00478   }
00479 
00480   _contentLength = atoi(lp);
00481   if (_contentLength <= 0) {
00482     XmlRpcUtil::error("XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).", _contentLength);
00483     return false;
00484   }
00485         
00486   XmlRpcUtil::log(3, "XmlRpcServerConnection::readHeader: specified content length is %d.", _contentLength);
00487 
00488   // Otherwise copy non-header data to request buffer and set state to read request.
00489   _request = bp;
00490 
00491   // Parse out any interesting bits from the header (HTTP version, connection)
00492   _keepAlive = true;
00493   if (_header.find("HTTP/1.0") != std::string::npos) {
00494     if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
00495       _keepAlive = false;           // Default for HTTP 1.0 is to close the connection
00496   } else {
00497     if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
00498       _keepAlive = false;
00499   }
00500   XmlRpcUtil::log(3, "KeepAlive: %d", _keepAlive);
00501 
00502 
00503   _header = ""; 
00504   _connectionState = READ_REQUEST;
00505   return true;    // Continue monitoring this source
00506 }

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

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

00511 {
00512   // If we dont have the entire request yet, read available data
00513   if (int(_request.length()) < _contentLength) {
00514     bool eof = false;
00515 
00516     _request.append(std::string(buf, length));
00517 
00518     if ( length <= 0 ) {
00519         XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error.");
00520       return false;
00521     }
00522 
00523     // If we haven't gotten the entire request yet, return (keep reading)
00524     if (int(_request.length()) < _contentLength) {
00525       if (eof) {
00526         XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
00527         return false;   // Either way we close the connection
00528       }
00529       return true;
00530     }
00531   }
00532 
00533   // Otherwise, parse and dispatch the request
00534   XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.", _request.length());
00535   //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", _request.c_str());
00536 
00537   _connectionState = WRITE_RESPONSE;
00538 
00539   return true;    // Continue monitoring this source
00540 }

bool DHTXMLRealworldApp::writeResponse (  )  [protected]

Executes the request and writes the resulting response.

00545 {
00546     cancelEvent(timeout_msg);
00547 
00548   if (_response.length() == 0) {
00549       _response = executeRequest(_request);
00550     _bytesWritten = 0;
00551 
00552     if (_connectionState == EXECUTE_REQUEST)
00553         return true;
00554 
00555     if (_response.length() == 0) {
00556       XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
00557       return false;
00558     }
00559   }
00560 
00561   // Try to write the response
00562   int curBytesWritten = scheduler->sendBytes(_response.c_str(),
00563                                              _response.length(), 0, 0, true);
00564 
00565   if (curBytesWritten <= 0) {
00566       XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error.");
00567     return false;
00568   } else {
00569       _bytesWritten += curBytesWritten;
00570   }
00571 
00572   XmlRpcUtil::log(3, "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.", _bytesWritten, _response.length());
00573 
00574   // Prepare to read the next request
00575   if (_bytesWritten == int(_response.length())) {
00576     _header = "";
00577     _request = "";
00578     _response = "";
00579     _connectionState = READ_HEADER;
00580   }
00581 
00582   return _keepAlive;    // Continue monitoring this source if true
00583 }

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

00319 {
00320     if (_connectionState == READ_HEADER) {
00321         if (! readHeader(buf, length)) {
00322             // discard data, if the header is invalid
00323             _header = "";
00324             _request = "";
00325             _response = "";
00326             _connectionState = READ_HEADER;
00327             return;
00328         }
00329     }
00330 
00331     if (_connectionState == READ_REQUEST)
00332         if (! readRequest(buf, length)) return;
00333 
00334     if (_connectionState == WRITE_RESPONSE)
00335         if (! writeResponse() ) {
00336             scheduler->closeAppSocket();
00337             return;
00338         }
00339 
00340     return;
00341 }

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

00424 {
00425         error("DHTXMLRealworldApp::handleCommonAPIPacket(): Unknown Packet!");
00426 }

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

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

Parameters:
msg The response message.
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

00345 {
00346     RPC_SWITCH_START(msg)
00347     RPC_ON_RESPONSE( DHTlookupCAPI ) {
00348         if (_connectionState != EXECUTE_REQUEST) break;
00349 
00350         XmlRpcValue resultValue;
00351         resultValue.setSize(_DHTlookupCAPIResponse->getSiblingsArraySize());
00352 
00353         if (_DHTlookupCAPIResponse->getIsValid() == true) {
00354             for (uint i=0; i < _DHTlookupCAPIResponse->getSiblingsArraySize();
00355                  i++) {
00356                 resultValue[i].setSize(3);
00357                 resultValue[i][0] =
00358                     _DHTlookupCAPIResponse->getSiblings(i).ip.str();
00359                 resultValue[i][1] =
00360                     _DHTlookupCAPIResponse->getSiblings(i).port;
00361                 resultValue[i][2] =
00362                     _DHTlookupCAPIResponse->getSiblings(i).key.toString(16);
00363             }
00364             _response = generateResponse(resultValue.toXml());
00365         } else {
00366             std::cout << "DHTXMLRealworldApp(): lookup() failed!" << endl;
00367             _response = generateFaultResponse("lookup() failed", 22);
00368         }
00369 
00370         _connectionState = WRITE_RESPONSE;
00371         if (! writeResponse() ) {
00372             scheduler->closeAppSocket();
00373         }
00374         break;
00375     }
00376     RPC_ON_RESPONSE( DHTputCAPI ) {
00377         if (_connectionState != EXECUTE_REQUEST) break;
00378 
00379         XmlRpcValue resultValue;
00380 
00381         if (_DHTputCAPIResponse->getIsSuccess() == true) {
00382             resultValue = 0;
00383             _response = generateResponse(resultValue.toXml());
00384         } else {
00385             std::cout << "DHTXMLRealworldApp(): put() failed!" << endl;
00386             _response = generateFaultResponse("put() failed", 22);
00387         }
00388 
00389         _connectionState = WRITE_RESPONSE;
00390         if (! writeResponse() ) {
00391             scheduler->closeAppSocket();
00392         }
00393         break;
00394     }
00395     RPC_ON_RESPONSE( DHTgetCAPI ) {
00396         if (_connectionState != EXECUTE_REQUEST) break;
00397 
00398         XmlRpcValue resultValue;
00399         resultValue.setSize(2);
00400         resultValue[0].setSize(1);
00401 
00402         if (_DHTgetCAPIResponse->getIsSuccess() == true) {
00403             resultValue[0][0] = XmlRpcValue(
00404                 &(*(_DHTgetCAPIResponse->getValue().begin())),
00405                 _DHTgetCAPIResponse->getValue().size());
00406             resultValue[1] = std::string();
00407             _response = generateResponse(resultValue.toXml());
00408         } else {
00409             std::cout << "DHTXMLRealworldApp(): get() failed!" << endl;
00410             _response = generateFaultResponse("get() failed", 22);
00411         }
00412 
00413         _connectionState = WRITE_RESPONSE;
00414         if (! writeResponse() ) {
00415             scheduler->closeAppSocket();
00416         }
00417         break;
00418     }
00419     RPC_SWITCH_END( )
00420 }

virtual int DHTXMLRealworldApp::numInitStages (  )  const [inline, virtual]

method to set InitStage

Reimplemented from BaseApp.

00085     {
00086         return 4;
00087     }

void DHTXMLRealworldApp::initialize ( int  stage  )  [virtual]

Initialization of the module.

Registers the device at the scheduler and searches for the appropriate payload-parser Will be called automatically at startup

Reimplemented from BaseApp.

00226 {
00227     // all initialization is done in the first stage
00228     if (stage!=0)
00229         return;
00230 
00231     packetNotification = new cMessage("packetNotification");
00232     mtu = par("mtu");
00233 
00234     scheduler = check_and_cast<RealtimeScheduler *>(simulation.scheduler());
00235     scheduler->setInterfaceModule(this, packetNotification,
00236                                   &packetBuffer, mtu, true);
00237 
00238     gateIndexNetwOut = gate("to_lowerTier")->id();
00239 
00240     overlay = check_and_cast<BaseOverlay*>
00241         (gate("to_lowerTier")->destinationGate()->ownerModule()
00242          ->gate("to_lowerTier")->destinationGate()->ownerModule());
00243 
00244     if (overlay == NULL) {
00245         opp_error("DHTXMLRealworldApp::initialize(): Can't get pointer "
00246                   "to overlay module!");
00247     }
00248 
00249     XmlRpc::setVerbosity(1);
00250 
00251     _localLookup = new LocalLookup(this);
00252     _lookup = new Lookup(this);
00253     _put = new Put(this);
00254     _get = new Get(this);
00255     _joinOverlay = new JoinOverlay(this);
00256 
00257     enableIntrospection(true);
00258 
00259     _connectionState = READ_HEADER;
00260     _keepAlive = true;
00261 
00262     initRpcs();
00263 
00264     timeout_msg = new cMessage("timeout_msg");
00265 }

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

The "main loop".

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

Reimplemented from BaseApp.

00269 {
00270     // Packet from the application...
00271     if (msg==packetNotification) {
00272         EV << "[DHTXMLRealworldApp::handleMessage() @ " << thisNode.ip
00273            << " (" << thisNode.key.toString(16) << ")]\n"
00274            << "    Message from application. Queue length = " << packetBuffer.size()
00275            << endl;
00276         while( packetBuffer.size() > 0 ) {
00277             // get packet from buffer and parse it
00278             RealtimeScheduler::PacketBufferEntry packet =
00279                                                  *(packetBuffer.begin());
00280             packetBuffer.pop_front();
00281             handleRealworldPacket(packet.data, packet.length);
00282             delete packet.data;
00283         }
00284     } else if(msg->isSelfMessage()) {
00285         // process rpc self-messages
00286         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00287         if (rpcMessage!=NULL) {
00288             internalHandleRpcMessage(rpcMessage);
00289             return;
00290         }
00291         // process all other self-messages
00292         if (msg == timeout_msg) {
00293             std::cout << "DHTXMLRealworldApp(): XML-RPC failed!" << endl;
00294             _response = generateFaultResponse("XML-RPC timeout", 22);
00295             _connectionState = WRITE_RESPONSE;
00296             if (! writeResponse() ) {
00297                 scheduler->closeAppSocket();
00298             }
00299             return;
00300         }
00301     } else {
00302         // RPCs
00303         BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
00304         if (rpcMessage!=NULL) {
00305             internalHandleRpcMessage(rpcMessage);
00306             return;
00307         }
00308         // common API
00309         CommonAPIMessage* commonAPIMsg = dynamic_cast<CommonAPIMessage*>(msg);
00310         if(commonAPIMsg != NULL)
00311             handleCommonAPIPacket(commonAPIMsg);
00312 
00313         delete msg;
00314     }
00315 
00316 }

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

00106 {
00107       if ((params.size() != 3) ||
00108           (params[0].getType() != XmlRpcValue::TypeBase64) ||
00109           (params[1].getType() != XmlRpcValue::TypeInt) ||
00110           (params[2].getType() != XmlRpcValue::TypeBoolean)
00111           )
00112           throw XmlRpcException("local_lookup(base64 key, int num, "
00113                                 "boolean safe): Invalid argument type");
00114 
00115       BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00116       
00117       NodeVector* nextHops = overlay->local_lookup(
00118                        OverlayKey::sha1(keyString),
00119                        params[1], params[2]);
00120 
00121       for (uint i=0; i < nextHops->size(); i++) {
00122           result[i][0] = (*nextHops)[0].ip.str();
00123           result[i][1] = (*nextHops)[0].port;
00124           result[i][2] = (*nextHops)[0].key.toString(16);
00125       }
00126 
00127       delete nextHops;
00128 }

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

00131 {
00132     if ((params.size() != 2) ||
00133         (params[0].getType() != XmlRpcValue::TypeBase64) ||
00134         (params[1].getType() != XmlRpcValue::TypeInt))
00135         throw XmlRpcException("lookup(base64 key, int numSiblings): "
00136                               "Invalid argument type");
00137 
00138     if ((int)params[1] > overlay->getMaxNumSiblings())
00139         throw XmlRpcException("lookup(base64 key, int numSiblings): "
00140                               "numSibling to big");
00141 
00142     _connectionState = EXECUTE_REQUEST;
00143 
00144     DHTlookupCAPICall* dhtLookupMsg = new DHTlookupCAPICall();
00145 
00146     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00147     dhtLookupMsg->setKey(OverlayKey::sha1(keyString));
00148     dhtLookupMsg->setNumSiblings(params[1]);
00149    
00150     sendRpcMessage(RPC_TO_LOWERTIER, NodeHandle::UNSPECIFIED_NODE,
00151                    dhtLookupMsg, NULL, OverlayKey::UNSPECIFIED_KEY, -1, 0);
00152 
00153     cancelEvent(timeout_msg);
00154     scheduleAt(simulation.simTime() + XMLRPC_TIMEOUT, timeout_msg);
00155 }

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

00172 {
00173     if ((params.size() != 4) ||
00174         (params[0].getType() != XmlRpcValue::TypeBase64) ||
00175         (params[1].getType() != XmlRpcValue::TypeBase64) ||
00176         (params[2].getType() != XmlRpcValue::TypeInt) ||
00177         (params[3].getType() != XmlRpcValue::TypeString))
00178         throw XmlRpcException("put(base64 key, base64 value, int ttl "
00179             ", string application): Invalid argument type");
00180     
00181     _connectionState = EXECUTE_REQUEST;
00182     
00183     DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();
00184 
00185 
00186     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00187 
00188     dhtPutMsg->setKey(OverlayKey::sha1(keyString));
00189     dhtPutMsg->setValue(((const XmlRpcValue::BinaryData&)params[1]));
00190     dhtPutMsg->setTtl(params[2]);
00191     dhtPutMsg->setIsModifiable(true);
00192 
00193     sendRpcMessage(RPC_TO_LOWERTIER, NodeHandle::UNSPECIFIED_NODE, dhtPutMsg, NULL, OverlayKey::UNSPECIFIED_KEY, -1, 0);
00194 
00195     cancelEvent(timeout_msg);
00196     scheduleAt(simulation.simTime() + XMLRPC_TIMEOUT, timeout_msg);
00197 }

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

00200 {
00201     if ((params.size() != 4) ||
00202         (params[0].getType() != XmlRpcValue::TypeBase64) ||
00203         (params[1].getType() != XmlRpcValue::TypeInt) ||
00204         (params[2].getType() != XmlRpcValue::TypeBase64) ||
00205         (params[3].getType() != XmlRpcValue::TypeString))
00206         throw XmlRpcException("get(base64 key, int num, base64 placemark "
00207             ", string application): Invalid argument type");
00208     
00209     _connectionState = EXECUTE_REQUEST;
00210 
00211     DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();
00212 
00213 
00214     BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
00215     dhtGetMsg->setKey(OverlayKey::sha1(keyString));
00216    
00217     sendRpcMessage(RPC_TO_LOWERTIER, NodeHandle::UNSPECIFIED_NODE, dhtGetMsg, NULL, OverlayKey::UNSPECIFIED_KEY, -1, 0);
00218 
00219 
00220     cancelEvent(timeout_msg);
00221     scheduleAt(simulation.simTime() + XMLRPC_TIMEOUT, timeout_msg);
00222 }

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

00159 {
00160       if ((params.size() != 1) ||
00161           (params[0].getType() != XmlRpcValue::TypeBase64))
00162           throw XmlRpcException("join(base64 nodeID): Invalid argument type");
00163 
00164       BinaryValue nodeID = (const XmlRpcValue::BinaryData&)params[0];
00165 
00166       overlay->join(OverlayKey::sha1(nodeID));
00167 
00168       result[0] = 0;
00169 }


Member Data Documentation

unsigned int DHTXMLRealworldApp::mtu [protected]

int DHTXMLRealworldApp::gateIndexNetwOut [protected]

cMessage* DHTXMLRealworldApp::timeout_msg [protected]

BaseOverlay* DHTXMLRealworldApp::overlay [protected]

pointer to the overlay module of this node

Reimplemented from BaseApp.

cMessage* DHTXMLRealworldApp::packetNotification [protected]

RealtimeScheduler::PacketBuffer DHTXMLRealworldApp::packetBuffer [protected]

RealtimeScheduler* DHTXMLRealworldApp::scheduler [protected]

ServerConnectionState DHTXMLRealworldApp::_connectionState [protected]

Current IO state for the connection.

std::string DHTXMLRealworldApp::_header [protected]

Request headers.

int DHTXMLRealworldApp::_contentLength [protected]

Number of bytes expected in the request body (parsed from header).

std::string DHTXMLRealworldApp::_request [protected]

Request body.

std::string DHTXMLRealworldApp::_response [protected]

Response.

int DHTXMLRealworldApp::_bytesWritten [protected]

Number of bytes of the response written so far.

bool DHTXMLRealworldApp::_keepAlive [protected]

Whether to keep the current client connection open for further requests.

XmlRpc::XmlRpcServerMethod* DHTXMLRealworldApp::_localLookup [protected]

XmlRpc::XmlRpcServerMethod* DHTXMLRealworldApp::_lookup [protected]

XmlRpc::XmlRpcServerMethod* DHTXMLRealworldApp::_put [protected]

XmlRpc::XmlRpcServerMethod* DHTXMLRealworldApp::_get [protected]

XmlRpc::XmlRpcServerMethod* DHTXMLRealworldApp::_joinOverlay [protected]


The documentation for this class was generated from the following files:
Generated on Wed Sep 26 12:13:01 2007 for ITM OverSim by  doxygen 1.5.1