Skip to content

Figuring out your online status, revisited

Three years ago, when I was learning how to integrate Second Life with external web servers in the summer of 2004, I posted some code for figuring out your online status from a website, blog, forum, etc. The tricky bit at the time was that XML-RPC requires a ‘channel’, which is created from scratch every time you register an object to handle XML-RPC calls, but this channel changes over time as sims get rebooted, or SL gets upgraded, or the asset server goes down, etc.

XML-RPC only allows queries from outside to an in-world object (but you can return an answer); in those days, the only way to store that channel on your webserver, to make sure you knew where to send the XML-RPC messages, was to send the channel ID by email. Parsing mails on a webserver, however, is an option that most low-cost web hosting services do not give you; it’s also not trivial, and very often requires you to have mail set up correctly (also, forget doing that under a Windows server). I just sent the channel to my own email address and manually changed it on my website.

Since Linden Lab introduced llHTTPRequest(), things are much easier. Using it, you can also call a webserver from any object — so now you have a simple and easy way to inform your website that the channel ID has changed! The PHP code I had was also designed for PHP4, using an external XML-RPC library that was quite easy to use. PHP4 has been made obsolete now, so it’s time to change the code to adapt. For me, it meant finding a new XML-RPC library. PHP5 has one, PEAR has another, and a lot of those are around, but almost all are hugely complex and, in some cases, you need to install it first, which may not be an option for the low-end hosting services. By chance, I was browsing through WordPress to see what library they were using — and I found one that works well under PHP4 and 5, comes with every WordPress installation, and it’s even simpler to use than Keith Devens‘ own, who never troubled himself to upgrade his library to PHP5. So here follows the code. The first bit is the LSL script to place in your object. As you can see, it follows the same model as my 2004 code pretty closely. If your object changes XML-RPC channel by any chance, just reset it or rez it again. Note that the webserver will always store the channel ID from the last object rezzed (but all should retrieve the same information from LL’s database servers, so it’s irrelevant).

// Code by Gwyneth Llewelyn to show online status and let it
// be retrieved by external XML-RPC calls

// Global Variables
key avatar;
string avatarName;
string onlineStatus = "status unknown"; // preserve it
key onlineStatusRequest;
key webResponse;    // we send the RPC channel ID to the webserver

default
{
    state_entry()
    {
        llSetTimerEvent(60.0);  // call a timer event
                        // every 60 seconds.
        avatar = llGetOwner();
        avatarName = llKey2Name(avatar);
        llOwnerSay("Registering with RPC server and retrieving user data from database server…");
        llOpenRemoteDataChannel()// this sets the object up to accept external XML-RPC calls
    }   

    on_rez(integer startParam)
    {
        llResetScript();
    }

    timer()
    {
        // Every 60 seconds, retrieve the online status from the SL database server
        onlineStatusRequest = llRequestAgentData(avatar, DATA_ONLINE);
        llSetText(avatarName + " is " + onlineStatus, ZERO_VECTOR, 1.0);    // set the hover text
    }

    dataserver(key queryid, string data)
    {
        // this is what SL returns to us when we call llRequestAgentData()
        if (queryid == onlineStatusRequest) // check if it’s the correct request
        {
            if (data == "1")    // online status is just 0 or 1
                onlineStatus = "online";
            else
                onlineStatus = "offline";
        }
    }

    remote_data(integer event_type, key channel, key message_id, string sender, integer idata, string sdata)
    {
        if (event_type == REMOTE_DATA_CHANNEL)
        {
            // SL has set up a channel for the XML-RPC calls
            llOwnerSay("Channel id "+(string)channel);
            llOwnerSay("Sending channel id to web server…");
            // We’ll save it, by sending it to our server
            webResponse = llHTTPRequest("http://insert.your.domain.here.tld/save-channel.php",
                        [HTTP_METHOD, "POST",
                        HTTP_MIMETYPE, "application/x-www-form-urlencoded"],
                        "channel=" + (string)channel);
        }
        if (event_type == REMOTE_DATA_REQUEST)
        {
            // This is a call made from our web site/blog asking us for the online status
            llRemoteDataReply(channel, message_id, onlineStatus, idata);
        }
    }

    http_response(key request_id, integer status, list metadata, string body)
    {
        if (request_id == webResponse)
        {
            if (status == 200)  // we’ll get a 200 OK status if the web server stored the XML-RPC channel correctly
                llOwnerSay("Channel id successfully saved");
            else llOwnerSay("Webserver error " + (string)status + ": " + body);
        }
    }
}

Now it’s time to take a look at the web-side code. The first bit is the handler for the new channel. I’ve done a quick-and-dirty thingy that simply writes to a local file. Since this is meant to be used inside things like your own hosted blogs/websites/forums, just pick a local directory that is writable and use it. For WordPress, I’m using the uploads directory and the filename I’ve picked was channels.inc. Just copy and paste the following code into a file called save-channel.php where your webserver can find it:

<?php
if ($_REQUEST[‘channel’])
{
    include(‘./wp-config.php’);
    $filename = ABSPATH . ‘wp-content/uploads/channel.inc’;
   
    $fd = fopen($filename, ‘w’);
    if (fwrite($fd, $_REQUEST[‘channel’]) === FALSE)
    {
        header("HTTP/1.0 503 Service Unavailable");
        echo "File $filename not writeable – channel not saved";
    }
    else
    {
        fclose($fd);
        header("Content-type: text/plain; charset=utf-8");
        echo "Channel " . $_REQUEST[‘channel’] . " saved.";
    }
}
else
{
    header("HTTP/1.0 405 Method Not Allowed");
    echo "No channel specified";
}
?>
 

And finally comes the last bit — adding the relevant code on your site/blog/forum to check if you’re in-world or not. This requires including class-IXR.php, which is available from Incutio. However, the WordPress guys have continued to update this XML-RPC library and have a more recent version.

<?php
include_once(ABSPATH . WPINC . ‘/class-IXR.php’);

$client = new IXR_Client(‘http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi’);

$payload["Channel"] = file_get_contents(ABSPATH . ‘wp-content/uploads/channel.inc’);
$payload["IntValue"] = 0;
$payload["StringValue"] = "online status";

print "I am ";
if ($client->query(‘llRemoteData’, $payload))
{
    $response = $client->getResponse();
    print $response["StringValue"] . " in Second Life.";
}
else
{
    print "having problems contacting RPC server…";
}
?>
 

Enjoy!

Related Posts

Readers who viewed this page, also viewed:

Comments

  1. Virgix October 24, 2007

    Gwyneth,
    Nice job, very interesting.

    But note that in the SL script there is a little bug:
    the line [if (status = 200) // we’ll...]
    should be if (status == 200) // we’ll...]

    However, many tks for your great job!

  2. Gwyneth Llewelyn October 25, 2007

    Oops. You’re so right! Thanks for spotting the bug!

  3. Kevin Oto November 5, 2008

    Parse error: syntax error, unexpected T_VARIABLE in /home/kevinoto/public_html/online.php on line 3 I am getting this. I am not sure how to fix it. Thanks

  4. Gwyneth Llewelyn March 28, 2009

    Kevin, which of the two PHP scripts gives that error to you?

  5. Kevin Oto April 3, 2009

    On the online.php that shows your online or not i get Parse error: syntax error, unexpected T_CLASS in /home/searchi9/public_html/web3/online.php on line 2
    and on the save-channel.php is giving me
    Parse error: syntax error, unexpected ‘/’ in /home/searchi9/public_html/web3/wp-content/uploads/save-channel.php on line 4

    And also are you going to remake this when http-in is in the main version? One of my scripter friends told me they are going to take out xml-rpc when http-in is in.

  6. Gwyneth Llewelyn April 3, 2009

    Ah… I wonder if you’re using this script on a WordPress blog? :)

    Because if you aren’t, you’ll need to download class-IXR.php, install it somewhere, and rewrite the whole code to point the paths properly to it. Or, well, use any other PHP XML-RPC packages (there are a lot of them; Incutio’s IXR just happens to be small, efficient, and very simple to us; these days, most installations of PHP also include XML-RPC classes, which are probably faster since they’re C libraries :) ).

    Oh yes, I most definitely will use http-in as soon as it’s available (hopefully still in 2009!). LL will slowly phase out XML-RPC — and not abruptly — since their own XstreetSL.com web shop uses XML-RPC profusely, and a hundred thousand people use that every day. That’s a lot of code to replace!

  7. Kevin oto April 3, 2009

    I have it install on my wordpress. So i don’t really know whats up with that.

Trackbacks

There are no trackbacks on this entry.

blog comments powered by Disqus

Status Updates

My images

Second Anniversary of Locus AmoenusLocus Amoenus Anniversary CeremonyPolitics doesn't need to be taken so serious...Preview of current work at the Lisbon 1755 projectKaseido Quandry at the Representative MeetingWind-blown on the Sun Castle
Gwyneth Llewelyn is offline in Second Life.
Digg! Listed on BlogShares Site Meter EgoSurf for Gwyneth Llewelyn