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

LSL Wiki : LibraryCBOutboundRequestRelay

HomePage :: PageIndex :: RecentChanges :: RecentlyCommented :: UserSettings :: You are ia360925.us.archive.org
// Provides an interface for communicating requests to the server.

// Copyright (C) 2005-2006  Francisco V. Saldana
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
// 
// Francisco V. Saldana can be contacted using his email account 
//  username: dressedinblue, at domain: gmail.com
// and in Second Life by IMming Christopher Omega


// ====================== XMLRPC request constants: ====================== \\
    // Sent by the client to the server when the server polls
    // and the client has no data to send.
    integer NO_REQUESTS     = 5000;
    
    // Sent by the server to the client when a poll occurs.
    integer SERVER_POLL     = 6000;
    
    // Sent by client to server requesting that the server stop polling.
    integer STOP_POLLING    = 6001;
    
    // Sent by server to client that tells client that the RPC string contains multiple command seperated
    // by COMMAND_SEPERATOR.
    integer MULTI_COMMAND   = 6002;
    
    // Sent by server to client requesting that the client restart.
    integer TERMINAL_RESET  = 6003;

    // Sent by the client to the server (or external entity) requesting a 
    // piece of content:
    integer GET_CATEGORY        = 7001; // String value: catagory requested
    integer GET_NOTECARD        = 7002; // String value: Notecard name requested.
    integer GET_PREV            = 7003; // String value: ""
    integer GET_NEXT            = 7004; // String value: ""
    integer GET_KEYWORD_SEARCH  = 7005; // String value: Keyword requested.
    integer GET_SUMMARY         = 7007;
    integer GET_BUTTON          = 7008;
    
    // Sent by the server to the client, between MENU_BEGIN and MENU_END
    // requesting that it display text.
    integer SET_CATEGORY        = 8001; // String value: Catagory name to display.
    integer SET_NOTECARD        = 8002; // String value: Notecard name to display.
    integer SET_PREV            = 8003; // String value ignored
    integer SET_NEXT            = 8004; // String value ignored.
    integer SET_KEYWORD_SEARCH  = 8005; // String value ignored.
    integer SET_TEXT            = 8006; // String value: any text.
    integer SET_SUMMARY         = 8007;
    integer SET_BUTTON          = 8008;
    
    // Sent by the server to the client specifying the start 
    // and end of a menu.
    integer MENU_BEGIN  = 9001; // String value: Menu title
    integer MENU_END    = 9002;
// ====================== /XMLRPC request constants ====================== \\

string CATEGORY_SEPERATOR = "]_[";

string SERVER_EMAIL_ADDRESS = "slpl@zerocubed.com";
string STARTUP_MESSAGE_COMMAND = "Register";
string SHUTDOWN_MESSAGE_COMMAND = "Shutdown";
string MESSAGE_SUBJECT = "SL Library Terminal";
string PROTOCOL_VERSION = "1.0";

string TYPE_INBOUND = "INBOUND";
string TYPE_OUTBOUND = "OUTBOUND";

// The number of scripts that have RPC channels.
integer RPC_SCRIPT_COUNT = 2;

list rpcChannelKeys;
list rpcChannelTypes;
// ========== For method invocation ==========
string randomStr(string chars, integer len) {
    integer numChars = llStringLength(chars);
    string ret;
    integer i;
    for (i = 0; i < len; i++) {
        integer randIndex = llFloor(llFrand(numChars));
        ret += llGetSubString(chars, randIndex, randIndex);
    }
    return ret;
}

string SEPERATOR_CHARS = "`~!@#$%^&*()-_+[]{}\|'\";/?.>,<";
integer SEPERATOR_LEN  = 3;
string dumpList2String(list src) {
    // Generate a seperator not present in any of the
    // elements in the list.
    string chars = (string) src; // Squashes all elements together.
    string seperator;
    do {
        seperator = randomStr(SEPERATOR_CHARS, SEPERATOR_LEN);
    } while (llSubStringIndex(chars, seperator) != -1);
    return seperator + llDumpList2String(src, seperator);
}

list parseStringKeepNulls(string src) {
    // The seperator should be the first SEPERATOR_LEN
    // characters in the string.
    return llParseStringKeepNulls(llDeleteSubString(src, 0, SEPERATOR_LEN - 1),
        [llGetSubString(src, 0, SEPERATOR_LEN - 1)], []);
}

callMethod(integer callId, string methodName, list parameters) { 
    llMessageLinked(LINK_THIS, callId,
        dumpList2String(parameters), methodName);
}

returnValue(string methodName, integer methodIdentifyer, list value) {
    llMessageLinked(LINK_THIS, methodIdentifyer, 
        dumpList2String(value), methodName + "_ret");
}
// =============================================

trigger_displayStatusMessage(string msg) {
    callMethod(0, "displayStatusMessage", [msg]);
}

trigger_sendRpcData(integer iData, string sData) {
    callMethod(0, "sendRpcData", [iData, sData]);
}

trigger_sendRpcControlData(integer iData, string sData) {
    callMethod(0, "sendRpcControlData", [iData, sData]);
}

integer getOutboundChannelReturnVal;
trigger_getOutboundChannel() {
    getOutboundChannelReturnVal = (integer) llFrand(1824214);
    callMethod(getOutboundChannelReturnVal, "getOutboundChannel", []);
}

integer getInboundChannelReturnVal;
trigger_getInboundChannel() {
    getInboundChannelReturnVal = (integer) llFrand(29481);
    callMethod(getInboundChannelReturnVal, "getInboundChannel", []);
}

integer sendEmailDataReturnVal;
trigger_sendEmailData(string address, string subject, string message) {
    sendEmailDataReturnVal = (integer) llFrand(119333);
    callMethod(sendEmailDataReturnVal, "sendEmailData", [address, subject, message]);
}

trigger_pong(string moduleName) {
    callMethod(0, "pong", [moduleName]);
}

sendServerEmail(string command, list commandParams) {
    commandParams = [PROTOCOL_VERSION, command] + commandParams;
    trigger_sendEmailData(SERVER_EMAIL_ADDRESS, MESSAGE_SUBJECT, llDumpList2String(commandParams, " "));
}

integer trySend() {
    // If we have keys from all rpc scripts:
    if (llGetListLength(rpcChannelKeys) == RPC_SCRIPT_COUNT) {
        // This email is in the format:
        // <version> <terminalKey> OUTBOUND <rpcKey> INBOUND <rpcKey>
        list emailParams = [
            "TerminalUUID",
            llGetKey()];
        
        integer i;
        for(i = 0; i < RPC_SCRIPT_COUNT; i++) {
            emailParams += llList2String(rpcChannelTypes, i);
            emailParams += llList2String(rpcChannelKeys, i);
        }
        sendServerEmail(STARTUP_MESSAGE_COMMAND, emailParams);
        returnValue("connectionStartup", startupCommandCallId, [TRUE]);
        return TRUE;
    }
    return FALSE;
}

integer startupCommandCallId;
string this;
default {
    state_entry() {
        this = llGetScriptName();
    }
    
    link_message(integer sender, integer num, string parameters, key methodName) {
        if (methodName == "connectionStartup") {
            // Method signature:
            // integer connectionStartup()
            startupCommandCallId = num;
            state starting;
        } else if (methodName == "ping") {
            list paramList = parseStringKeepNulls(parameters);
            // Method signature:
            // ping(string moduleName)
            string moduleName = llList2String(paramList, 0);
            if (moduleName == this)
                trigger_pong(this);
        }
    }
}

state starting {
    state_entry() {
        trigger_getInboundChannel();
        trigger_getOutboundChannel();
        rpcChannelKeys = rpcChannelTypes = [];
    }
    
    link_message(integer sender, integer callId, string parameters, key methodName) {
        if (methodName == "getInboundChannel_ret" && callId == getInboundChannelReturnVal) {
            list paramList = parseStringKeepNulls(parameters);
            // Method sig:
            // getInboundChannel_ret(key channel)
            key rpcChan = (key) llList2String(paramList, 0);
            rpcChannelKeys += rpcChan;
            rpcChannelTypes += TYPE_INBOUND;
            if(trySend())
                state started;
        } else if (methodName == "getOutboundChannel_ret" && callId == getOutboundChannelReturnVal) {
            list paramList = parseStringKeepNulls(parameters);
            // Method sig:
            // getOutboundCHannel_ret(key channel)
            key rpcChan = (key) llList2String(paramList, 0);
            rpcChannelKeys += rpcChan;
            rpcChannelTypes += TYPE_OUTBOUND;
            if (trySend())
                state started;
        }
    }
}

state started {
    link_message(integer sender, integer num, string parameters, key methodName) {
        if (methodName == "requestMenuCategory") {
            list paramList = parseStringKeepNulls(parameters);
            // Method signature:
            // requestMenuCategory(integer ID)
            integer id = (integer) llList2String(paramList, 0);
            trigger_sendRpcData(GET_CATEGORY, CATEGORY_SEPERATOR + (string) id);
            trigger_displayStatusMessage("Sent data to server, waiting for reply...");
        } else if (methodName == "requestMenuSummary") {
            list paramList = parseStringKeepNulls(parameters);
            // Method signature:
            // requestMenuSummary(integer ID)
            integer id = (integer) llList2String(paramList, 0);
            trigger_sendRpcData(GET_SUMMARY, CATEGORY_SEPERATOR + (string) id);
            trigger_displayStatusMessage("Sent data to server, waiting for reply...");
        } else if (methodName == "requestMenuKeywordSearch") {
            list paramList = parseStringKeepNulls(parameters);
            // Method signature:
            // requestKeywordSearch(string keywords)
            string keywords = llList2String(paramList, 0);
            trigger_sendRpcData(GET_KEYWORD_SEARCH, keywords);
            trigger_displayStatusMessage("Sent data to server, waiting for reply...");
        } else if (methodName == "connectionShutdown") {
            // Method signature:
            // requestPollingShutdown()
            list emailParams = [
                "TerminalUUID",
                llGetKey()];
            sendServerEmail(SHUTDOWN_MESSAGE_COMMAND, emailParams);
            state default;
        } else if (methodName == "connectionStartup") {
            // Method signature:
            // integer connectionStartup()
            startupCommandCallId = num;
            state starting;
        } else if (methodName == "ping") {
            list paramList = parseStringKeepNulls(parameters);
            // Method signature:
            // ping(string moduleName)
            string moduleName = llList2String(paramList, 0);
            if (moduleName == this)
                trigger_pong(this);
        }
    }
}


LibraryContentBrowser
There is no comment on this page. [Display comments/form]