Applicaton that communicates with a realword application via a socket. More...
#include <XmlRpcInterface.h>
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 ¶ms, XmlRpc::XmlRpcValue &result) |
void | lookup (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | p2pnsRegister (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | p2pnsResolve (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | put (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | get (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | dumpDht (XmlRpc::XmlRpcValue ¶ms, XmlRpc::XmlRpcValue &result) |
void | joinOverlay (XmlRpc::XmlRpcValue ¶ms, 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 |
RealtimeScheduler * | scheduler |
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. | |
P2pns * | p2pns |
Pointer to the P2PNS module. |
Applicaton that communicates with a realword application via a socket.
Definition at line 44 of file XmlRpcInterface.h.
enum XmlRpcInterface::ServerConnectionState [protected] |
Possible IO states for the connection.
Definition at line 63 of file XmlRpcInterface.h.
00063 { READ_HEADER, READ_REQUEST, EXECUTE_REQUEST, 00064 WRITE_RESPONSE };
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 }
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
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.
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.
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
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.
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 }
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_dumpDht [protected] |
Definition at line 108 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_get [protected] |
Definition at line 107 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_joinOverlay [protected] |
Definition at line 109 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_localLookup [protected] |
Definition at line 102 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_lookup [protected] |
Definition at line 103 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_put [protected] |
Definition at line 106 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_register [protected] |
Definition at line 104 of file XmlRpcInterface.h.
Referenced by initializeApp(), XmlRpcInterface(), and ~XmlRpcInterface().
XmlRpc::XmlRpcServerMethod* XmlRpcInterface::_resolve [protected] |
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] |
Definition at line 99 of file XmlRpcInterface.h.
Referenced by closeConnection(), dumpDht(), get(), handleMessage(), handleRealworldPacket(), handleRpcResponse(), handleRpcTimeout(), initializeApp(), isPrivileged(), lookup(), p2pnsRegister(), p2pnsResolve(), put(), readHeader(), readRequest(), resetConnectionState(), sendInternalRpcWithTimeout(), and writeResponse().
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().
P2pns* XmlRpcInterface::p2pns [protected] |
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().
RealtimeScheduler* XmlRpcInterface::scheduler [protected] |
Definition at line 51 of file XmlRpcInterface.h.
Referenced by closeConnection(), deliverTunneledMessage(), initializeApp(), and writeResponse().
std::map<int, XmlRpcConnectionState> XmlRpcInterface::state [protected] |
Definition at line 98 of file XmlRpcInterface.h.
Referenced by dumpDht(), get(), handleMessage(), handleRealworldPacket(), handleRpcResponse(), handleRpcTimeout(), isPrivileged(), lookup(), p2pnsRegister(), p2pnsResolve(), put(), readHeader(), readRequest(), resetConnectionState(), sendInternalRpcWithTimeout(), and writeResponse().