Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes

XmlRpcInterface Class Reference

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

#include <XmlRpcInterface.h>

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

List of all members.

Classes

struct  XmlRpcConnectionState

Public Member Functions

 XmlRpcInterface ()
 ~XmlRpcInterface ()
virtual void initializeApp (int stage)
virtual void handleMessage (cMessage *msg)
 The "main loop".
void handleRpcTimeout (BaseCallMessage *msg, const TransportAddress &dest, cPolymorphic *context, int rpcId, const OverlayKey &)
void deliverTunneledMessage (const BinaryValue &payload)
void localLookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void lookup (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void p2pnsRegister (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void p2pnsResolve (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void put (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void get (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void dumpDht (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)
void joinOverlay (XmlRpc::XmlRpcValue &params, XmlRpc::XmlRpcValue &result)

Protected Types

enum  ServerConnectionState { READ_HEADER, READ_REQUEST, EXECUTE_REQUEST, WRITE_RESPONSE }
 

Possible IO states for the connection.

More...

Protected Member Functions

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

Protected Attributes

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

Detailed Description

Applicaton that communicates with a realword application via a socket.

Definition at line 44 of file XmlRpcInterface.h.


Member Enumeration Documentation

Possible IO states for the connection.

Enumerator:
READ_HEADER 
READ_REQUEST 
EXECUTE_REQUEST 
WRITE_RESPONSE 

Definition at line 63 of file XmlRpcInterface.h.

                               { READ_HEADER, READ_REQUEST, EXECUTE_REQUEST,
                             WRITE_RESPONSE };


Constructor & Destructor Documentation

XmlRpcInterface::XmlRpcInterface (  ) 

Definition at line 467 of file XmlRpcInterface.cc.

{
    p2pns = NULL;

    _localLookup = NULL;
    _lookup = NULL;
    _register = NULL;
    _resolve = NULL;
    _put = NULL;
    _get = NULL;
    _dumpDht = NULL;
    _joinOverlay = NULL;

    packetNotification = NULL;
}

XmlRpcInterface::~XmlRpcInterface (  ) 

Definition at line 483 of file XmlRpcInterface.cc.

{
    delete _localLookup;
    delete _lookup;
    delete _register;
    delete _resolve;
    delete _put;
    delete _get;
    delete _dumpDht;
    delete _joinOverlay;

    cancelAndDelete(packetNotification);
}


Member Function Documentation

void XmlRpcInterface::closeConnection (  )  [protected]
void XmlRpcInterface::deliverTunneledMessage ( const BinaryValue payload  ) 

Definition at line 722 of file XmlRpcInterface.cc.

Referenced by P2pns::deliver().

{
#if not defined _WIN32 && not defined __APPLE__
    Enter_Method_Silent();

    if (payload.size() == 0) {
        return;
    }

    int curBytesWritten = scheduler->sendBytes(&payload[0],
                                               payload.size(),
                                               0, 0, true, appTunFd);

    if (curBytesWritten <= 0) {
        throw cRuntimeError("XmlRpcServerConnection::deliverTunneledMessage(): "
                            "Error writing to application TUN device.");
    }
#endif
}

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

Definition at line 404 of file XmlRpcInterface.cc.

{
    if (params.size() != 1) {
        throw XmlRpcException("dump_dht(int dummy): Invalid argument type");
    }

    if (!isPrivileged()) {
         throw XmlRpcException("dump_dht(int dummy): Not allowed");
     }

    if (overlay->getCompModule(TIER1_COMP) == NULL)
        throw XmlRpcException("dump_dht(): No DHT service");

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    DHTdumpCall* call = new DHTdumpCall();

    sendInternalRpcWithTimeout(TIER1_COMP, call);
}

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

Definition at line 380 of file XmlRpcInterface.cc.

{
    if ((params.size() != 4)
            || (params[0].getType() != XmlRpcValue::TypeBase64)
            || (params[1].getType() != XmlRpcValue::TypeInt)
            || (params[2].getType() != XmlRpcValue::TypeBase64)
            || (params[3].getType() != XmlRpcValue::TypeString))
        throw XmlRpcException("get(base64 key, int num, base64 placemark "
                ", string application): Invalid argument type");

    if (overlay->getCompModule(TIER1_COMP) == NULL)
        throw XmlRpcException("get(base64 key, int num, base64 placemark "
                ", string application): No DHT service");

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    DHTgetCAPICall* dhtGetMsg = new DHTgetCAPICall();

    BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
    dhtGetMsg->setKey(OverlayKey::sha1(keyString));

    sendInternalRpcWithTimeout(TIER1_COMP, dhtGetMsg);
}

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

Definition at line 682 of file XmlRpcInterface.cc.

Referenced by handleMessage().

{
#if not defined _WIN32 && not defined __APPLE__
    EV << "XmlRpcInterface::handleAppTunPacket(): packet of "
       << "length " << length << endl;

    if (!p2pns) {
        throw cRuntimeError("XmlRpcInterface::handleAppTunPacket(): "
                "P2PNS module missing on tier2!");
    }

    if (OverlayKey::getLength() < 100) {
        throw cRuntimeError("XmlRpcInterface::handleAppTunPacket(): "
                "P2PNS needs at least 100 bit nodeIds!");
    }

    if (length < 40) {
        EV << "XmlRpcInterface::handleAppTunPacket(): packet too "
           << "short - discarding packet!" << endl;
        return;
    }

    ip6_hdr* ip_buf = (ip6_hdr*) buf;
    if (((ip_buf->ip6_vfc & 0xf0) >> 4) != 6) {
        EV << "XmlRpcInterface::handleAppTunPacket(): received packet "
              "is no IPv6 - discarding packet!" << endl;
        return;
    }

    OverlayKey destKey = OverlayKey(ntohl(ip_buf->ip6_dst.s6_addr32[0]));

    for (int i = 1; i < 4; i++) {
        destKey = (destKey << 32) + OverlayKey(ntohl(ip_buf->ip6_dst.s6_addr32[i]));
    }
    destKey = destKey << (OverlayKey::getLength() - 100);

    p2pns->tunnel(destKey, BinaryValue(buf, buf + length));
#endif
}

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

Definition at line 939 of file XmlRpcInterface.cc.

Referenced by handleMessage().

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

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

The "main loop".

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

Definition at line 527 of file XmlRpcInterface.cc.

{
    // Packet from the application...
    if (msg==packetNotification) {
        EV << "[XmlRpcInterface::handleMessage() @ " << overlay->getThisNode().getIp()
        << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
        << "    Message from application. Queue length = " << packetBuffer.size()
        << endl;
        while (packetBuffer.size() > 0) {
            // get packet from buffer and parse it
            RealtimeScheduler::PacketBufferEntry packet =
                    *(packetBuffer.begin());
            packetBuffer.pop_front();
            curAppFd = packet.fd;

            switch (packet.func) {
            case RealtimeScheduler::PacketBufferEntry::PACKET_APPTUN_DATA:
                handleAppTunPacket(packet.data, packet.length);
                break;

            case RealtimeScheduler::PacketBufferEntry::PACKET_DATA:
                if (state.count(curAppFd) == 0) {
                    throw cRuntimeError("XmlRpcInterface::handleMessage(): "
                                            "Received packet "
                                            "from unknown socket!");
                }

                handleRealworldPacket(packet.data, packet.length);
                break;

            case RealtimeScheduler::PacketBufferEntry::PACKET_FD_NEW:
                if (state.count(curAppFd)) {
                    throw cRuntimeError("XmlRpcInterface::handleMessage(): "
                                            "Connection state table corrupt!");
                }

                resetConnectionState();

                if (packet.addr != NULL) {
                    if (((sockaddr_in*)packet.addr)->sin_addr.s_addr
                            == inet_addr("127.0.0.1")) {
                        state[curAppFd].localhost = true;
                    }
                    delete packet.addr;
                    packet.addr = NULL;
                }
                break;

            case RealtimeScheduler::PacketBufferEntry::PACKET_FD_CLOSE:
                if (state.count(curAppFd) == 0) {
                    throw cRuntimeError("XmlRpcInterface::handleMessage(): "
                                            "Trying to close unknown "
                                            "connection!");
                }

                resetConnectionState();
                state.erase(curAppFd);
            }

            if (packet.data) {
                delete[] packet.data;
            }
        }
    } else if (msg->isSelfMessage()) {
        // process rpc self-messages
        BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
        if (rpcMessage!=NULL) {
            internalHandleRpcMessage(rpcMessage);
            return;
        }

        delete msg;
    } else {
        // RPCs
        BaseRpcMessage* rpcMessage = dynamic_cast<BaseRpcMessage*>(msg);
        if (rpcMessage!=NULL) {
            internalHandleRpcMessage(rpcMessage);
            return;
        }
        // common API
        CommonAPIMessage* commonAPIMsg = dynamic_cast<CommonAPIMessage*>(msg);
        if (commonAPIMsg != NULL)
            handleCommonAPIPacket(commonAPIMsg);

        CompReadyMessage* readyMsg = dynamic_cast<CompReadyMessage*>(msg);
        if (readyMsg != NULL)
            handleReadyMessage(readyMsg);

        delete msg;
    }
}

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

Definition at line 637 of file XmlRpcInterface.cc.

Referenced by handleMessage().

{
    if ((msg->getReady() == false) || (msg->getComp() != OVERLAY_COMP)) {
        return;
    }

    if (appTunFd != INVALID_SOCKET) {
        // set TUN interface address using the current NodeId
        // TODO: this is ugly
        const OverlayKey& key = overlay->getThisNode().getKey();

        if (OverlayKey::getLength() < 100) {
            throw cRuntimeError("XmlRpcInterface::handleReadyMessage(): "
                    "P2PNS needs at least 100 bit nodeIds!");
        }

        std::stringstream addr;
        addr << "2001:001";
        for (int i = 0; i < 100/4; i++) {
            if (((i + 3) % 4) == 0) {
                addr << ":";
            }
            addr << std::hex << key.getBitRange(OverlayKey::getLength() -
                                                4 * (i + 1), 4);
        }

        std::string cmd = "/sbin/ip addr add " + addr.str() + "/28 dev tun0";

        EV << "XmlRpcInterface::handleOverlayReady(): "
              "Setting TUN interface address " << addr.str() << endl;

        if (system(cmd.c_str()) != 0) {
            EV << "XmlRpcInterface::handleOverlayReady(): "
                  "Failed to set TUN interface address!" << endl;
        }

        if (system("/sbin/ip link set tun0 up") != 0) {
            EV << "XmlRpcInterface::handleOverlayReady(): "
                  "Failed to set TUN interface up!" << endl;
        }

        p2pns->registerId(addr.str());
    }
}

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

Definition at line 742 of file XmlRpcInterface.cc.

Referenced by handleMessage().

{
    if (state[curAppFd]._connectionState == READ_HEADER) {
        if (!readHeader(buf, length)) {
            // discard data, if the header is invalid
            state[curAppFd]._header = "";
            state[curAppFd]._request = "";
            state[curAppFd]._response = "";
            state[curAppFd]._connectionState = READ_HEADER;
            return;
        }
    }

    if (state[curAppFd]._connectionState == READ_REQUEST)
        if (!readRequest(buf, length))
            return;

    if (state[curAppFd]._connectionState == WRITE_RESPONSE)
        if (!writeResponse() ) {
            closeConnection();
            return;
        }

    return;
}

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

Definition at line 768 of file XmlRpcInterface.cc.

{
    curAppFd = rpcId;

    if (state.count(curAppFd) == 0) {
        return;
    }

    RPC_SWITCH_START(msg)
    RPC_ON_RESPONSE(Lookup) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST) break;

        XmlRpcValue resultValue;
        resultValue.setSize(_LookupResponse->getSiblingsArraySize());

        if (_LookupResponse->getIsValid() == true) {
            for (uint32_t i=0; i < _LookupResponse->getSiblingsArraySize();
                    i++) {
                resultValue[i].setSize(3);
                resultValue[i][0] =
                    _LookupResponse->getSiblings(i).getIp().str();
                resultValue[i][1] =
                    _LookupResponse->getSiblings(i).getPort();
                resultValue[i][2] =
                    _LookupResponse->getSiblings(i).getKey().toString(16);
            }
            state[curAppFd]._response = generateResponse(resultValue.toXml());
        } else {
            std::cout << "XmlRpcInterface(): lookup() failed!" << endl;
            state[curAppFd]._response = generateFaultResponse("lookup() failed", 22);
        }

        state[curAppFd]._connectionState = WRITE_RESPONSE;
        if (!writeResponse()) {
            closeConnection();
        }
        break;
    }
    RPC_ON_RESPONSE(P2pnsRegister) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
            break;

        XmlRpcValue resultValue;

        if (_P2pnsRegisterResponse->getIsSuccess() == true) {
            resultValue = 0;
            state[curAppFd]._response = generateResponse(resultValue.toXml());
        } else {
            std::cout << "XmlRpcInterface(): register() failed!" << endl;
            state[curAppFd]._response = generateFaultResponse("register() failed", 22);
        }

        state[curAppFd]._connectionState = WRITE_RESPONSE;
        if (!writeResponse() ) {
            closeConnection();
        }
        break;
    }
    RPC_ON_RESPONSE(P2pnsResolve) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
            break;

        XmlRpcValue resultValue;
        resultValue.setSize(_P2pnsResolveResponse->getAddressArraySize());

        if (_P2pnsResolveResponse->getIsSuccess() == true) {
            for (uint i=0; i < _P2pnsResolveResponse->getAddressArraySize(); i++) {
                resultValue[i].setSize(3);
                BinaryValue& addr = _P2pnsResolveResponse->getAddress(i);
                resultValue[i][0] = XmlRpcValue(&addr[0], addr.size());
                resultValue[i][1] = (int)_P2pnsResolveResponse->getKind(i);
                resultValue[i][2] = (int)_P2pnsResolveResponse->getId(i);
            }
            state[curAppFd]._response = generateResponse(resultValue.toXml());
        } else {
            std::cout << "XmlRpcInterface(): resolve() failed!" << endl;
            state[curAppFd]._response = generateFaultResponse("resolve() failed: Name not found", 9);
        }

        state[curAppFd]._connectionState = WRITE_RESPONSE;
        if (!writeResponse() ) {
            closeConnection();
        }
        break;
    }
    RPC_ON_RESPONSE(DHTputCAPI) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
            break;

        XmlRpcValue resultValue;

        if (_DHTputCAPIResponse->getIsSuccess() == true) {
            resultValue = 0;
            state[curAppFd]._response = generateResponse(resultValue.toXml());
        } else {
            std::cout << "XmlRpcInterface(): put() failed!" << endl;
            state[curAppFd]._response = generateFaultResponse("put() failed", 22);
        }

        state[curAppFd]._connectionState = WRITE_RESPONSE;
        if (!writeResponse() ) {
            closeConnection();
        }
        break;
    }
    RPC_ON_RESPONSE(DHTgetCAPI) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
            break;

        XmlRpcValue resultValue;
        resultValue.setSize(2);
        resultValue[0].setSize(_DHTgetCAPIResponse->getResultArraySize());

        if (_DHTgetCAPIResponse->getIsSuccess() == true) {
            for (uint i=0; i < _DHTgetCAPIResponse->getResultArraySize(); i++) {
                resultValue[i].setSize(2);
                DhtDumpEntry& entry = _DHTgetCAPIResponse->getResult(i);
                resultValue[0][i] = XmlRpcValue(&(*(entry.getValue().begin())),
                                                entry.getValue().size());
            }
            resultValue[1] = std::string();

//            resultValue[0][0] = XmlRpcValue(
//                      &(*(_DHTgetCAPIResponse->getValue().begin())),
//                      _DHTgetCAPIResponse->getValue().size());
            state[curAppFd]._response = generateResponse(resultValue.toXml());
        } else {
            std::cout << "XmlRpcInterface(): get() failed!" << endl;
            state[curAppFd]._response = generateFaultResponse("get() failed", 22);
        }

        state[curAppFd]._connectionState = WRITE_RESPONSE;
        if (!writeResponse() ) {
            closeConnection();
        }
        break;
    }
    RPC_ON_RESPONSE(DHTdump) {
        if (state[curAppFd]._connectionState != EXECUTE_REQUEST)
            break;

        XmlRpcValue resultValue;
        resultValue.setSize(_DHTdumpResponse->getRecordArraySize());

        for (uint32_t i=0; i < _DHTdumpResponse->getRecordArraySize();
             i++) {
            resultValue[i].setSize(3);
            resultValue[i][0] =
                _DHTdumpResponse->getRecord(i).getKey().toString(16);
            resultValue[i][1] = XmlRpcValue(
                 &(*(_DHTdumpResponse->getRecord(i).getValue().begin())),
                 _DHTdumpResponse->getRecord(i).getValue().size());
            resultValue[i][2] =
                _DHTdumpResponse->getRecord(i).getTtl();
        }

        state[curAppFd]._response = generateResponse(resultValue.toXml());

        state[curAppFd]._connectionState = WRITE_RESPONSE;
         if (!writeResponse()) {
             closeConnection();
         }
         break;

    }
    RPC_SWITCH_END( )
}

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

Definition at line 619 of file XmlRpcInterface.cc.

{
    curAppFd = rpcId;

    if (state.count(curAppFd) == 0)
        return;

    std::cout << "XmlRpcInterface(): XML-RPC failed!" << endl;
    state[curAppFd]._response = generateFaultResponse("XML-RPC timeout", 22);
    state[curAppFd]._connectionState = WRITE_RESPONSE;
    if (!writeResponse() ) {
        closeConnection();
    }
}

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

Definition at line 433 of file XmlRpcInterface.cc.

{
    // all initialization is done in the first stage
    if (stage != MAX_STAGE_APP)
        return;

    packetNotification = new cMessage("packetNotification");
    mtu = par("mtu");
    limitAccess = par("limitAccess");

    scheduler = check_and_cast<RealtimeScheduler *>(simulation.getScheduler());
    scheduler->setInterfaceModule(this, packetNotification, &packetBuffer, mtu,
                                  true);

    appTunFd = scheduler->getAppTunFd();

    p2pns = dynamic_cast<P2pns*>(overlay->getCompModule(TIER2_COMP));

    XmlRpc::setVerbosity(1);

    _localLookup = new LocalLookup(this);
    _lookup = new Lookup(this);
    _register = new P2pnsRegister(this);
    _resolve = new P2pnsResolve(this);
    _put = new Put(this);
    _get = new Get(this);
    _dumpDht = new DumpDht(this);
    _joinOverlay = new JoinOverlay(this);

    enableIntrospection(true);

    curAppFd = INVALID_SOCKET;
}

bool XmlRpcInterface::isPrivileged (  )  [protected]

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

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

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

Definition at line 424 of file XmlRpcInterface.cc.

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

{
    if (limitAccess) {
        return state[curAppFd].localhost;
    } else {
        return true;
    }
}

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

Definition at line 330 of file XmlRpcInterface.cc.

{
    if ((params.size() != 1)
            || (params[0].getType() != XmlRpcValue::TypeBase64))
        throw XmlRpcException("join(base64 nodeID): Invalid argument type");

    if (!isPrivileged()) {
        throw XmlRpcException("join(base64 nodeID): Not allowed");
    }

    BinaryValue nodeID = (const XmlRpcValue::BinaryData&)params[0];

    overlay->join(OverlayKey::sha1(nodeID));

    result[0] = 0;
}

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

Definition at line 256 of file XmlRpcInterface.cc.

{
    if ((params.size() != 3)
            || (params[0].getType() != XmlRpcValue::TypeBase64)
            || (params[1].getType() != XmlRpcValue::TypeInt)
            || (params[2].getType() != XmlRpcValue::TypeBoolean))
        throw XmlRpcException("local_lookup(base64 key, int num, "
                "boolean safe): Invalid argument type");

    BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];

    NodeVector* nextHops = NULL;

    if (keyString.size() > 0) {
        nextHops = overlay->local_lookup(OverlayKey::sha1(keyString),
                                                     params[1], params[2]);
    } else {
        nextHops = overlay->local_lookup(overlay->getThisNode().getKey(),
                                                     params[1], params[2]);
    }

    for (uint32_t i=0; i < nextHops->size(); i++) {
        result[i][0] = (*nextHops)[i].getIp().str();
        result[i][1] = (*nextHops)[i].getPort();
        result[i][2] = (*nextHops)[i].getKey().toString(16);
    }

    delete nextHops;
}

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

Definition at line 286 of file XmlRpcInterface.cc.

{
    if (((params.size() != 2)
            || (params[0].getType() != XmlRpcValue::TypeBase64)
            || (params[1].getType() != XmlRpcValue::TypeInt))
        && ((params.size() != 3)
            || (params[0].getType() != XmlRpcValue::TypeBase64)
            || (params[1].getType() != XmlRpcValue::TypeInt)
            || (params[2].getType() != XmlRpcValue::TypeInt)))
        throw XmlRpcException("lookup(base64 key, int numSiblings(, "
                              "int RoutingType)): Invalid argument type");

    if ((int)params[1] > overlay->getMaxNumSiblings())
        throw XmlRpcException("lookup(base64 key, int numSiblings(, "
                              "int RoutingType)): numSibling to big");

    if (params.size() == 3) {
        if (((int)params[2] != DEFAULT_ROUTING) &&
            ((int)params[2] != ITERATIVE_ROUTING) &&
            ((int)params[2] != EXHAUSTIVE_ITERATIVE_ROUTING) &&
            ((int)params[2] != SEMI_RECURSIVE_ROUTING) &&
            ((int)params[2] != FULL_RECURSIVE_ROUTING) &&
            ((int)params[2] != RECURSIVE_SOURCE_ROUTING)) {

            throw XmlRpcException("lookup(base64 key, int numSiblings(, "
                                  "int RoutingType)): invalid routingType");
        }
    }

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    LookupCall* lookupCall = new LookupCall();

    BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];
    lookupCall->setKey(OverlayKey::sha1(keyString));
    lookupCall->setNumSiblings(params[1]);

    if (params.size() == 3) {
        lookupCall->setRoutingType(params[2]);
    }

    sendInternalRpcWithTimeout(OVERLAY_COMP, lookupCall);
}

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

Definition at line 203 of file XmlRpcInterface.cc.

{
    if ((params.size() != 5) ||
            (params[0].getType() != XmlRpcValue::TypeBase64) ||
            (params[1].getType() != XmlRpcValue::TypeInt) ||
            (params[2].getType() != XmlRpcValue::TypeInt) ||
            (params[3].getType() != XmlRpcValue::TypeBase64) ||
            (params[4].getType() != XmlRpcValue::TypeInt))
        throw XmlRpcException("register(base64 name, int kind, int id, base64 address, int ttl): "
                              "Invalid argument type");

    if (overlay->getCompModule(TIER2_COMP) == NULL)
        throw XmlRpcException("register(base64 name, int kind, int id, base64 address, int ttl): "
                              "No P2PNS service");

    if (!isPrivileged()) {
        throw XmlRpcException("register(base64 name, int kind, base64 address, "
                              "int ttl): Not allowed");
    }

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    P2pnsRegisterCall* registerCall = new P2pnsRegisterCall();
    registerCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
    registerCall->setKind((int)params[1]);
    registerCall->setId((int)params[2]);
    registerCall->setAddress(((const XmlRpcValue::BinaryData&)params[3]));
    registerCall->setTtl(params[4]);

    sendInternalRpcWithTimeout(TIER2_COMP, registerCall);
}

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

Definition at line 235 of file XmlRpcInterface.cc.

{
    if ((params.size() != 2) ||
            (params[0].getType() != XmlRpcValue::TypeBase64) ||
            (params[1].getType() != XmlRpcValue::TypeInt))
        throw XmlRpcException("resolve(base64 name, int kind): Invalid argument type");

    if (overlay->getCompModule(TIER2_COMP) == NULL)
        throw XmlRpcException("resolve(base64 name, int kind): No P2PNS service");

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    P2pnsResolveCall* resolveCall = new P2pnsResolveCall();

    resolveCall->setP2pName(((const XmlRpcValue::BinaryData&)params[0]));
    resolveCall->setKind((int)params[1]);
    resolveCall->setId(0);

    sendInternalRpcWithTimeout(TIER2_COMP, resolveCall);
}

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

Definition at line 347 of file XmlRpcInterface.cc.

{
    if ((params.size() != 4)
            || (params[0].getType() != XmlRpcValue::TypeBase64)
            || (params[1].getType() != XmlRpcValue::TypeBase64)
            || (params[2].getType() != XmlRpcValue::TypeInt)
            || (params[3].getType() != XmlRpcValue::TypeString))
        throw XmlRpcException("put(base64 key, base64 value, int ttl "
                ", string application): Invalid argument type");

    if (!isPrivileged()) {
        throw XmlRpcException("put(base64 key, base64 value, int ttl "
                ", string application): Not allowed");
    }

    if (overlay->getCompModule(TIER1_COMP) == NULL)
        throw XmlRpcException("put(base64 key, base64 value, int ttl "
                ", string application): No DHT service");

    state[curAppFd]._connectionState = EXECUTE_REQUEST;

    DHTputCAPICall* dhtPutMsg = new DHTputCAPICall();

    BinaryValue keyString = (const XmlRpcValue::BinaryData&)params[0];

    dhtPutMsg->setKey(OverlayKey::sha1(keyString));
    dhtPutMsg->setValue(((const XmlRpcValue::BinaryData&)params[1]));
    dhtPutMsg->setTtl(params[2]);
    dhtPutMsg->setIsModifiable(true);

    sendInternalRpcWithTimeout(TIER1_COMP, dhtPutMsg);
}

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

Reads the http header.

Definition at line 944 of file XmlRpcInterface.cc.

Referenced by handleRealworldPacket().

{
    // Read available data
    bool eof = false;

    state[curAppFd]._header.append(std::string(buf, length));

    if (length <= 0) {
        // Its only an error if we already have read some data
        if (state[curAppFd]._header.length() > 0)
            XmlRpcUtil::error("XmlRpcServerConnection::readHeader: error "
                "while reading header.");
        return false;
    }

    XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: read %d bytes.",
                    state[curAppFd]._header.length());
    char *hp = (char*)state[curAppFd]._header.c_str(); // Start of header
    char *ep = hp + state[curAppFd]._header.length(); // End of string
    char *bp = 0; // Start of body
    char *lp = 0; // Start of content-length value
    char *kp = 0; // Start of connection value

    for (char *cp = hp; (bp == 0) && (cp < ep); ++cp) {
        if ((ep - cp > 16) && (strncasecmp(cp, "Content-length: ", 16) == 0))
            lp = cp + 16;
        else if ((ep - cp > 12) && (strncasecmp(cp, "Connection: ", 12) == 0))
            kp = cp + 12;
        else if ((ep - cp > 4) && (strncmp(cp, "\r\n\r\n", 4) == 0))
            bp = cp + 4;
        else if ((ep - cp > 2) && (strncmp(cp, "\n\n", 2) == 0))
            bp = cp + 2;
    }

    // If we haven't gotten the entire header yet, return (keep reading)
    if (bp == 0) {
        // EOF in the middle of a request is an error, otherwise its ok
        if (eof) {
            XmlRpcUtil::log(4, "XmlRpcServerConnection::readHeader: EOF");
            if (state[curAppFd]._header.length() > 0)
                XmlRpcUtil::error("XmlRpcServerConnection::readHeader: EOF while reading header");
            return false; // Either way we close the connection
        }

        return true; // Keep reading
    }

    // Decode content length
    if (lp == 0) {
        XmlRpcUtil::error("XmlRpcServerConnection::readHeader: No Content-length specified");
        return false; // We could try to figure it out by parsing as we read, but for now...
    }

    state[curAppFd]._contentLength = atoi(lp);
    if (state[curAppFd]._contentLength <= 0) {
        XmlRpcUtil::error(
                          "XmlRpcServerConnection::readHeader: Invalid Content-length specified (%d).",
                          state[curAppFd]._contentLength);
        return false;
    }

    XmlRpcUtil::log(
                     3,
                    "XmlRpcServerConnection::readHeader: specified content length is %d.",
                    state[curAppFd]._contentLength);

    // Otherwise copy non-header data to request buffer and set state to read request.
    state[curAppFd]._request = bp;

    // Parse out any interesting bits from the header (HTTP version, connection)
    state[curAppFd]._keepAlive = true;
    if (state[curAppFd]._header.find("HTTP/1.0") != std::string::npos) {
        if (kp == 0 || strncasecmp(kp, "keep-alive", 10) != 0)
            state[curAppFd]._keepAlive = false; // Default for HTTP 1.0 is to close the connection
    } else {
        if (kp != 0 && strncasecmp(kp, "close", 5) == 0)
            state[curAppFd]._keepAlive = false;
    }
    XmlRpcUtil::log(3, "KeepAlive: %d", state[curAppFd]._keepAlive);

    state[curAppFd]._header = "";
    state[curAppFd]._connectionState = READ_REQUEST;
    return true; // Continue monitoring this source
}

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

{
    // If we dont have the entire request yet, read available data
    if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
        bool eof = false;

        state[curAppFd]._request.append(std::string(buf, length));

        if (length <= 0) {
            XmlRpcUtil::error("XmlRpcServerConnection::readRequest: read error.");
            return false;
        }

        // If we haven't gotten the entire request yet, return (keep reading)
        if (int(state[curAppFd]._request.length()) < state[curAppFd]._contentLength) {
            if (eof) {
                XmlRpcUtil::error("XmlRpcServerConnection::readRequest: EOF while reading request");
                return false; // Either way we close the connection
            }
            return true;
        }
    }

    // Otherwise, parse and dispatch the request
    XmlRpcUtil::log(3, "XmlRpcServerConnection::readRequest read %d bytes.",
                    state[curAppFd]._request.length());
    //XmlRpcUtil::log(5, "XmlRpcServerConnection::readRequest:\n%s\n", state[curAppFd]._request.c_str());

    state[curAppFd]._connectionState = WRITE_RESPONSE;

    return true; // Continue monitoring this source
}

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

{
    if (state.count(curAppFd) && state[curAppFd].pendingRpc) {
        cancelRpcMessage(state[curAppFd].pendingRpc);
    }

    state[curAppFd].appFd = INVALID_SOCKET;
    state[curAppFd].localhost = false;
    state[curAppFd]._header = "";
    state[curAppFd]._request = "";
    state[curAppFd]._response = "";
    state[curAppFd]._connectionState = READ_HEADER;
    state[curAppFd]._keepAlive = true;
    state[curAppFd].pendingRpc = 0;
}

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

{
    state[curAppFd].pendingRpc = sendInternalRpcCall(destComp, call, NULL,
                                                     XMLRPC_TIMEOUT, 0,
                                                     curAppFd);
}

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

{
    if (state[curAppFd]._response.length() == 0) {
        state[curAppFd]._response = executeRequest(state[curAppFd]._request);
        state[curAppFd]._bytesWritten = 0;

        if (state[curAppFd]._connectionState == EXECUTE_REQUEST)
            return true;

        if (state[curAppFd]._response.length() == 0) {
            XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: empty response.");
            return false;
        }
    }

    // Try to write the response
    int curBytesWritten = scheduler->sendBytes(state[curAppFd]._response.c_str(),
                                               state[curAppFd]._response.length(),
                                               0, 0, true, curAppFd);

    if (curBytesWritten <= 0) {
        XmlRpcUtil::error("XmlRpcServerConnection::writeResponse: write error.");
        return false;
    } else {
        state[curAppFd]._bytesWritten += curBytesWritten;
    }

    XmlRpcUtil::log(3,
                "XmlRpcServerConnection::writeResponse: wrote %d of %d bytes.",
                state[curAppFd]._bytesWritten, state[curAppFd]._response.length());

    // Prepare to read the next request
    if (state[curAppFd]._bytesWritten == int(state[curAppFd]._response.length())) {
        state[curAppFd]._header = "";
        state[curAppFd]._request = "";
        state[curAppFd]._response = "";
        state[curAppFd]._connectionState = READ_HEADER;
    }

    return state[curAppFd]._keepAlive; // Continue monitoring this source if true
}


Member Data Documentation

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

bool XmlRpcInterface::limitAccess [protected]

Definition at line 100 of file XmlRpcInterface.h.

Referenced by initializeApp(), and isPrivileged().

unsigned int XmlRpcInterface::mtu [protected]

Definition at line 47 of file XmlRpcInterface.h.

Referenced by initializeApp().

Pointer to the P2PNS module.

Definition at line 138 of file XmlRpcInterface.h.

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

cMessage* XmlRpcInterface::packetNotification [protected]

Definition at line 49 of file XmlRpcInterface.h.

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


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