Prowler

From Second Life Wiki
Revision as of 00:33, 4 February 2012 by Kira Komarov (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Created by Kira Komarov.

Introduction

We have gone through some possibilities of extracting data from Second Life and, more recently, a system to centralize messages. Our first exploration was syslog which, albeit a standard of log centralization, it proves to be inflexible and frequently insecure. Newly, it has been replaced with other, more modern counterparts. However, they are still not portable enough, considering that Windows users will be forced to use Cygwin or similar.

Furthermore, we were looking for something that is truly portable. We had something in mind similar to the PUSH feature on modern devices. For users who are unfamiliar with the PUSH feature of modern devices, it is really a rebrand of the good old Fetchmail with a prettier interface. It is not really a PUSH but rather a PULL. Very misleading; very profitable that confusion.

Puns aside, we bottom lined it an wanted a method of delivering a message (a string, if you will) from Second Life to mobile devices regardless where you may find yourself in the world. The applications are numerous, we guess, starting from in-game messaging systems and more advanced features which will be made more concrete by the end of this article page.

After some searches, we stumbled onto something called Prowl, which apparently is a pusher for iOS devices. Behind the scenes though, given their REST (another re-brand of HTTP-standard-GET-and-POST-headers, wth?) API, any HTTP client capable of doing GET or POST is able to both store messages on the Prowl servers, as well as retrieve them (fetchmail, pretty much).

The system probably work like the following:

  • A computer or a client capable of HTTP, pushes a "message" which can be anything to the Prowl servers.
  • A mobile device (may be a computer as well, why not) after connecting to the Internet, runs a thread in the background that fetches the messages from the Prowl servers. If there is a new message there, it usually pops it up as a notification.

The Prowl name is not incidental, it is in fact an extension to what Macintosh users may know as Growl (another nice rebrand of syslog, meant for end-user applications this time). The latter is used on a computer to send messages across the network. Given multiple machines, it is convenient to have all the notifications centralized on your main working machine. Growls does just that an syslog used to do that back when the giants roamed the earth for massive datacentres.

The YouTube video below is a demonstration using the scripts you will find further on of sending a message from a Second Life primitive to an iPad. For completeness, we use Veency to access the iPad via VNC in order to shoot the clip. The soundtrack is called Corruption by John Molloy (Magnetic Scrolls).

YouTube Video

Set-up

To use this system in its basic form, you will need to:

  • Sign-up on Prowl with a username which we will call USER and a password we will call PASS (don't register with that please, it's just... immature).
  • Log-in with the username and password you signed-up with and navigate to Prowl's API Key generator and generate a new API key.
  • If you are on an iDevice, you will need to purchase (or steal, up to you, we don't want to hear about it, nor do we care - we do however recommend purchasing though since you will get proper updates and if you do use this on a regular basis, even combined with Growl, which is free, you will love this application) the Prowl: Growl Client from the AppStore.
  • Log-in to Prowl from your iDevice.
  • Create a new primitive in Second Life and dump the scripts below inside it.
  • Edit the [K] Injector script below and change USER, PASS and API_KEY to the username, password and key that you generated at Prowl's API Key generator.
  • To test, you can touch the primitive you created and an llTextBox dialog will pop-up (Imprudence users beware, it is still not implemented) which will ask for a message.
  • Type your message and if you followed the previous successfully, you should see that message appear on screen.

Additionally, you may also customize the EVENT, DESCRIPTION and APPLICATION to something that suits your needs. Those fields assume that an application, triggering an event with a description is sending the message. However, given that you are sending this from Second Life, those fields could perhaps be some description of your build, or the location of it, or visitors on your simulator.

Limitations

The Prowl API mentions limitations to be at:

IP addresses are limited to 1000 API calls per hour which begins from the start of the first call.

We do not think that more than that is really necessary and if you do need to take out more than 1000 events per hour, then you probably would want a separate database to store them.

The following limitations apply to the REST(w.t.h. is REST anyways? they're just POST parameters for phrack's sake) fields:

apikey -> unlimited (well, duh)
application -> 256 characters
event -> 1024 characters
description -> 10000 characters.

As you can see, the system is quite generous: 10000 characters is quite a bit.

Please bear in mind, that the messages should be escaped with llEscapeURL.

Security

Wizardry and Steamworks is not affiliated in any way with Prowl. We believe it is a nice feature! However, bear in mind that this relies on a 3rd party service to store your notifications. We cannot confirm nor deny if the folks at prowl do anything dodgy with your data. If your messages are of the utmost privacy (like, if you are one of those peeps without a facebook account), then this is probably not recommended. You document yourself, you decide whom to trust. We just provide the mechanism of using it (the only thing we will ever be interested in).

The calls between LSL and Prowl are done over HTTPS meaning (assuming) that the traffic between the script and Prowl is encrypted.

Code

Only the [K] Prowl script is necessary if you want to integrate this script into a bigger build. The [K] Prowl script listens for linked messages and you can access them by sending a comma-separated list of parameters.

Two parameters are mandatory:

PROWL_API_KEY -> your api key (mandatory)
PROWL_APPLICATION -> some name you want to give to your message (appears as the Title usually) (mandatory)

The remaining two are optional:

PROWL_EVENT -> some event name, anything you wish
PROWL_DESCRIPTION -> this is usually a large portion of text, anything you wish

An example link-message would look like this (assuming that the two scripts are in the same primitive): <lsl> llMessageLinked(LINK_THIS, comChannel, "PROWL_API_KEY,6f5902ac237024bdd0c176cb93063dc4,PROWL_APPLICATION,Prowler,PROWL_EVENT,I got tickled!,PROWL_DESCRIPTION,Stop that!", id); </lsl> which will pop-up something like the following on a device:

+----------------+
|    Prowler     |
| I got tickled! |
|   Stop that!   |
+----------------+

The only observation is that usually the title takes precedence, then the event name and then the message which is usually much longer (may be) than the previous two.

[K] Prowl

This is the actual Prowl module which could be integrated in a larger build.

<lsl> ////////////////////////////////////////////////////////// // [K] Kira Komarov - 2011, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // //////////////////////////////////////////////////////////

key kReq = NULL_KEY; list pLoad = [];

default {

   link_message(integer sender_num, integer num, string str, key id) {
       integer cha = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
       if(num != cha) return;
       pLoad = [];
       pLoad = llCSV2List(str);
       state notify;
   }
   
   on_rez(integer num) {
       llResetScript();
   }

}

state notify {

   state_entry() {
       string sLoad = "";
       integer itra=llGetListLength(pLoad)-1;
       do {
           string in = llList2String(pLoad, itra);
           if(in == "PROWL_API_KEY") {
               sLoad += "&" + "apikey=";
               sLoad += llEscapeURL(llList2String(pLoad,itra+1));
               jump add;
           }
           if(in == "PROWL_APPLICATION") {
               sLoad += "&" + "application=";
               sLoad += llEscapeURL(llList2String(pLoad,itra+1));
               jump add;
           }
           if(in == "PROWL_EVENT") {
               sLoad += "&" + "event=";
               sLoad += llEscapeURL(llList2String(pLoad,itra+1));
               jump add;
           }
           if(in == "PROWL_DESCRIPTION") {
               sLoad += "&" + "description=";
               sLoad += llEscapeURL(llList2String(pLoad,itra+1));
               jump add;
           }

@add;

       } while(--itra>=0);
       kReq = llHTTPRequest("https://api.prowlapp.com/publicapi/add", [HTTP_METHOD,"POST",HTTP_MIMETYPE,"application/x-www-form-urlencoded"], sLoad);
       
   }
   http_response(key id, integer status, list metadata, string body) {
       if(kReq != id) return;
       state default;
   }

} </lsl>

[K] Injector

This is just a test script that delivers link messages but feel free to expand on it.

Please replace in the code below:

PROWL_API_KEY -> your API key
PROWL_APPLICATION -> anything under 256 characters
PROWL_EVENT -> anything under 1024 characters
PROWL_DESCRIPTION -> anything under 10000

in the llMessageLinked call below.

<lsl> ////////////////////////////////////////////////////////// // [K] Kira Komarov - 2011, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // //////////////////////////////////////////////////////////

integer comChannel = 0;

default {

   touch_start(integer total_number) {
       comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
       llListen(comChannel, "", llGetOwner(), "");
       llTextBox(llGetOwner(), "\nPlease enter a test-string to broadcast to growl-enabled devices:\n", comChannel);
   }
   listen(integer channel, string name, key id, string message) {
       llMessageLinked(LINK_THIS, comChannel, "PROWL_API_KEY,6f5902ac237024bdd0c176cb93063dc4,PROWL_APPLICATION,Prowler,PROWL_EVENT,Tickled!,PROWL_DESCRIPTION," + message, id);
   }

} </lsl>