Don't click here unless you want to be banned.

LSL Wiki : XMLRPC

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are ec2-204-236-235-245.compute-1.amazonaws.com

What is XML-RPC?


XML-RPC (remote procedure calling) is a specification and set of implementations that allow software running on disparate operating systems running in different environments to make procedure calls over the Internet.

Its remote procedure calling uses HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed, and returned.

The URL for sending XML-RPCalls to a script is: http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi

The name for a request is: llRemoteData

Parameters must be a struct(ure) consisting of : string Channel, string StringValue, int Int[[value Value]] (see example requests below)

If "XML-RPC" is simply too long to type out and you feel you must abbreviate it, don't call it "XML", call it "RPC". Describe it by what it does, not by the data format it uses. Everything uses XML now anyway.


Event:
remote_data


Functions:
llOpenRemoteDataChannel Open a channel
llCloseRemoteDataChannel Close the channel (Doesn't actually work.)
llSendRemoteData Send data/request (Doesn't actually work.)
llRemoteDataReply Reply to a request
llRemoteDataSetRegion Reregister channels upon moving into another sim (Doesn't actually work.)


Constants:
REMOTE_DATA_CHANNEL successful llOpenRemoteDataChannel
REMOTE_DATA_REQUEST request received
REMOTE_DATA_REPLY reply received

Warning
The performance of XML RPC has been steadily degrading over the last year. If you need reliable communications that originate from outside of SL you're likely better off polling with HTTP requests. XML RPC requests are typically taking 60 seconds or more to complete these days, and not completing at all quite frequently. For more information, search for XMLRPC on the scripter forums.

IMPORTANT IMPLEMENTATION NOTES:
The current implementation of XML-RPC only allows ONE request to be queued on the front-end server (xmlrpc.secondlife.com) at a time. Any additional requests to the same data channel overwrite any pending one. This has serious ramifications for the design of XML-RPC communications where the in-world object could receive requests faster than it can respond to them. In addition, the 3-second delay in llRemoteDataReply exacerbates this problem even more.

The observed issue is this: if you send multiple quick requests to an in-world object via XML-RPC, one which is scripted to perform some processing and then return a response (via llRemoteDataReply), there is a potential for earlier requests to get lost on the front end server (they still should generate remote_data events, though), and have the response meant for an earlier request end up being passed back to a later one, while the earlier requests will time out back at your external application.

As a result, if you intend to do any serious work with XML-RPC, you will have to design your external client application to manually serialize all requests to each individual RPC channel. That means you have to wait for a response from the previous request before you attempt to send the next one. If you don't care about receiving responses, then this problem is not an issue, as all requests seem to get passed on to the script, regardless of the queueing issue.

Also note that there is NO way to get around the 3-second delay for llRemoteDataReply; you cannot use the multiple-slave-comm-script trick, because XML-RPC channels are *script-specific*, NOT *object-specific*.

For more information, see these forum threads here and here.

-- TalarusLuan

Like llRemoteDataReply, the length of the sdata field passed by the remote_data event is also limited to 254 bytes

The implementation is at the sim level. When moving across region borders the channel must be re-established in the new region. This can be done in a changed event. See the notes under llOpenRemotedataChannel for further details.

-- KeikoRau

Examples


LSL
Example Request
Example Response



LSL Example:
// XML-RPC example

key     gChannel; // my llRemoteData channel

DEBUG(list out) { // output debug info
    llSay(0, llList2CSV(out));
}

default { // initialize XML-RPC
    state_entry() {
        llOpenRemoteDataChannel(); // create an XML-RPC channel
        // this will raise remote_data event REMOTE_DATA_CHANNEL when created
    }

    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) {
        if (type == REMOTE_DATA_CHANNEL) { // channel created
            DEBUG(["Channel opened", "REMOTE_DATA_CHANNEL", channel, message_id, sender, ival, sval]);
            gChannel = channel;
            llSay(0, "Ready to receive requests on channel \"" + (string)channel +"\"");
            state go; // start handling requests
        } else DEBUG(["Unexpected event type", type, channel, message_id, sender, ival, sval]);
    }
}

state go { // handle requests
    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) {
        if (type == REMOTE_DATA_REQUEST) { // handle requests sent to us
            DEBUG(["Request received", "REMOTE_DATA_REQUEST", channel, message_id, sender, ival, sval]);
            // handle request
            if (sval == "How are you?") { // we do something special on that string parameter
                // send a reply to this request, referencing the senders message id
                llRemoteDataReply(channel, message_id, "Fine, thanks!", 1);
            } else { // IMPORTANT: a reply MUST always be sent
                llRemoteDataReply(channel, message_id, "", 0);
            }
        } else DEBUG(["Unexpected event type:", type, channel, message_id, sender, ival, sval]);
    }

    state_exit() {
        llCloseRemoteDataChannel(gChannel); // clean up when you no longer want to handle requests
    }
}



Example request:
<?xml version="1.0"?>
<methodCall>
    <methodName>llRemoteData</methodName>
    <params>
        <param>
            <value>
                <struct>
                    <member>
                        <name>Channel</name>
                        <value><string>4a250e12-c02e-94fb-6d2f-13529cbaad63</string></value>
                    </member>
                    <member>
                        <name>IntValue</name>
                        <value><int>0</int></value>
                    </member>
                    <member>
                        <name>StringValue</name>
                        <value><string>test</string></value>
                    </member>
                </struct>
            </value>
        </param>
    </params>
</methodCall>



Example response:
<?xml version="1.0"?>
<methodResponse>
    <params>
        <param>
            <value>
                <struct>
                    <member>
                        <name>Channel</name>
                        <value><string>6df57cf4-68b7-b958-5b6c-10cb9f2fa391</string></value>
                    </member>
                    <member>
                        <name>StringValue</name>
                        <value><string>Monkey</string></value>
                    </member>
                    <member>
                        <name>IntValue</name>
                        <value><int>0</int></value>
                    </member>
                </struct>
            </value>
        </param>
    </params>
</methodResponse>


Want to complain about XML-RPC's implementation? Have you come up with an idea for a better solution? See XML-RPC Discussion.

For XML-RPC implementations in a variety of languages, see XMLRPCImplementations.

LuccaKitty: The above example requests and responses are fine if you already have a simple http post app, but that wasn't the case for me, i had to construct an entire http post packet from scratch. I'm posting the http post packet in it's entirety below. This will be useful if you intend on sending raw packets to make a quick and dirty client app. Maybe needs a refactoring. I apologise for the code scrolling off the example box. When generating said packet, I was attempting to keep the actual amount of data to a minimum to conserve bandwidth. I would format the packet, except that you'll notice Content-Length: 411. If I refactor it, the packet is no longer actually usable, as it changes the content length of the request. Hope this helps someone.


Example request entire raw packet:
POST /cgi-bin/xmlrpc.cgi HTTP/1.0
Host: xmlrpc.secondlife.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 411

<?xml version="1.0"?><methodCall><methodName>llRemoteData</methodName><params><param><value><struct><member><name>Channel</name><value><string>51ef73f1-14d6-a6c3-b6b6-dbacaa4127d5</string></value></member><member><name>IntValue</name><value><int>11261979</int></value></member><member><name>StringValue</name><value><string>happy birthday</string></value></member></struct></value></param></params></methodCall>

Example PHP script showing how to put together a http-post: https://wiki.secondlife.com/wiki/Category:LSL_XML-RPC#php

Links
current XML-RPC specification
XML-RPC.com


Functions | Communications | XML-RPC Discussion | XML-RPC Implementations Despammed
There are 9 comments on this page. [Display comments/form]