Add llMessageLinkedScript( integer link, string script_name, integer num, string str, key id );
tracked
Woolfyy Resident
Same as llMessageLinked() but addressing directly the named script to stop losing time extra checking each script with link_message(). That way it would open the path to structured / modular programming and better architectured / readable scripts, in spite of overloading scripts with things having nothing to do with each other and having spaghetti programmers always bragging because they are lacking memory.
Log In
Spidey Linden
Merged in a post:
[Feature Request] Protected/Filtered/Targeted Link Messaging
Lucia Nightfire
Over the years, there have been requests filed for the ability to have script targeting link messaging, to allow secure communication between links and to reduce event triggering in all scripts that have link_message() events.
The following functions facilitate this need:
integer llSetScriptLinkMessagePass(string pass);
sets pass as a script property (not a prim property)
returns 0 if no change
returns 1 if pass is updated
pass is a null string script property by default (upon injection and reset)
pass uses the same encryption that protected LSD r/w uses
llMessageLinkedProtected(integer link, integer num, string str, key id, string pass, list options);
triggers link_message() events in scripts with matching set pass
- Allows script targeted link messaging
- Allows secure link message communication
- Allows reduction in unwanted link message event triggering
llMessageLinked() sends a null string for pass by default in the background
The two key backend changes needed to bring this to fruition is the pass data being added to link messaging and the event scheduler checking the pass script property of any target links containing scripts with active link_message() events. I believe this to be trivial to implement.
Linkset Data cannot facilitate this need.
linkset_data() is too prominent and triggers with most LSD usage.
Attempting to negotiate downstream state changing to disable linkset_data() involves bytecode and communication overhead that we are already trying to avoid.
Nelson Jenkins
First, this would be useful to pair with a function like llDetectedScript to be able to ID where link messages come from. Yes, this could be sent "in-band", but that requires some messy code if you're already using the string and key and is subject to spoofing. Being able to safely identify the script that sent a link message in any circumstances would be a very handy debugging tool and would allow for at least some security in conjunction with llMessageLinkedScript.
Second, adding a long-winded use case for this, but one that hopefully will resonate a little with whoever handles these requests:
I have a simulated computer that uses scripts as individual programs in a basic multitasking environment through a heavily beefed-up XyText-like display (similar to IBM TopView from... 40 years ago). The scripts are started, stopped, and reset by a sort of kernel script that starts scripts only as they're "executed". As programs close or get backgrounded, the associated script is stopped, and if that program no longer exists in the process list, the script is also reset (programs can have multiple running instances despite using a single script, the kernel handles context switching depending on what's in the foreground).
The main reason for this is if you have 500 different programs installed for whatever reason, you don't have 500 different running scripts processing events and potentially causing resource conflicts all the time.
Currently, the only way any system calls can occur is by blasting a link message to all running scripts. (Linkset data is already used for the file system.) That's a performance issue first and foremost - every system call forces maybe a few dozen scripts to process the link message, even though only one script needs to do anything with it. But it is also a security problem - any running script, even one not part of the kernel, can trivially listen to all of the system calls on the system. In fact, the server forces them to, because it triggers an event for each one in every single running script!
This gets to be a big problem when doing anything that requires a lot of system calls, like fast display manipulation and filesystem access. Each time a cursor blinks on and off, that's 2 system calls generating a few dozen events for no reason. Loading a "file" off linkset data takes at least 10 link messages for complicated (but I promise valid and explainable!) reasons. If a program loads additional libraries, or there are a lot of services running in the background, those scripts cause even more lag, even if they're not actually doing anything most of the time.
Yes, this is all dramatically overcomplicating things. But ironically, that's the way it has to be done BECAUSE this function doesn't exist - if, for example, the file system driver just dumped a whole 8kB string via link message, it could stack-heap running scripts, including scripts that aren't involved in the file operation at all.
Being able to target link messages to specific scripts isn't a bulletproof security fix but it could make for a lot of really clever and efficient multi-script objects.
SamanthaTekcat Resident
I can definitely benefit from this where I need to have rez nodes set up but don't want to queue up the nodes I don't want to call up.
Assume there is the following Scripts in the following Example
Main.lsl
Rez Node 0.lsl
Rez Node 1.lsl
Rez Node 2.lsl
integer numberOfNodes = 3;
fireBurst()
{
for (integer i = 0; i < numberOfNodes; ++i)
{
llMessageLinkedScript(0,"Rez Node "+(string)i, 0, "",NULL_KEY);
llSleep(0.045);
}
}
Ratany Resident
That's what the integers are for. Script names can change, so what's the point.
You could add another integer as parameter, or another string that can be set to anything, including the script name. You can already transfer a list that contains the information which script has send the message. If I needed that, I'd use an integer because that saves memory and is faster to compare than a string.
If you're creating convoluted code that's difficult to read and unmaintainable, adding more parameters and functions will be counter productive. I would downvote this.
Nelson Jenkins
Ratany Resident That still triggers an event in every other script in the same prim. If you're worried about the script name changing - which, I should add, still can't be done via LSL anyway - figure out a name exchange mechanism, big deal.
Giving people the opportunity to optimize their code a little better doesn't harm anyone else in the slightest, no need to "downvote" this.
Spidey Linden
tracked
Issue tracked. We have no estimate when it may be implemented. Please see future updates here.
Tapple Gao
I have a vehicle script I've been working on for 12 years. It started out as a single script, with control event setting vehicle parameters. I have expanded it a lot since then. It now includes AI (control keys simulateed by another script, 7 vehicle mode controlers (ground, swim, fly, each with a physical and nonphysical option, plus attached mode), security features for restricting it to moving within a user-defined area.
It ran beyond the capabilities of one script a long time ago. The most obvious way to split it was at the control boundary: put all the code that takes user control and modifies that into one script (pilot for manual, autopilot for not), and put the different vehicle modes (ground vs flying vs attached) into seperate scripts. However, after using that for a while and comparing that with the old script, I realized I'd lost something important:
input responsiveness.
Just having a link message on the critical path from control event to vehicle parameters made the vehicle harder to steer due to input responsiveness. And people use it for racing. So, I redesigned the scripts again, and went with a design I still dislike: I duplicated the pilot script (input handling) into all 3 motion scripts (ground, flying, attached). I got back input responsiveness, but, now with duplicated code (and now I get to deal with obscure bugs with multiple scripts having llTakeControls active at once)
The script was actually better when it was split: I could use dedicated timers in each script at optimal frequencies for each one, and they don't actually share a lot of state. However, link messages are NOT a great way to split scripts:
- They do cause delay, usually 1 sim frame between send and wakeup, which is bad for vehicles
- They broadcast to every script in the prim. This is ok for some uses, but it's not great when there are 20 or so scripts in the prim, and every link message causes 20 script wakeups
- They require serializing to string at the sender, and parsing from string at the sender, which adds unnecessary cpu usage
We really need a better way to send one message to one other script in the prim. It should ideally be:
- immediate. It is processed as soon as it is called, or, at latest, immediately when the current script ends its active event. No putting it in a queue until the next frame, unless the script would be pre-empted anyway
- synchronous. It would be best if the remote call was an rpc, and did not resume the calling script until the callee script finished. The callee script could possibly even return a value to the caller, making it a remote function and not a remote procedure. This would make it possible to share functions between scripts
- typed, so I can pass things other than strings. I'd like to pass a list and get back a list, without serializing/parsing in the middle, since that's the only typed variable type in LSL
something like:
// sender
list returnValue = llRPC(string scriptName, integer fn, list params);
// receiver
RPC(integer fn, list params) {
if (fn == ECHO) {
llRPCResponse(params);
}
}
Link messages can stay; they are good for shared state updates to all scripts in the prim. But, splitting scripts to deal with exhausted memory needs a finer grained control like a remote procedure call, that addresses the issues with link messages
RestrainedRaptor Resident
I guess what you're really after is a link message equivalent of message filtering that exists for chat channels, provided by
llListen
Peter Stindberg
I don't see an issue here. Linkmessage-events - if
not
queried - cost no script time. There are an awful amount of events occuring for any given script at any time, and they cost no script time if the script simply ignores them.If
they are queried, it's also a non-issue if some thought has been given to the proper usage of the string/key parameter fields, to filter out and quickly skip over unwanted/3rd-party link messages.However, the idea is not
totally
without merit, if you are operating in a modifyable object and share the linkset with 3rd party scripts you have no control or trust over. But as Bavid mentions, the script name is probably the worst choice for targeting.If something like this would be implemented, a PIN similar to
llSetRemoteScriptAccessPin
would be a suitable way. With a unique PIN, settable by the receiver script, the script name/version is irrelevant.In scenarios like the above (3rd party scripts in the linkset and data-integrity/secrey concerns), I use LSD with protected keys as messaging basis. But of course, the same could be achieved with link-messages and encrypted strings.
Bavid Dailey
Peter Stindberg
The problem of using LSD, is that if you're using it as a 'permanent' database, you will come to begrudge using it for other things. Overloading makes for conflicts.
Bleuhazenfurfle Resident
Peter Stindberg: If the script has no linked_message handler, then no event is scheduled, and indeed it has negligible cost. But, I can't think of the last time I had more than one script in an object, without each and every one of them having a linked_message handler.
And if there's a handler, then the event needs to be constructed, queued, the script scheduled, and invoked, and all that even if the handler is empty, and before the first line of the handlers code gets evaluated (ie. before any such filtering is possible) — I see people frequently forgetting that there
is
cost to invoking a handler, probably because it's nigh impossible to measure.The ability to not queue the event at all, is actually a good one, and the same reason there are calls to add filtering for the changed event — it's a rather significant performance hit if your colour cycling shoelaces simply want to know when the shoes they're attached to get transferred to a new owner. (And yes, of course there is an alternative way to handle that, it's called an example — because I just know
someone
will want to argue the point.)A pin is horrible for security, it's only 32-bit. That's pretty uselessly small for actual security, if the attacker has even a little time on their hands. For that, the only real option is encrypting or signing your messages (I sometimes do this by computing a SHA hash of the message payload, and passing it through the key parameter of link_message). This could be improved by whacking the script with a large delay in the event an incorrect pin is used (though there are no examples I can think of off hand, of a command having a variable delay — that might not even be possible in the current system), or even halting it entirely with a debug channel error, but that's nothing a bot couldn't bypass quite easily. (So now you're making up even more cryptic limits, and the whole thing goes to hell in a handbasket.)
Being able to address the target script directly bypasses the need to encrypt, and allows for the use of a one-time session token negotiation (which must be kept secret). Many of us do this all the time with llRegionSayTo, for example. Not to mention avoiding a whole heap of excess events being queued and processed.
As for addressing a script by name, I don't like that either. It's fine for optimisation, but not authentication. Would much rather use the scripts UUID. And yes, the UUID will change at times such as when the script is recompiled, but that's the
right
time for it to change anyhow. So, you authenticate, and if the script passes validation, you remember it's UUID, and send your messages direct henceforth, is how I would see this being useful. (There is one more issue here… More than one script having the same UUID… Which is where a URI would help, but I can't think of a suitably stable one off-hand that meets the requirements above.)Pazako Karu
Bleuhazenfurfle Resident I imagine you've already tried guard clauses and found them insufficient?
if(!mine) return;
It's a nonzero runtime but it's a heck of a lot faster than misinterpreting the input and going through the regular if-chain. I imagine the difference in link_this and link_set might be similar to a dozen guard clauses, it's worth a test.
Bavid Dailey
Must be a better way than drecting to scriptname; i name my scripts with versions for one thing. Suggest adding a way to assign a URI to a script, association to be controlled by the programmer, and using that as the second parameter above.
Bavid Dailey
Woolfyy Resident
No a URI used as a label, it's not the URI of the script, so it does not change as the script is recreated - that's the point.
To restate :
- script is assigned a developer managed URI , which it can assert as its 'identity'
- the proposed extension directs link messages only to a supplied URI