|
|
|
Will HTTPS be allowed, as it is in llHTTPRequest()? If so, can we have a setting to allow only HTTPS requests? Or would we need to filter based on some metadata about whether SSL was used?
I could see this being difficult because of the need to provision many SSL certificates, one for each region or sim. Perhaps LL could solve this by creating their own CA, and posting its CA certificate on the SL website accessible by HTTPS so we can be sure that we're getting an authentic certificate. Then again, perhaps that's all a little too complicated That's already dealt with, it seems. The script will get an http_event() with type URL_LOST when the http server is lost. Hopefully we can get some amount of guarantee that that event will always be sent to the script when the server is lost, so that the script can restart the server if it wants to.
Gordon: That is my personal priority setting. We actually don't pay too much attention to the priority of issues in pjira - votes and number comments (ie general interest) weigh in more. The internal one is 'major' so maybe I'll change this to match. I'm hoping to get to work on this within the next 6 months. I have other things I must do first though, priorities being what they are.
Lex: That is a good point. I actually think the cap server only listens on https, but I will look into that closer. My guess right now is it will be either HTTPS only or both. Whoa, hmm. It might be disadvantageous if ONLY HTTPS is allowed... because then people will have to dig around for an HTTPS-compliant library for their given language. Granted, many languages have them, but HTTP is likely to be more supported than HTTPS. I'm just idly nitpicking, though... I'd sure rather see HTTPS-only webservers in SL than nothing
@lex:
2 objects communicating via LSL http requests (assuming this is permitted: see http://wiki.secondlife.com/wiki/LSL_http_server rolling restart occurs, both objects now have new url's having to revert back to llemail or xmlrpc to communicate the new url's once generated? the issue is ability to keep track of the url of the object without having to fall back on another communication method is point i'm trying to raise if that makes sense. Drew: For communication between 2 objects on the SL grid as you describe llEmail will work great as a fall back for discovering urls. llEmail from one object on the grid to another is not really email and is much faster than normal email. The primary goal of this feature however is not obj -> obj comms. Email really is very good for that. The biggest goal is for communication to in world object initiated from outside SL.
You are right, this design has the draw back that any sort of presence for objects has to be maintained by the LSL scripter. I am aware of that. I think it is a necessary evil to create the most scalable feature possible and I have tried to add the features to make it as easy as possible. This aspect is actually mirrored by XMLRPC which requires you to track a key that may change (although less frequently than http_server will). Kelly,
We need a way to get the GET variables. Thanks for this. Gigs,
The wiki page has some more details I think. But basically I don't think that will be possible at first. The caps system just doesn't allow for anything past the end of the cap URL (no /<uuid>/Foo). You will be able to do POST or PUT to pass in a body with the message (or even with a GET I think?), which the LSL can look at and send back different data for. Sure it isn't the easiest, but I think it is workable. If in the future we are able to extend the cap system to allow tacking data to the end of urls then the LSL event will be able to handle that as extra information in the META variable of the http_server event. Hmm... without being able to pass GET variables, we won't be able to easily set up a redirecting registry of LSL server URLs. I was envisioning some kind of service on a server out on the internet, which would allow LSL scripts to register their HTTP servers using an llHTTPRequest(). The script could request a simple, descriptive name, and the server could provide a static URL that wouldnt' change as the script's HTTP server URL changed. Requests to that static URL would be met with an HTTP redirect that sent the requester on to the LSL script. Redirects won't send POST bodies, though, so that kind of system would break down unless the request was actually proxied. Ah well.
Really? It doesn't seem like much of a redirect if it won't forward the post body. I admit to not being an expert on that though and could see that would be a draw back.
The cap server is essentially an url redirect service. The data from the request at the cap url is sent to the internal url - including any data in POST or PUT (and I think even bodies of GET). Or is that more what you mean by "actually proxied"? What you describe is a proxy, rather than a redirect, I think. The caps server itself goes inside and does its own requests on behalf of the client, and then forwards the data back to the client. An HTTP redirect (HTTP 302 status, for example) actually tells the client "go here instead", and the client is responsible for following up on the request. That's advantageous for a registry like I described above because it would mean there was no burden on the server of actualy fulfilling the request and forwarding the results. The original client would deal with that. That would mean the server would use fewer resources, and the registry system would act similar to a DNS lookup, but at the HTTP level.
Redirects don't forward the POST body. In fact, if your browser POSTs a form and gets back a redirect, it GETs the url specified in the "Location:" header. This is probably a good idea so that POST bodies don't get spewed all over the place. It's fairly common (especially in forums and the like) to use a POST -> Redirect -> GET system for submitting forms. The user fills out the form (ie me placing this comment), the browser POSTS the form body, the server acts on the POST, and then the server redirects the client to use a GET request to see the results of their action. This means that the user ends up, for example, just looking at a JIRA entry, and if they hit "reload", their comment won't re-POST. Generally a good thing. From the HTTP RFC: 10.3.3 302 Found The requested resource resides temporarily under a different URI. The temporary URI SHOULD be given by the Location field in the If the 302 status code is received in response to a request other Note: RFC 1945 and RFC 2068 specify that the client is not allowed Interestingly enough, the common convention of automatically following a redirect resulting from a POST violates the spec... but it's generally considered a useful way to go about things, and EVERY browser does it. "303 See Other" basically does exactly what I described above, and the spec specifically says that the target URL SHOULD be retrieved with a GET. All in all, HTTP redirects simply don't carry a POST body onward, so any data would need to be copied by the server from the original request's query string into the redirect-target's query string. So that means that something like I described above wouldn't be possible without GET argument processing. Not the end of the world, but something to consider. Thanks Lex, that is good information.
There's a deeper issue here, that the new CAPS stuff purports to be RESTful, but one of the key things about REST is that the URI can fully describe the resource to be accessed.
I'd go as far as saying that's THE core idea of REST. Unless I'm misunderstanding this situation badly, this whole thing goes strongly against the grain of REST the way it's designed now, forcing actual resource information into the body of the request. I'm not saying this wouldn't be extremely useful even if we don't have a GET sort of functionality, but there might be a deeper issue here that needs to be resolved. Does that mean we can host a file, page and view it from a external browser?
Also, an ETA, if you would be so kind?
Cory:
Not really. The url is going to ugly and subject to semi frequently changing. You could have a script that returned some specific data, or data about it's environment or whatever, and you could view that data in a web browser. However given the limited available script memory, general LSL constraints and the ugly, changing urls it will not be good for use as a general web server. And no, you won't be able to host files on it (although someone will figure out the exact LSL required to serve some small file I'm sure. No ETA right now. This is not in active development. Updated the Feature Request pages on the wiki: Added this JIRA to notes section.
http://wiki.secondlife.com/wiki/Http_server
Siris... I looked at the functions list at the bottom of that page, and I see a function "llGetHTTPServerURL". I don't understand where it came from and why it needs a 0.5 second delay. It'd be useful to have in case you misplaced the return from http_server(), but why a delay?
Lex:
At the time of conception that was the set we (Sean & others...) had come up with initially. Nothing about them is set in stone & totally theoretical. The delay is just there for "shits n' giggles" basically. Please feel free to update/delete/rename them, etc... A lot has changed since they were made originally. I need this >_>
I need to be finished <.< How do we get URL parameters?
https://sim123.agni.lindenlab.com/cap/f23b4b94-012d-44f2-bd0c-16c328321221?var1=true&var2=false&var3=foo&var4=bar What method would I use to get varX in the LSL script from a GET request to the above? Using llListFindList... Hopefully the params should be received as a Name/Value pair within a strided list:
Evens - Param name [param1, value1, param2, value2, . . . paramN, valueN] Kamilion: For the design proposed in this jira you may need to use a PUT or a POST, in which case the variables would be in the body of the message. I'd like to be able to pass the tail end of the url in to the LSL script but there are reasons this may not be possible. If we can do it everything after the capability would be passed in as a single string in the meta list of the http_server event.
And yes, that is I think the biggest down side to the proposed design here. Hmm, if that's how it's done (passing in the query string url-escaped), then it might be nice to have a llDecodeQueryString() function. Heck, it might be nice to have one regardless, for POST bodies encoded in the same way (as happens with forms submitted with method=POST). It'd be possible to write an equivalent in LSL, but it'd be slow and use a lot of memory.
The wiki design for this has been updated:
https://wiki.secondlife.com/wiki/LSL_http_server There is a teaser image of a hello world server available also: I don't currently have a time frame other than Soon(tm). Feedback is welcome, but please keep comments on the discussion page of the wiki, the way I am updating the design page (to reflect a changing internal design page) means edits there are likely to be lost. Final word of warning: while this is in active development, the design is being adjusted regularly to reflect actual implementation when needed. I'm excited
> * system_changed(integer change) (possibly a subset of existing changed event) Maybe this should be a separate event. Having a changed() event means that scripts get events for ANY change and have to filter. That could annoyingly clog an event queue when all you want to do is keep your http server open. It could increase simulator load. While that is true Lex, I think the additional script load in that case is negligible, but probably something to be considered.
The other concerns I have around the issue are:
Ah, it's good to hear that the load from a changed() event is low. In that case, changed() does sound like a good way of doing this. Any script using == on a bitfield deserves to be broken. It's one thing to avoid breaking content by changing the LSL API, and it's another thing to avoid breaking content by fixing LSL bugs people depend on, but it may be too far to try to avoid breaking LSL due to incorrect LSL code.
I wonder what other CHANGE_ flags the SYSTEM_CAPS_RESTART and SYSTEM_REGION_RESTART flags would be likely to occur in combination with? Good stuff Kelly.
Q: How are DoS attacks against sims handled? Good to see that work has started on this.
Things I Like about the current design:
I'm glad you took my request for arguments into consideration, and I heartily approve the header name – "x-untrusted-argument" is a perfect description of what I was looking for.
I like the fact that you guys are really thinking about the limits to put in place to make this a useful AND safe thing – otherwise we'll end up with "the bling effect" of some jerk putting ~200 particle bling scripts in his 3 prim sculptie necklace. Very good forethought there.
Yet more forethought into the response codes, I would propose that response code 410 "Gone" be used for "No Script/Object found". 410 Gone The requested resource is no longer available at the server and no forwarding address is known. This condition is expected to be considered permanent. Clients with link editing capabilities SHOULD delete references to the Request-URI after user approval. If the server does not know, or has no facility to determine, whether or not the condition is permanent, the status code 404 (Not Found) SHOULD be used instead. This response is cacheable unless indicated otherwise. The 410 response is primarily intended to assist the task of web maintenance by notifying the recipient that the resource is intentionally unavailable and that the server owners desire that remote links to that resource be removed. Such an event is common for limited-time, promotional services and for resources belonging to individuals no longer working at the server's site. It is not necessary to mark all permanently unavailable resources as "gone" or to keep the mark for any length of time – that is left to the discretion of the server owner. 301 "Moved Permanently" should be used for an object that has recently changed regions, if the regions are still in communication with eachother (assuming they are adjacent) a 301 should be returned to the new CAPS URL if known. Throttled requests should result in a 503 "Service Unavailable" with a proper Retry-After header. 503 Service Unavailable The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response. Note: The existence of the 503 status code does not imply that a
I believe that we should, like the llHTTPRequest() call, be very clear in our handling of bodies and mime-types. I support this, but we should have a mechanism to define RESPONSE types other than text/* – I regularly use ruby on rails and have ported a simple YAML implementation to LSL, and I would be quite happy to be able to respond with application/x-yaml instead of text/x-yaml.
If my memory serves me correctly, the queue depth for script events is 63, is it not? Therefore we theoretically would be able to have up to 32 or 128 HTTP requests in progress? Certainly hope you guys are writing this is a multithreaded manner! That is quite a comment, here are my thoughts.
I need to update the design again, but I also need to update the internal one a bit (not as much as the external). The design is a little different, trusted path and untrusted path are gone (including from the llRequestPublicURL() call) replaced with 3 other headers. The full header list is now: "x-remote-port", "x-remote-ip" as described above. I will have a look at those response codes. 301 will not be possible - we simply don't know where the object has gone and have no intention of tracking that. LSL can only produce UTF-8 text. For now that is what we will be returning, and the content type will be fixed to "text/plain; charset=utf-8". At a later date it may be possible to implement setting headers including content type on responses and maybe even returning different response types. For now we are going with the queue depth, 64, for number of pending http requests. However there is a relatively short time out as well - 25 seconds. I'll try and get the wiki pages updated this week, but no guarantees. kelly wrote: LSL can only produce UTF-8 text. For now that is what we will be returning, and the content type will be fixed to "text/plain; charset=utf-8".
Not sure I understand what possible use an LSL HTTP server would be if it can only return content MIME type text/plain, not even text/html?? The "H" in "http_server" stands for Hypertext after all. So if it can only return text/plain and not hypertext, why not just call the event "text_server" instead? Am I missing something? I'd prefer if the script can set the content type to anything - there is no negative security implication of that I can think of, is there? If this feature is really going to be so crippled by only being able to return text/plain, I'd rather see work spent on something more worthwhile (I'll remove my vote, though I realize that'll make no difference). I hope I've misunderstood or you'll reconsider. If so, it could be a very useful addition to the grid. Thanks for keeping this issue up-to-date. You do not misunderstand and you are free to remove your vote of course.
The greatest utility for this function is getting data into SL / LSL and out of SL / LSL when polling via llHTTPRequest would otherwise be required but impractical. Essentially when data needs to be transferred on the schedule of the external service as opposed to the LSL based service. Being able to host user friendly or pretty web pages and interface seamlessly with various protocol systems are distant runners up in priority. Creating intermediate interfaces for these features are not that difficult, well within the realm of doable. Web sites at persistent URLs can retrieve data from objects and format it for viewing and interaction. In fact this is a much better scenario because it keeps the bulk of the load on the high performance and less restricted server and relies only on the low performance LSL server for the SL related data it needs. You may be surprised at how quickly you burn up 2k bytes when you start making pretty html pages. Redirecting services are going to be needed and popular anyway given the temporary nature of the urls. Similarly it should be possible to create simple services that retrieve the text based data from LSL servers and format it as required to match desired protocols. There are probably business opportunities in providing these services, both for protocols and html, including the tracking of these very dynamic urls. Our goal with this phase is to make the greatest amount of functionality available as quickly as possible. The more features we add the longer development and testing takes. No, the solutions above are not necessarily ideal and they do require extra work and extra servers and introduce latency. There is also a social hacking concern around the ability to create pretty web pages on dynamic often changing urls. For example phishing systems could be created that linked to objects in world with the pretty mock bank site and disappeared entirely after used. This simply isn't possible if objects can only return text. I'm not saying this may not be addressable, only using to illustrate that there are security implications in these decisions. continuing the previous comment:
Adding more features, such as setting headers and changing the returned content type, is definitely something that is possible in the future. I do not mean to imply by my above statements that these features are not possible. It is just very unlikely they will be included in our initial implementation. Thanks for the comment kelly.
That saddens me because "getting data into SL / LSL and out of SL / LSL" and "when data needs to be transferred on the schedule of the external service as opposed to the LSL based service" is exactly what we'd hoped to use this facility for (specifically, text) - just not with plain text, but "text/xml" and "application/json" (which is also text but uses "application" for historical reasons). It seems we'll be unable to do that using standard tools that expect those content types. If we can use it at all, it be via 'hacking' client libraries to deal with the non-standard response content-types. If you're worried about the social engineering problem of people using it to serve HTML pages to standard web-browsers, why not just limit the response content-type to text/plain if the user-agent indicates a request from the top 3-4 most popular browsers? (e.g. IE/Mozilla-based/Webkit/Opera) - or even require a specific substring to be present in the user-agent client header (e.g. "SLUserClient"), or a special x-grid-user-agent header and just reject requests that don't contain it outright. Since, most HTTP-based protocol libraries allow setting of the user-agent and additional headers, but don't have any mechanism for dealing with incorrect/non-standard response content types. Currently we used a mixture of llHTTPRequest polling (from tens of thousands of objects all over the grid), XMLRPC (since it does still work occasionally), email both ways (both inter-sim and external), IMs to bots and two-way region chat to between 'relay' devices which also use llHTTPRequest polling to our external service. How difficult would it be to at least have some way to set text/xml instead of text/plain in the initial implementation? At least that would allow people implementing XMLRPC. It would even allow developers to re-use the code already developed for the ill-fated LL XMLRPC service. I can't think of any phishing schemes that would benefit from being able to serve text/xml. Cenji,
Even if we can only serve text/plain, you can still pretty easily set up a system that will let you use your JSON clients or any other kind of client. It'd look something like this: [LSL HTTP server] <===> [translation server]<===>JSON clients The translation server would be a relatively thin server that would have these tasks: 1. Communicate with LSL scripts to keep track of their HTTP server URLs. The overhead for such a translator will be minimal. You'll have to have something doing #1 anyway. The advantages are:
Kelly, I would like to point out one thing with respect to phishing. Mozilla browsers are good about paying attention to the Content-Type and trusting it regardless, but Microsoft IE sometimes tries to be "helpful". I know it was true in the past that if you pointed it to a url like "http://foo.com/bar.html", even if the server returned a Content-Type of "text/plain", IE would go ahead and render the HTML anyway. I think this was an ill-conceived attempt to save server admins trouble... but in practice it just made it so that server admins who only tested in IE could find that people using Mozilla browsers would get a page full of HTML. You might want to test recent versions of IE with this kind of thing, since your design allows scripts to pay attention to path info, which would allow them to produce URLs that "look" like they should be static HTML pages. Perhaps a "Content-Disposition: attachment" header might convince IE not to be "helpful"; it will cause firefox to always save the file rather than displaying it. Lex,
Of course it is always possible to create translation servers, but that just adds more code, more complexity, more maintenance and less reliability. We already have JSONRPC and XMLRPC clients and servers external to the grid and we have LSL XMLRPC and JSONRPC clients calling out from the grid. We also have LSL XMLRPC servers using LL's XMLRPC implementation. Given it would seem simple enough for the implementation to allow other response content types (or even just text/xml as an option) that would keep things straight-forward for us - all we need to do is implement JSONRPC and XMLRPC servers in LSL - which would leverage the LSL code we already use. On the other hand, adding an additional 'translation' server tier means:
Our using XMLRPC and JSONRPC calls from the grid implies XML and JSON in both directions and we are living within the current llHTTPRequest/LSL constrains and can live within the 2kb limit. I'm not disagreeing with you Lex. I'm just voicing my wish to Kelly that in our particular case we'd greatly benefit from being able to serve responses with at least text/xml and if possible application/json content-types. I don't think our case is especially unique. I've implemented a fully threaded HTTP server myself in the past. I can't speak for Kelly's implementation, but I find it difficult to believe that it would be such a big task to provide a mechanism to set the response content-type - even if it is 'filtered' by the implementation to be in the set ["text/plain", "text/xml"] (for example). Then the mechanism wouldn't need to be changed if a future implementation expands the allowed types. So, it is a suggestion in the hope that when Kelly weights it with all his other considerations he decides the effort is worth it I'll add the capability to the opensim code myself if necessary, since having the restriction only from the SL grid is better than having it from other grids as well. If it is implemented with only text/plain, of course we'll utilize the facility. I'll probably just stop using the facilities of our framework for XMLRPC and JSONRPC and find an open-source implementation of them, then hack it to accept the non-standard response content-type and then have the maintenance headache of extra build dependencies and of re-applying my patches if I ever want to update the code. Either way, it'll be interesting to see to what uses people but the facility, even if it is initially crippled. Well, just to continue the friendly debate here, I think you overestimate the detractions you list. There will be just a little extra code to add the translation layer, but I don't think that necessarily implies decreased reliability or greater complexity. There are many examples of modular design which use a layered approach like this in order to build up to the application layer. I'm specifically thinking of the network stack here, with its 7 layers. In this case, all we're talking about is three layers: LSL (think of it as a very limited interface, like the Physical Layer in the OSI model), an intermediate translation layer, and then the application layer (JSON/XML/whatever).
LSL isn't so good at speaking XML, and it's going to be pretty painful to write a good, reliable, robust XML parsing routine. You've already done it, I know, but I bet it was a pain, wasn't it? LSL's so limited and difficult to maintain that I prefer to move as much code out of the LSL script and onto an external server as I can get away with. LSL really would rather just deal with simple text communication. On the other hand, your applications would really love to just do abstract XMLRPC, passing objects around or whatever the model is in your applications. To me this is just asking for a robust, reliable layer to act as a go-between, handling all the nitty-gritty communication with LSL and leaving you free to write nice-looking, easily-maintained RPC code. Furthermore, as Kelly points out, that translation layer need not be written by you; it could be an external service you subscribe to. You're suggesting you'd go grab an XMLRPC/JSONRPC implementation and hack it to accept text/plain content. You said yourself: this is a maintainence headache waiting to happen. You're going to be subverting the code so that it's not necessarily working how the writers intended. You might introduce unexpected problems, affecting reliability. Upgradeability is out the window. Complexity goes up. This strikes me as a far less robust solution. Why do this when you can write a small, reliable, clean, simple little piece of code to act as a go-between? Oh, and about the feasibility of adding other content types to the LSL HTTP server system: Of course if you just look at the technical aspects, it'd be a very simple thing to add different content types to an HTTP response. Just a few lines of code. But Kelly's not dealing with an HTTP server in isolation here. It's part of a big production system with lots of interconnecting parts, a QA department, design and implementation phases, etc. Making a change might well mean going back and modifying the design, figuring out the 5 or 6 places that the code needs to be changed, wondering if the changes will break the CAPS server and bring SL down, more QA cycles, more test cases, more thoughts about security, etc. I'm going to take Kelly's word for it, because I know that these things are much more complicated than they seem from the outside. I'm probably totally missing something - but if each prim only gets a max of one public url, why does llReleasePublicURL take the url as an arguement? There is only ever one per script, right? So shouldn't just llReleasePublicURL(); work?
Yes, you are missing something.
Each script can request as many urls as it needs. There is a limited amount of total urls available, but it isn't limited by prim or script. Also urls point to specific scripts - other scripts in the same prim will not receive the events. So you could have 10 scripts in a single prim each with their own url. Or you could have 1 script with 10 urls. The design at https://wiki.secondlife.com/wiki/LSL_http_server
Also there is some discussion on the Talk page that might clear up (or cause more confusion) the issue of public urls as resources and resource pools: https://wiki.secondlife.com/wiki/Talk:LSL_http_server I put up a couple of really simple examples, hopefully to give people a better idea of what this looks like in practice.
I've just attended CG Linden's office hours where this was discussed today. I'm sorry if I am coming late to the party here, but it seems to me that not having persistent URL's for the server makes this feature almost worthless. After all, the whole point of a client-server system is that the client knows where the server is.
I am talking about things like vending systems, where a vendor sends a HTTP request to a warehouse server object to deliver the product. This is a much neater method using using llEmail, which is currently the only way for two in-world objects to communicate if they are in different regions. Similar considerations apply to any external application which needs to know the URL of the in-world server Is it possible to have a URL that uses the Region name, Object Key, and some user-defined given name, as follows: http://myregion.regions.secondlife.com/object-key/myname For static objects, this would persist as long as the object remains rezzed. Yes, maybe it involves an extra database lookup for each request, but surely this information could be cached somehow, because regions don't change sims THAT often. My twopence from the UK The "temporary urls" will already remain as long as the object is rezed, unless the region is restarted or the script is restarted. These two actions change the identifiers for the object and so would need new urls anyway. (Region restart changes the port, script restart changes script id).
As documented on the wiki page (http://wiki.secondlife.com/wiki/LSL_http_server Yes it is a bit of a pain, but doing it this way makes this feature scalable (which our implementation of email is not). I also expect dynamic name services to pop up as a viable business opportunity, so after a short time it seems very unlikely that you would need to build your own custom solution unless you had some really specific needs. Thanks for your reply, Kelly. I can understand the point about re-rezzing the object or resetting the script. These are things that I have control over, but I have NO control over a region restarting. I really, REALLY think that you need to find some way of implementing persistent URL's. Otherwise, you will have spent a long time developing a nice technical feature that is fatally flawed and very few people will bother to get their heads around how to make it work.
I'm not sure how this could be considered fatally flawed.
This function is to replace inbound XML-RPC with something scalable. It does just that beautifully. It's designed to complement an external service, which you can easily poll with the latest http_server url through httprequest or email. To provide persistent URLs would invite abuses of simulator resources. If I'm using this then I'm going to have to track these URLs anyways, I'm not sure that tracking them after a reset is that big of a deal, its definitely not a showstopper.
Adding my voice to the debate here - I'd much prefer this to be implemented quickly, and with minimum risk to the caps server than to waste time trying to solve all the issues around keeping "stable" urls.
I've already got plans to implement a web based dynamic name service for this anyways...either for my own use or possibly as a generally available service. I'm betting I'm not the only one. The other advantage of the approach taken here is that we get a new CHANGED event when a region restarts - useful in many other ways! the UUID of rezzed objects change whent he region restarts? what about rollbacks? and sim crashes?
Tigro: No. The UUIDs of rezed objects almost never change. Taken to inventory and re-rezed they do change.
What changes on region restart is the host and port number for the region, which are kind of essential for actually communicating with the object. ok, then since UUIDs are suposed to not change, and be unique, why not use just that for the address?
as the number of urls available is per owner, not per object, an object can have a large number of urls - so using the UUID of the object wouldn't work.
"Kelly Linden - Yes, you are missing something. Each script can request as many urls as it needs. There is a limited amount of total urls available, but it isn't limited by prim or script. Also urls point to specific scripts - other scripts in the same prim will not receive the events. So you could have 10 scripts in a single prim each with their own url. Or you could have 1 script with 10 urls." oh, I didn't knew that, I see, ok
I don't think that abuse of simulator resources can be used as an argument against persistent URL's. That's a bit like saying I'll prevent DOS attacks on my web site by giving it an obscure URL that nobody knows and which changes frequently
I've already apologized for entering the fray late in the day here, but it's often good to have outsiders come in and poke holes in something you have been working on for a long time. Sometimes you get so focused on something that you can't see the wood for the trees. I know - I've done it myself enough times. Please reconsider this, because I don't think I can find much use for this as it is, and I suspect a lot of other SL developers will feel the same. I don't see any difficulty with having urls that aren't persistent. And because of the following issues they can't be persistent:
1) You move to a different region, on a different host and port number. for all of these reasons, and probably more, persistent URLs aren't possible. It's not that LL doesn't want to do it, more like the overhead to even try to attempt to have the urls remain persistent would be outrageous. I'd rather have something simple that works with a high amout of reliability (and so far so good.) It's pretty trivial to handle non-persistent URLs. Get the new URL, phone home to your external server (who's address never changes), and tell it the new URL. If your application doesn't involve an external server, all the same tricks that worked for llEmail are still applicable. And as Kelly correctly points out, Dynamic DNS is completely workable for HTTP-IN, there are numerous free services that provide this already, and I'm sure some which are SL specific may spring up. Overall I find HTTP-IN to be fantastic and It is going to revolutionize many aspects of communication within SL and between SL and outside destinations. Many, many thanks for implementing this. OK, I'm with Lamorna on this. It would be bad enough to have to do something like using Google only to discover that on random days, their name has changed ... but that's not so bad, all you have to do is e-mail them and they will tell you the new one. Oh, and repeat if it happens again. Oh, but then, if you have your OWN web-crawler service, you can use that to figure out where Google has moved to this time.
I'm glad people think this will revolutionize things in SL, but it seems to have an Achille's Heel. If we have to fall back on the things we're trying to avoid (e-mail and our own http servers) what's the point other than a cute, but incompletely thought out exercise? Aargle: " what's the point other than a cute, but incompletely thought out exercise?"
Scalability. repeat after me Sca-la-bility. Frans, I don't care whether something is, technically speaking, scalable or not. I want something that is USEFUL. Repeat after me U-S-E-FUL
This will certainly me useful to me and I guess many SL developers. It may not be the most elegant interface - I agree with some of Lamorna's points.
Think of this as a good first step. Not having a readily available resolution service for persistent URLs certainly makes it more complex to use - hence will be less used/useful to many. I'd rather have this now than wait longer for something better. As mentioned, 3rd-parties will provide such look-up services for sure. Of course, the less external dependencies one has the better - so I would love to see LL provide such a resolution service on top of it in time. LL obviously has the facilities as they've had to solve similar problems internally themselves. I hate to sound condescending here, but this is the truth.
This functions EXCELLENTLY as a replacement to XML-RPC. It is both useful and trivial to get around the temporal nature of the URL. (especially with the functions provided). Programmers (and specifically scripters of LSL) have been working around this problem for years now. Frankly, if this isn't useful to you, then you aren't the type of developer this was intended for. Input is of course appreciated - but attempting to derail the train in the eleventh hour will only succeed in delaying the feature for a lengthy period (you can't just bang out code, a major change like you and others are suggesting would most likely require a retooling of the entire feature, and then it would have to go through QA ALLL over again) Already this feature has been in development for (most likely) over a year. Worst case scenario they decide it's too much trouble and we get SQUAT. So your opinions have been noted. After this feature has been released you can submit a ticket for a change or a new service. I have plans to create a DNS type service and (as others have signalled) so do many others. Once several good DNS services are available, this will be something you never really have to think about. Stop, now. This is not a place for a fight, no one here is stupid or should be treated like they are.
Lamorna: Unfortunately scalability is a huge concern for us. We have a huge number of servers, a huge number of active scripts and a huge number of active users. I completely and fully understand the desire for persistent urls. However implementing persistent urls on our end requires pretty much the same thing we are asking users of this: a registration service. That registration service would require new hardware and additional cost. Also, if done by us at this stage (every url being persistent) it would have to be a registration of every url ever used, which increases the scope dramatically. Doing it the way we are has many advantages:
It is also important to realize that this feature is not meant for user visible web pages, it is meant as a glue between webservices on the greater Internet and the scripts in Second Life. For a web service it is not that difficult to update the url it communicates with when needed. Persistent urls are not something we just forgot or overlooked. We thought really hard and long about them and what is required to offer them at the scale we have now and the scale we expect to reach. We discussed the options with content creators at various venues and even sought out some of the highest users of xml-rpc and llemail for their input. The conclusion is that it is not free to offer persistent urls (but is essentially free to offer non-persistent ones), that the service required for that registration does not need to be built by us, that the service could in fact be built better by our residents for some uses and that we could always offer the service as a later feature if needed. Your input is of course highly valued, as is everyone elses here. I agree the feature is less usable without persistent urls, but it is far from useless. Currently every "live" object I have that uses HTTP polls my website database once every 10 seconds to check for messages. I would assume that I could cut that to a "log-in" to refresh the URL if no communication message (or "null-wake-up" message) is received for an hour, of if an event is detected that would change the URL.
The present system has been working (nearly) flawlessly for a year so reliability would not increase but my website traffic volume and SL outgoing HTTP traffic would go down by just under 100%. Not having kept up with the developments, I assume a log-in like that could easily keep the URL current? The way to do it would be, Monitor the conditions which could cause URL Loss. (Sim Restart, Reset (by using the state_entry() event), Region Crossing, or Rez). If any of these occur, request a new URL, and poll your external webserver, providing it the new URL. Simple as that.
Darien, admittedly that requires resources every time one of these events occurs and multiplied by the number of scripts having to do such checks that could cause quite a bit of load right after a sim restart however I think that's probably the best if not the only way to do that and thank you for beating me to the punch in suggesting using such checks.
Yup that sounds right. On the examples page (http://wiki.secondlife.com/wiki/LSL_http_server/examples
I'll bury this deep in here, but I have re-written the landing page (http://wiki.secondlife.com/wiki/LSL_http_server Thank you Kelly and everyone else for your comments. I seem to have opened a hornet's nest, but I assure you that my intentions were only because I care about SL and the features it offers to developers. It just seems to me that without persistent URL's as a primary design goal, HTTP server is far more difficult and costly to implement for the majority of scripters.
In the use case I had in mind, I have an in-world HTTP server and multiple clients. Either I use an external server to resolve where my in-world server is, or I use...duh... llEmail... to communicate with an intermediate in-world server whose address persists. But the latter is what I'm already doing. Therefore, I can't see the point of rewriting my application to use HTTP. I'll bow out of this debate now, and I hope that those of you who are keen to have this feature find good uses for it. Personally, I find it a big disappointment as it is, and I hope that Linden Lab implement some kind of URL registration service in the future. This doesn't have to grow and grow – we could be told that URL's will time out if not renewed after some period of time, and it's a simple matter for a running script to have a timer to renew its URL(s) occasionally. I read on Xstreetsl.com about this and am pretty thrilled. Sounds very good and I can't wait to get my hands on it.
However, there's one small thing that I'd like to add, which is the limitation of data to 2kb. Kelly states that «You may be surprised at how quickly you burn up 2k bytes when you start making pretty html pages». Well - heck, yes! I don't know about technical details, but I'm pretty sure that making subsequent HTTP-calls, just to get all the data we need, contributes more load to the server than being able to get all the data at once. Plus, I think it'll make some stuff more complicated than needed. I have a service running right now, which pulls data from a webservice to track airplanes. The data contains 8 variables, including plane-type, carrier, scheduled start/landing type, origin/destination airport and some more. REALLY small pieces of data. But depending on the length of the carrier and the airport names, the data is being capped. So I have to split these variables into two and make multiple requests to the server, just to get all the data. I'm pretty sure this will happen with HTTP-Server as well. So please, please, please - make the amount of data just a tiny little bit bigger (4k would be fine, 8k would be great!). And while you're at it, raise it on the HTTPRequest side as well I can't remember if I post this suggestion on jira before or not, but a possible alternative to the limit on the size of received page, would be to have tha ability of specifying a offset from the beginning of the file, this way in a couple of requests, without having to alter too much system, one could get an entire page, or just the end, or the middle or whatever
and (this being the idea i got now, that for some reason I thought would be similar tot he previously mentioned one) for pages hosted by scripts that the creator intends to be bigger than the maximum ammount that can be send at once, add one or two commands to create a page by appending a few 2KB chunks before sending to the client that requested the page Lamorna: This is by no means a solution to all problems. There are definitely cases where still using llEmail will make the most sense, and at this time I don't think we have any plans to stop that. LSL xml-rpc is another story though, and I'm hoping most or all uses of it can switch. The difference between the two is scalability - email is a scalability headache but we have it in a mostly manageable state, xmlrpc is a scalability migraine that we have barely under control.
Haruki: The size limit is not quite etched in stone. We do need some limit, and we chose to match the limit of llHTTPRequest. I think this is a case where if we need to we can increase the allowed length later, but we would never be able to reduce it if needed. As such I'd prefer to err on the side of a smaller limit for now. Also, you can't make pretty html pages with this, or at least they don't display as pretty in most browsers. Kelly, might I suggest the change of the name of the changed event constant to CHANGED_REGION_START?
The common expectation for what a restart does is that there is a short period of time between the stopping and the starting, but the way I'm reading this you intend to use the flag is to indicate when a region comes online. Additionally, the name of CHANGED_REGION_RESTART infers that it is warning of an impending restart and not the result of a restart. I've made a separate feature suggestion for this that goes into greater depth: SVC-3254 I'm with Lamorna here, requiring an external web application to track URLs is rather an issue. Given there's two things that shouldn't change, island name and object UUID, could we maybe have a lookup service to convert island names into hostnames, and then use UUID to compose the rest of the URL?
@Xugu: URLs are registered to individual scripts, not to the object/prim. Knowing the sim and the object/prim UUID wouldn't help you, nor should it. The system is designed so that the CAP cannot be guessed. If you know the UUID you could always have your script respond to email and that way send back the CAP.
Is it ok if I start writing documentation for this feature set?
(Basically work the design specification page into our normal style of documentation). Essentually what I'm asking, is have the keywords been finalized? Given Kelly's comments on
Stephen: It will be allowed.
As per http://wiki.secondlife.com/wiki/LSL_http_server
That's 38 URLs per Resident for the entire grid, yes? 38 per avatar, which is handy for things like attachments, and a safety net independent of parcel sizes. Added to that, you get whatever the parcel allows where the objects that request the URLs are dropped in. I think it was 1 URL per prim the parcel allows, sooooo...
38 isn't arbitrary btw, it's the number of attach points.
what about URLs on vehicles with avatars sitting? don't they use urls from the av count?
The wiki page linked at the top of the issue outlines most questions pretty effectively =)
I'm not trying to sound like a curmudgeon, but almost all of these types of questions are answered in the wiki. Please read there first before posting a comment as myself and all others with a watch on the issue get emailed every time you post a comment I believe I had already read it, though I didn't remember it being so detailed, either way, this kinda confirms what I though but then...
...does vehicles eat up from the same 38 urls meant for attachments when they are using avatar resources? and somthign I hadn't seen before, wouldn't it be better to inform the script it lost the url instead of returning the object? Please consider allowing through to llGetHTTPHeader() the headers added by the llHTTPRequest() function. Namely:
(though if the full list wasn't to be provided, at least shard, object name and key, region, local position, and owner key would be very nice). Any status updates on this?
I second that request for updates
Sorry for the lack of updates.
HTTP-In should hit Second Life with server version 1.27. We are currently on 1.25, and 1.26 became feature frozen before the final pieces of HTTP-In were in place. History we hope is a poor indicator of the actual time frame this implies. We are working to shorten the time between major versions, which is one of the reasons that 1.26 froze so early. Trust me I am as eager or more than anyone here to see this out the door. We will keep the HTTP-In regions on aditi / beta up until 1.27 beta servers are deployed there. Hewee: I can't remember if I made another jira for including the second life specific headers, but they will be available and should be on beta now. Woot! Awesome. Thanks Kelly!
Thank you for the update Kelly! Looking forward to it.
Well it would have been more of a woohoo if it were going out in 1.26, but I can't complain too much, that's still pretty fast.
Problem #1: text/plain only
To go around the text/plain limitation, simply write a firefox plugin that looks beyond text/plain for another header and use the second header instead if it is found - but only for second life type links. Perhaps make a series of plugins, one per file type, so that users that trust *.BMP files from inworld servers aren't surprised by a scary *.EXE Problem #2: dynamic URLs If the object itself says its URL and asks the user to click it, it is good enough for inworld-export work like outputting a file for the user to download. I'd use it to export sculptie maps with my SculptCrafter tool, for example. If the server is meant for offworld offline people, then have some bot login as an alt avatar. Have that bot stay just long enough to notice what the media URL is. Whenever the region restarts, your inworld server sets the media URL to its own URL so the bot has the info it needs always updated. Neither solution is very pretty, but they don't need intermediate servers at all! The problem is that they have already manually resolved the IE problem such that doing this would create the same problem in reverse, only much worse as most users use IE. So now instead of a significant (though smaller) group of users unable to view html from the prim, now a significant and LARGER group would be unable to view it.
I think a better solution is for http_server to support more mimetypes =) Everything I've looked at discusses design from the server end. Are there any corollary client changes planned? Is there a page for that I've missed? Specifically what I'm looking for would be something perhaps under About Land that would list object names and how many url resources they occupy. Much the same as the existing list of av names versus prim usage. Having llGet FreeURLs() return a value of zero is not overly helpful. Tracking down which obj is leaking url's is vital. Over time badly scripted objects can create url orphans and deplete a parcel's pool. But this is not immediately apparent. Land owners will need a way of determining the culprit after the problem presents so they can complain to the creator.
That has been suggested in http://jira.secondlife.com/browse/SVC-3245
Thanx. I figured it was probably in the thought pipeline somewhere. I took the liberty of making the Relates-To link to make it easier to find.
Kelly, Babbage –
Regarding upcoming changes to the LSL scheduler and obj->obj comms. I currently use llEmail extensively for Object to Object communications, and it works great for that purpose. I'm concerned that the large number of scripts (and related memory usage) will cause problems with the proposed scheduler changes and memory limits. llRequestUrl et al looks promising, but there's the headache of managing presence. Also, I suspect this method may actually incur more overhead than llEmail for obj->obj. What I'd REALLY like to see is just dropping the delay for llEmail in the case of obj->obj comms. If that's not possible, a specific set of zero/low delay functions for obj->obj comms would be nice. Is such a thing possible? Is it on the roadmap? --Doran Zemlja llRequestURL and http_request() are much more efficient than llEmail and will be the obj->obj comm method to get around the 20s sleep of llEmail.
Thx Kelly. What is the planned release date for 1.27?
http://sim3014.aditi.lindenlab.com:12046/cap/b180ede2-4850-c9d0-6d47-62f1e94fbefc
I need to compress these URLs. Is it safe to assume they will always be Is it safe to assume the port will always be 12046? Is it safe to assume the regionhostname will always end in .aditi.lindenlab.com or .agni.lindenlab.com ? Doran Q#1:
1.27 does not have an estimated release date. I don't even know if 1.26 has an estimated release date, but at the very least 1.27 won't happen until many weeks after 1.26 is fully released. Doran Q#2: The concept of a capability is that the url is a magic key, it is a whole entity, they are atomic in that the component parts don't have meaning or use. We could change the port or the host, the type of key used, add extra paths etc. Essentially if you make your scripts work such that they just treat the url given as the base url they will be portable and not break. If you dissect it and assume some parts then it may break in the future and you aren't allowed to get upset at us when they do. Or if you do get upset I think we are allowed to say "told you so". Something like that. Sorry. Thanks Kelly. I now have a compression scheme that will degrade gracefully if something changes.
That said, please bear in mind that we're very conscious of memory limits, especially considering Babbage's proposed scheduler changes. Shorter URLs, better. Regular, predictable URLs, better. For some definitions of better, yes I agree and I understand. These urls are about as condensed as they can be: the host name, the port, the key. The only real extras are "cap/" and "http://" (but you need the last to differentiate from http and https). "(grid).lindenlab.com" is only extra if you assume only Linden Lab will ever host regions, which is probably a bad assumption.
After thinking about this some more there is one assumption that is safe to make:
The base part of the cap url (everything except the key) can be assumed to not change for as long as keys are valid. If you are storing multiple caps per script, and they all point to the same scripted object you could store the "http://sim###.grid.lindenlab.com:port/cap/" part once then a list of keys for each cap. Sure it is a contrived situation maybe, but perhaps common for some usage scenarios. I am also discussing the idea of url-safe base64 encoded cap keys with an internal dev. This would in theory reduce the cap from 36 characters to 8. This would be essentially a presentation only thing: the same 128 bits that made the long cap could be encoded to the shorter base64 version to point at the same resource. I don't know if we will go anywhere with that, but it is an interesting idea. Dolan,
If you are trying to store a large number of caps/keys/UUIDs you may find this page of use: http://wiki.secondlife.com/wiki/Key_Compression But transferring in that form by http could be dicey. And unless the target server already insists on utf-16 it would prolly take more bandwidth. (and there's no way to change the content type of a response to utf-16 in the current proposed design anyway) Kelly, @Vampaerus: Looks interesting but I have to transfer these things via both email and http, so I think that's a nonstarter
Also, I've fought the +/ issue before, and settled on -_ ; both can url encode properly without escaping. (although the stock ll function escapes them anyway sigh ) Notice I mentioned url-safe base64. It is fairly standard (if not actually standardized) to use - and _ instead of / and + for url-safe base64.
You are right on the actual savings, dunno what math I was thinking. It would take 22 characters, really only saving 10. (I don't think 22 introduces any error: 128bits / 6bits-per-char = 21.33 characters) If we were caring that much we'd drop the dashes for a total savings of 14 characters. This does not seem worth the effort to me. Unfortunately I can't think of any more dense encoding that would be url safe. If such a function (to reduce a UUID to 14 characters) were made available as an LSL function I think it would be VERY useful. I send batches of deliveries to a dropbox via http response. Limited to 2048 characters, the number of keys I can stuff into one transmission directly effects the speed of operation. Currently 1024 (I have 1024 chars of metadata) / 36 = 28 keys (rounded down). 1024/ 14 = 73 (rounded down) ! Huge difference. I currently don't do any key compression because it adds enough delay (we all know lsl is a bit slow sometimes) that it would take less time to httprequest the server a second time and receive that response than do hefty compression. A nice speedy built in function might make the difference though =]
If you provide us a LSL function for it we can either construct our own external function (or you can give us the pseudocode) and you wouldn't need to do any fancy foot work on the server side. The benefit of this is all the other applications we could use for key compression. Keys are the life blood of everything in LSL. I'd say 4/5 major scripting projects involve storing a fair number of keys (whether texture keys, av keys, object keys, etc) Sorry Stephen I think you misunderstood. It would save 14 characters, the keys would be 22 characters. 1024 / 22 = 46. So, still a win but more like 60% and not 160% more keys.
Doing this in LSL is not very pretty or fast, here is a quick (rough) implementation that is not optimized for lsl: string base64_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
string hex_set = "0123456789abcdef";
string hex_to_base64(key id)
{
// Do this in 12 bits = 2 base64 and 3 hex
string sid = llGetSubString((string)id,0,7)
+ llGetSubString((string)id,9,12)
+ llGetSubString((string)id,14,17)
+ llGetSubString((string)id,19,22)
+ llGetSubString((string)id,24,-1);
integer i;
string out;
while (i < 32)
{
integer h1 = llSubStringIndex(hex_set,llGetSubString(sid,i,i));
integer h2 = llSubStringIndex(hex_set,llGetSubString(sid,i+1,i+1));
integer h3 = llSubStringIndex(hex_set,llGetSubString(sid,i+2,i+2));
integer b1 = (h1 << 2) | ( (h2 & 12) >> 2);
integer b2 = ( (h2 & 3) << 4) | h3;
out += llGetSubString(base64_set,b1,b1) + llGetSubString(base64_set,b2,b2);
i += 3;
}
return out;
}
key base64_to_hex(string sid)
{
integer i;
string out;
while (i < 22)
{
integer b1 = llSubStringIndex(base64_set,llGetSubString(sid,i,i));
integer b2 = llSubStringIndex(base64_set,llGetSubString(sid,i+1,i+1));
integer h1 = ( (b1 & 60) >> 2);
integer h3 = (b2 & 15);
integer h2 = ((b1 & 3) << 2) | (b2 >> 4);
out += llGetSubString(hex_set,h1,h1) + llGetSubString(hex_set,h2,h2) + llGetSubString(hex_set,h3,h3);
i += 2;
}
// Convert to canonical UUID format.
return (key)(llGetSubString(out,0,7)
+ "-" + llGetSubString(out,8,11)
+ "-" +llGetSubString(out,12,15)
+ "-" + llGetSubString(out,16,19)
+ "-" + llGetSubString(out,20,31));
}
default
{
state_entry()
{
key id = llGetOwner();
string b64 = hex_to_base64(id);
key h = base64_to_hex(b64);
llOwnerSay((string)id + " : " + b64 + " : " + (string)h);
if (id == h) llOwnerSay("Success.");
else llOwnerSay("Fail. " + (string)id + " != " + (string)h);
}
}
I get: [11:25] Object: 0e346d8b-4433-4d66-a6b0-fd37083abc4c : DjRti0QzTWamsP03CDq8TA : 0e346d8b-4433-4d66-a6b0-fd37083abc4c [11:25] Object: Success. There are a couple builtin functions that do half, tho a dedicated function would be way better. But in the meantime something else folks can try out below. One limitation is that all ints are 4bytes which makes chewing thru stuff messy. I chose to just manually work around the hyphens rather than use a loop and extra string functs to get rid of the hyphens. Not pretty, but saves a few ticks at the cost of script mem. Also the built in functs use slash and plus hence I brought it up in the first place. This raises consistency hiccups with designing a new funct. But for now if your purpose can live with /+ you can get rid of the two nested dump/parse cycles. But all-in-all the encode anyway is fairly smooth. If you're decoding serverside it might be useable. The LSL decode got yucky, mostly on the int->hex actually. There's prolly a better way. I did not run any explicit timing tests, merely tried to avoid costly string manips wherever I could.
ETA: Speaking of caffeine. Thanx for the multi-digit hex, alot nicer than shifting in one at a time (face-palm). Though I do still recommend working with 24bits at a time. It packs better, 22 vs 24 chars and is more "correct" if compatibility with another b64 routine ever comes into play. string keyToBase64(key k){return
llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,0,5))<<8),0,3)+
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,6,7))<<24|(integer)("0x"+llGetSubString(k,9,12))<<8),0,3)+
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,14,17))<<16|(integer)("0x"+llGetSubString(k,19,20))<<8),0,3)+
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,21,22))<<24|(integer)("0x"+llGetSubString(k,24,27))<<8),0,3)+
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,28,33))<<8),0,3)+
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(k,34,35))<<24),0,1)
,["/"],[]),"-"),["+"],[]),"_");//DumpParse
}//keyToBase64
key base64ToKey(string b){
string h="0123456789abcdef";
integer i;
b=(b="")+llDumpList2String(llParseString2List(llDumpList2String(llParseString2List(b,["-"],[]),"/"),["_"],[]),"+");
i=llBase64ToInteger(llGetSubString(b,0,3)+"AA==");
string k=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF)+llGetSubString(h,(i>>20)&0xF,(i>>20)&0xF)
+llGetSubString(h,(i>>16)&0xF,(i>>16)&0xF)+llGetSubString(h,(i>>12)&0xF,(i>>12)&0xF)+llGetSubString(h,(i>>8)&0xF,(i>>8)&0xF);
i=llBase64ToInteger(llGetSubString(b,4,7)+"AA==");
k+=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF)+"-"+llGetSubString(h,(i>>20)&0xF,(i>>20)&0xF)
+llGetSubString(h,(i>>16)&0xF,(i>>16)&0xF)+llGetSubString(h,(i>>12)&0xF,(i>>12)&0xF)+llGetSubString(h,(i>>8)&0xF,(i>>8)&0xF)+"-";
i=llBase64ToInteger(llGetSubString(b,8,11)+"AA==");
k+=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF)+llGetSubString(h,(i>>20)&0xF,(i>>20)&0xF)
+llGetSubString(h,(i>>16)&0xF,(i>>16)&0xF)+"-"+llGetSubString(h,(i>>12)&0xF,(i>>12)&0xF)+llGetSubString(h,(i>>8)&0xF,(i>>8)&0xF);
i=llBase64ToInteger(llGetSubString(b,12,15)+"AA==");
k+=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF)+"-"+llGetSubString(h,(i>>20)&0xF,(i>>20)&0xF)
+llGetSubString(h,(i>>16)&0xF,(i>>16)&0xF)+llGetSubString(h,(i>>12)&0xF,(i>>12)&0xF)+llGetSubString(h,(i>>8)&0xF,(i>>8)&0xF);
i=llBase64ToInteger(llGetSubString(b,16,19)+"AA==");
k+=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF)+llGetSubString(h,(i>>20)&0xF,(i>>20)&0xF)
+llGetSubString(h,(i>>16)&0xF,(i>>16)&0xF)+llGetSubString(h,(i>>12)&0xF,(i>>12)&0xF)+llGetSubString(h,(i>>8)&0xF,(i>>8)&0xF);
i=llBase64ToInteger(llGetSubString(b,20,21)+"AAAA==");
k+=llGetSubString(h,i>>28,i>>28)+llGetSubString(h,(i>>24)&0xF,(i>>24)&0xF);
return (key)k;
}//base64ToKey
Ouch. Try this, please.
string compress_key(string s) {
s = llDumpList2String(llParseString2List(s, ["-"], []), "");
return
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(s,0,7))),0,5) +
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(s,8,15))),0,5) +
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(s,16,23))),0,5) +
llGetSubString(llIntegerToBase64((integer)("0x"+llGetSubString(s,24,31))),0,5);
}
string strreplace(string str, string find, string replace) {
return llDumpList2String(llParseStringKeepNulls(str, [find], []), replace);
}
string integer2hex(integer in) {
string s = "0123456789abcdef";
string ret = "";
integer i;
for (i = 0; i < 8; i++) {
ret = llGetSubString(s, in & 0xF, in & 0xF) + ret;
in = in >> 4;
}
return ret;
}
string uncompress_key(string s) {
return
integer2hex(llBase64ToInteger(llGetSubString(s,0,5))) +
integer2hex(llBase64ToInteger(llGetSubString(s,6,11))) +
integer2hex(llBase64ToInteger(llGetSubString(s,12,17))) +
integer2hex(llBase64ToInteger(llGetSubString(s,18,23)));
}
string pad_dash(string s) {
return
llGetSubString(s, 0, 7) + "-" +
llGetSubString(s, 8,11) + "-" +
llGetSubString(s,12,15) + "-" +
llGetSubString(s,16,19) + "-" +
llGetSubString(s,20,31);
}
Thanks kelly, Vampaerus, and Doran! These functions all operate MUCH faster than one's I've written previously
I was referring to a built-in function, though, like string llCompressKey(key input) and key llDecompressKey(string input), which would undoubtedly be super speedy(er). I will try using some of these out though, as their ms time isn't too shabby. =] Thanks again. (sorry minor syntax error in the nonexistent function prototypes =P ) Doran, this might be the lack of coffee, but I think that by grabbing 8 hex chars at a time, you potentially (though unlikely) grab too much, because the max value for 8 hex chars is FFFF FFFF BUT the max value for a 32 bit signed int is 7FFF FFFF if I am not mistaken, so there is a potential to overrun the maximum value of the int. Perhaps you could utilize both sides of the signed int somehow ( I need more coffee before I think too much about that =P ) I think Kelly's implementaiton avoided this by converting directly from hex to b64, but I will need to look at it some more.
@Stephen, you need more coffee. That code is in production use, and works reliably. llIntegerToBase64 works just as well on negative numbers as it does on positive numbers. Think of them as unsigned integers and you'll see why.
I've produced a base 32768 compression scheme that will get a key down to 9 characters. Rather than pollute this issue further with compression schemes, I've updated https://wiki.secondlife.com/wiki/Key_Compression Doran, I looked at it again, and despite the fact that it is in production use, I believe it is still an issue. The reason it hasn't caused problems for you yet, is it would only cause an error if there was a straight segment of FFFF FFFF in a key, which is very very unlikely (though possible).
@stephen – The reason it hasn't caused problems is because it works just fine. Try this test harness with that code. I'd love to play mentor, but other than saying "think of them as unsigned values" I'm not sure how to explain it to you so that you'll understand.
test(key k) {
string compressed = compress_key(k);
key uncompressed = uncompress_key(compressed);
llSay(0, "testing: " + (string) k);
llSay(0, "comp "+(string)llStringLength(compressed)+" : " + compressed);
llSay(0, "uncomp : " + (string) uncompressed);
}
default {
state_entry() {
test(llGetKey());
test(llGetOwner());
test((key)pad_dash("00000000000000000000000000000000"));
test((key)pad_dash("ffffffffffffffffffffffffffffffff"));
test((key)pad_dash("0123456789abcdef000007ff0800a5a5"));
test((key)pad_dash("0000d800dffffdd0fdeffffeffffa5a5"));
}
}
Will you guys ever support the datamode "text/html"? It would kinda be abit silly not to support at least a rudimentary form of that? Then one could at least make some tiny userinterfaces with HTML instead of the way too old llDialog() buttons we got today.
We have discussed allowing text/html for specific browsers, specifically for your example. It would be possible to allow text/html for results to a browser window from within Second Life (or any browser that has a user-agent identifying it as being Second Life). This isn't currently on the roadmap and will not be part of the 1.27 release but may be possible at a later date.
As I understand it, the concern about allowing HTML content type is that users might be directed to a domain under secondlife.com or lindenlab.com and thus trust the interface as coming from Linden Lab. I'd like to suggest perhaps a second domain, or perhaps a sub-domain, that web users can be warned about. Perhaps even proxy the request on the simulator's web server, forwarding users with cookies enabled and no cookie present ("first visit") to a warning page describing that the contents of the "blahblahblah.com" (sub-)domain are contributed by users and cautioning about the submission of sensitive information. I'd expect, though I don't know a great deal about Linden Lab's network architecture, that it would be possible without too big a hassle to perform DNS resolution and handle HTTP requests in a parallel fashion for a second (sub-)domain.
Problem #1: dynamic URLs
Here is a free DNS service. http://www.everydns.com/aboutus.php There are more free dynamic DNS services out there, by the way. Problem #2: text/plain The firefox plug-in "modify headers" will work. Someone could make that plugin explicitely support some second-life content type changes by default (so SL costumers of some file-outputing tool can "just install it and it works"). Just be weary of not letting content type being switched to anything else than what is strictly necessary for the tool in question so we don't make virus writers, spammers, or griefers work too easy. Thank you for giving me this information. Makes perfectly sense to me. Keep up the good work on this, I already love the fact that you can at least request object data from outside servers/software like this. Its a major step in the right direction even tho it will not support text/html at first. I am very excited.
Our concerns for text/html are primarily focused on spoofing / phishing. It is trivially easy to create temporary "websites" that disappear and are somewhat difficult to track using this feature. You could imagine for example an email that contained a link to a task's web service cleverly disguised as an authentication url and page for some service - LL owned or otherwise. The object hosting this could disappear after a certain time frame (a few hours, maybe a day) or as soon as the page was used. It seems quite reasonable to limit this potential abuse if we can. Forcing the output of these web servers to plain text means you can't make a fake login page that someone inadvertently hits.
Most of the work arounds mentioned all seem reasonable to me. If you fake the user-agent or install a mod to view some text/plain pages as text/html you are moving yourself out of the group that would inadvertently hit a spoofed page - you've made some very explicit exceptions and taken deliberate steps. By nature it seems unlikely for any of these methods to create a group large enough that phishing/spoofing/spamming them would be worth the effort. If we built the functionality in to allow embedded browsers in SL to view these web servers as text/html (when specified by the script of course) we can add extra information and warnings to the viewer since we have some control of the browser in this case. There are many possible ways we could use to indicate to the user that the page they are viewing is hosted by an object in SL and give them access to some of the extra header information about object owner and location to help combat abuse. There are indeed a lot of dynamic DNS services (free and paid) out there. I've used DynDNS and ZoneEdit myself, with success. And many seem to offer a "WebHop" or "WebForward" service that will redirect a 'permanent' URL (port 80) to a different URL as specified. That latter seems to be what we will need here for persistent URLs.
What I haven't seen, though, is a service that lets the target URL be set dynamically from an URI-driven API the same way a dynamically-changing IP address is for the dynamic-IP DNS service. The services I've looked at all require a manual webform update to change the target URL (so: (tough and bulky to script and near impossible to maintain). Does anyone know of an API-driven WebHop/WebForward service? Or do we need to start beating on the various vendors to provide this extension to the existing redirection services? Trouble is, even with 3rd-party service offerings like this, we're going to end up with scripts embedded in objects that will go belly-up when/if the 3rd party service does – perhaps permanently. Persistence of service seems like a good reason for LL to host a URL redirection service and specify an API for it.... someday. I can appreciate the scaling issues, though! Coyote, that's exactly the type of DNS service I have been developing with HTTP-IN in mind. However I sort of let it slide to the back burner when it became apparent HTTP-IN wasn't coming anytime soon. I'm also still ambivalent about offering such a service to the public because I'm not sure to what extent it would be used and how much it would potentially impact my web host. The last thing I would want to do is host a service I couldn't sustain.
I really need to know more about how people would intend to use it. If they would use it for a few central servers, fine, but if they intend to have 3000-10,000 items out in the world with persistent URL's, thats not something I could see sustaining, at least not for free. Coyote,
I did much like you have done at first. I have an old "lifetime" account with dynDNS and assumed I'd be able to put that to use. Unfortunately &url= is still "reserved for future use". And trying to cURL it thru their human webAPI proved far more difficult than it was worth, and almost requires an intermediate server anyway. Putting pressure on dynDNS to get direct url functionality implemented would seem a viable option, but who knows how long. My searching for an alternative turned up nothing. Exactly as you said, most offer a url redirect of some kind, but not an easily automated update interface. So I too decided that a simple (and easy to find) solution to this is needed and set about making one. Much like Darien, the announcement that it had not made the 1.26 cutoff took some wind out of my sails, but not entirely. It is a commercial site which will be pre-pay as-you-go based directly on bandwidth usage. Seemed the fairest way versus monthly subscription which most won't fully use, and select few may significantly exceed. I'm not looking to become a millionaire but couldn't risk much capital either. I will offer different tiers of service from a simple dynamic lookup, to full html-proxy and was also considering an html-template service. The html-proxy part is still the part thats under heaviest development and I must admit, Kelly just gave me something else to think about. I have been considering requesting for beta testers, but have designed this from the get go as a commercial project and have been hesitant to mention it here as not to appear a spammer. But early on it seemed LL's "solution" was exactly this, to have others provide the solution. Darien and I are prolly not the only ones either. There's alot of time-will-tell going on which is personally driving me bonkers. Some of the comment (such as dynDNS and text/html) give me the impression that some are considering using this as a sort of webserver?
That seems very odd to me. I've been viewing this as just a method to send data into an object (from another object or an outside server). If the address isn't static, you can always just have the object register upon reset, or whenever the URL_Lost event triggers using http_request or llEmail. Considering that the URL appears to only really be lost when the region resets or region changes, it shouldn't happen excessively often. @Anthony R said
"If the address isn't static..." — that's not an "if"; it's a given. The external URI will be variable and essentially random as far as the outside world is concerned – see the Linden explanations on the mechanism. "... you can always just have the object register upon reset,..." – register WHERE, though? That's the point of the discussions on a sort of "dynamic DNS" scheme. In order to let the outside world know its current URI, the scripted object is going to have to 'register' that URI with some address-mapping entity on the external 'net – one that can be reliably located BY THE SCRIPT arbitrarily far into the future. The day someone's home-made address-mapping service goes down is the day the associated scripts in-world stop working (assuming no-mod scripts and lack of instant in-world creator support). Relying on a well-founded external address mapping service alleviates these concerns going forward. (Which is why, ideally, the Lindens would host that remapping service – but they said they will not.) "... it shouldn't happen excessively often." – one time is enough to make the end-user of your objects very unhappy. Where you can go in and tinker with your own scripts in your own objects... that's one thing. Expecting an end-user to go through some elaborate (and long-winded) manual procedure every time this happens... that's another matter. So I really think these concerns are quite valid even for uses well short of running miniature web pages from in-world objects (which the Lindens are discouraging; see above.) These are all valid issues. However, I think in short order these issues will be resolved much like the name2key issue was resolved. At one time (which many of you no doubt remember) the resolution of names to keys was a huge technical and ethical issue that was debated back and forth constantly. Now we have quite a few ways to resolve names to keys (many of them reliable) and it is a non-issue. Let's wait for this to rollout and gain broader appeal before we start declaring doom and the End Of All Scripted Things (tm).
To clarify, I was speaking more along the lines of 'if ... then ... else', but if you want to say 'when ... then' thats fine,
2 places come to mind, the server of the script creator, or a central object inworld. What I meant about happening excessively often is that it won't happen often enough to cause excessive pings to a website. If the URL changes, it should be transparent to an end-user that the script updates that information where necessary. If the URL changed to often, it would be a concern that lots of scripts would suddenly update, which could bring an external server down. I think all of these concerns are valid, but can be handled reasonably by careful script and external site design. I also agree with Stephen that there is no way we can solve everything before it it gets out, so getting it out for the masses to use would help flush out any other really critical flaws or needed features.
Frankly, the issue was never really a technical issue - it was relatively easy to collect the keys, and the whole subject is still a huge ethical issue. Its just that the sheer amount of key collection databases have rendered the issue impossible to handle, silencing most people. Either way, collecting URLs for llHTTPServer isnt really an ethical or a technical issue - more of an annoyance issue. I'm just surprised that LL cant afford supporting a DNS server. User supported services tend to vanish after awhile while scripted items tend to stay in the world for as long as the grid is going to stay alive. I'd really prefer having the domain resolution handled by LL where the DNS is assured to stay alive as long as the grid is. If LL is worried about the DNS server being hammered for requests, here's what i'd consider doing: Rather then allowing every single object to register - i'd limit the DNS to supporting a limited number of domain names per avatar. Say, 3 or 5. You can then assign these names to objects that can be used as sub-domain hosts that will store currently updated URLs of all of your personal objects. Its sort of the best of both worlds - take the pressure off LL, while still having the security of atleast one step of the DNS system always available and working. I agree with CrystalShard, on all points.
The use cases I'm thinking of this are generally sending an amount of data that a script would normally be polling for.
Either a central management object inworld, or an external server would have data to send to all its 'children' who have this http_server running so they don't have to poll that management object or external server (which doesn't scale well if your child product becomes widespread). My line of thinking is that even if the URL was static, or was made static by some DNS service, it wouldn't matter because if the management object or external server went away, those objects would lose that functionality anyways. What use cases are you considering where the DNS or a static URL would keep a product 'alive' even if the other side was gone? That might help frame what I'm misunderstanding. This is a general comment, not directed at anyone specific. Thinking about new technology in terms of old technology will usually lead to getting blind-sided. Thinking of this as a replacement for polling is a limited point of view. With new technology there will be new gadgets that make use of it in new ways. (Un)imaginable things. SL security orb on your RL cell phone. Think of a vehicle with an in-world lo-jack or GPS. Or a slave collar with lo-jack or GPS like tracking. Master can keep tabs on pet from any computer *cough*work*cough* with web access and not need to login. Any attachment or vehicle (technically possible) can produce large surges of updates during border crossings. Stationary web servers are unlikely due to other constraints (data servers perhaps), but in terms of dns-ish updates are largely irrelevant. That does NOT make the issue irrelevant. It makes that one possible use irrelevant. Looking at HTTP-In by itself without any other preconceived ideas, it is still clear that there is at least one gap. LL has stated they won't span the gap (for whatever reason). At least not yet. Many people can fill that gap themselves, and if you have that capability, and reliability is a concern, it's the only way to go IMO. There will be plenty who want to use the new technology, but don't have a technical enough background to build one themselves. They will have these 3rd party services to choose from.
I believe an in-world mediation server object is not going to help with use of HTTP-In. As far as I am aware, HTTP-In is meant as a replacement for e-mail and RPC to objects, and in large part because locating an object by key is too demanding and, "unscalable." That leads me to believe it will eventually be the only viable inter-simulator IPC method as well, which again introduces a chicken-and-egg problem. If I am mistaken, I'd love it if a Linden or someone with a (direct, verifiable, hopefully linked) source of information from LL could clarify, of course.
I'm not quite sure what you are looking for Hewee that I haven't already stated.
Http-in and Http-out are the magic bullet for communications into and out of SL. XMLRPC is definitely not scalable, and llEmail only slightly better. If your system can switch, please do when the time comes. Yeah. Sorry Kelly. I was responding to the suggestion about scripts using an in-world server object as a kind of DNS lookup server. It seems that would only be viable if llEmail() remained a stable form of inter-object IPC between objects in different simulators. I assume that if e-mail to objects from out-of-world sources is going bye bye then e-mails between objects in-world will suffer the same fate, as I can't imagine a significant difference in scalability for contacting an object by key from the external Internet vs. from a script on the grid.
I understand what Kelly is saying, and indeed - resolution by key is too much effort.
However, there's still a way for LL to allow domain -> capurl resolution without investing in a big resolution server. Allow me to elaborate:
llRequestAgentData(my_key, DATA_HTTP_INDEX); will return the following dataserver Data field: <cap_url>,<cap_url>,<cap_url> This is useful in two ways:
The result: Even if the DNS object gets returned or loses its URL, you can still restore its usability by updating the profile field to the current HTTP cap url - hopefully, automatically and via script. Coders will not hammer the dataserver more then they do already, since the scripts would (or should) be designed to query for the capurl list only if they lose contact with whatever object they were talking to, and have no other capurl to fall back on. What do you think? Is this feasible? I hope we can clarify something here. Is LL indeed saying llEmail will be going 'bye bye'? It seems to me that would break a lot of existing legacy content and there are still uses for such a feature, even if it's not scalable nor reliable. I would like to hear from LL exactly what the future fate of llEmail will be. Will it continue to exist, become depreciated, or be removed entirely?
And Crystal, That sounds good. If there's one thing that Scripters have been begging for, it's a way to store persistent data, even if it's the tiniest bit. We just need a toehold in-world, an external server is not the answer for everyone or every situation. I'm currently having to do something potentially risky just to store a persistent integer in-world and I don't like it one bit. But I have no other choice. AH! I can offer some clarification on those issues:
The issue I see with the profile solution is that there aren't any functions to write to a profile so you couldn't 'register' any way except by manually editing your profile unless you were to use an outside server like openmv to do it for you. And if you are going to do that, well, I think it would be just as good to maintain it out of SL completely anyways. If a function were to be introduced, then it could be done even in the notes or profile description section already (or in pick list info, or anywhere) without adding another set of data.
I think Kelly's idea for an optional registration is a good solution for those who want something LL controlled (so it is more likely to be around for the grid lifetime). However, I still think that considering http-in as a potential webserver (which is basically what I see would be needed for any use case that wouldn't have an external server) brings on a whole load of issues. I mean, it would be like running apache in every instance that would use this, which opens up many huge cans of worms. That's why I see it as a communications layer, instead of acting as an actual portal into SL for browsers. None of the current communications layers can do this (object UUID's change upon region reset, and XMLRPC does as well, and can actually be lost if it isn't used often enough). In any case, any of the ideas mentioned so far could be done using an external server, and none would even require http-in. I'm looking for use cases (of the non-webserver type) where having a static name is necessary without being dependent on some creator item (inworld object or external server). Thanks for the clarification Kelly.
@Anthony, I think it would be a narrow view to think those who want to have something persistent only want to use it as a 'web server'. HTTP-IN has a lot of potential to be used for object to object communications, as a faster, more reliable form of llEmail. However, given that both the sender and reciever has the potential to 'change keys' suddenly, it can be problematic. It's a shame to say someone must buy/rent an external server just to manage addresses of in-world objects. It can be done, and likely will be done, but it's just kind of sad. We've had to deal with the same issues with llEmail for years and really there's a lot of things I built and never released, as I felt they simply would never be reliable enough given the transitory nature of keys/addresses in SL. It may be LL banks on that sort of thing, to keep the amount of communication low. But I can't say I favor that approach, if it's indeed the case. For Crystal's proposal, I think you should read again, She's talking about additional hidden fields that would be added to a profile, accessed by script only. So yes, there would need to be a new function to write to these fields. To prevent random scripts from writing random junk to the fields, I think it would be necessary to implement some sort of access restriction. If my application uses slot A, I don't want some other application overwriting it. Of course this starts adding more complications and I can see where it can begin to get out of hand. If I thought there was a chance it would be implemented I might sit down and really work something out but, I'm never a fan of wasted efforts. Crystalshard's suggestion is interesting, but I don't see how it would mitigate the fact that a registration service would cost LL in hardware and maintenance. Storing this information in the profile would just move that load over to the servers that hold profiles, not avoid it entirely.
While CrystalShard's idea sounds attractive - I suspect that there are lots of issues with allowing LSL to write to the profile. I suspect it'd open a can of worms that LL aren't prepared for at this time.
The thing that quite a few folks here seem to have missed, is that unlike XML-RPC and similar, part of the HTTP-IN implementation gives us an event that we can use to tell when the URL has changed. This means in the change handler we can use some code to tell any other objects that need to know our URL the new details. That way object / object comms can be self maintaining - each time an object knows its URL has changed, it updates its peers...and so on. The cases where the URL change are actually relatively rare, so it's not going to add a lot of work - unlike the current situation with XML-RPC. I have a timer set to check the current XML-RPC for my object every 1o minutes, and if it's changed, it tells my webserver - a total waste of resources that HTTP-IN will remove. Yes it's not ideal - but it's a vast improvement on what we've got, so let's get it implemented quickish! Yes Hippyjim, don't get me wrong, I am eagerly awaiting HTTP-IN.
So two people in two sims both have an attachment on, that talk to each other. Somehow, mysteriously you have got them talking, each knows the other's key. The two people take them off about the same time. Then person A puts his back on. on_rez() fires,and the item says "oh, my key has changed", and tries to tell it's new key to the other attachment on person B. But it's not being worn, and once it is put back on, it's key has too also changed. now neither can talk to the other, and there's no way, save both of them talking to some 3rd party who's address doesn't change, to re-establish that communication. This has been the problem with llEmail and XML-RPC for years and sadly, also remains the issue with HTTP-IN. I'm probably preaching to the choir but It's one of my favorite sermons. @Hippyjim "Yes it's not ideal - but it's a vast improvement on what we've got, so let's get it implemented quickish!"
Given that the email() event has been unusably broken since around 2005 (SVC-23) and XMLRPC is (unofficially) deprecated, I'd rather email was fixed BEFORE another new method is introduced. Actually, I don't know why LL is spending resources on this new feature when there are a huge and growing number of grid platform bugs that need fixing anyway. Perhaps getting the Mono script engine in shape so that it can at least run the scripts that the old LSL engine can run would be a good idea first. (We had to switch thousands of users back from Mono to LSL scripts to patiently wait for Mono to become a bit more stable - but it is starting to look like LL is going to leave it broken while they implement more features. We have a business to run and users don't care about explanations like "LL is working to improve the stability of the new Mono script engine" - they just want their products and services to work, which for us means not using Mono due to the various script halting exceptions it causes - SVC-2908) Having said all that, we (apez.biz) will be announcing a free scalable public service to track server URLs using a DNS solution. I realize people have concerns about investing in 3rd-party services that might disappear if a company goes bankrupt, but honestly, LL could go the same way. Our other public APIs have been around for years already. It is a mash-up world. Take it or leave it. I'm looking forward to HTTP-IN if it is robust and we're already developing for it, but honestly I hope it is delayed to receive MUCH much more testing that LL typically puts into features before deeming them 'release' ready. I've not been following in detail, or testing. I'm just waiting for the dust to settle before I try it out and perhaps don't fully understand the dynamic URL problem or is my situation elementary compared to other applications?
Currently I have objects polling a data base every 10 seconds to check if there is an HTTP-IN message waiting for them. It is clumsy but it works. With HTTP-IN, could I not have each object report its URL to a new slot in the database whenever a situation arises that changes the URL? And if necessary report once an hour just in case? That would be a reduction in traffic of 99.7%. If there was a transition situation where a new URL report came in, outgoing messages for the last 10? seconds could be repeated as duplicates. The objects automatically log in when rezzed or worn now, so it would be an elementary change. @Darien: You can still have object to object communication without persistent addresses. The example that you mention where two people in 2 sims need their objects to talk to each other just requires a 3rd object that both can either register with, or at least use to negotiate a connection. You would have that problem no matter what communication method (email / x lRPC / HTTP-in) you used. With a 3rd object (or possibly 4th, 5th, or more for better robustness) in other regions, it would reduce the likelihood that all would go down at the same time and require intervention of some sort.
For a case like that, they must register somewhere. Whether it is an external server (DNS or URL tracking), a 3rd inworld object 'server', or LL run registration service, you couldn't avoid that. I am guessing here, but having keys/URLs themselves be persistent isn't feasible likely either due to database growth or a complex management of how items are populated within a simulator (when a new item is added how would you know it was the same one and not a copy) One other possible thought is that both objects could fallback to sending an email to the owner's address (from a notecard, etc.) that comms have failed and how to restore it by sending information in one email to an address in another which would restore the communication. (Could also be done via IM I suppose). That way the scripts wouldn't have to rely on any 3rd party at all (except the owner) which is what some have mentioned as being problematic. an idea I just got, I can't figure out if it would be feasible or not
distributed-mesh-like-DNS: it would be somthing like, people volunter one address of their quota to store a certain number of records, plus the address of other DNS servers, if the requested name isn't found locally, it relays the request to some of the other servers randomlly, the server that finds the result sends the data directly to the address that requested it. Scripts can request that an record be created for their address and an URL, if the server that received the request already got too many records, it relays the request to other DNS servers it knows about picked randomly, the servers that create a record will report the succses of the request and the server's own address so the script can if desired, store that DNS server address for future use. Details like time to live, pings and other things inspired by regular networks should be discussed by people that knows mroe about such things to see how it would be better. If enough people volunteer to host a DNS server I believe a system like this might become quite resilient. @anthony:
It is possible to do this sort of thing without a central server by using a distributed hash table. The Open Stargate Network works this way. see http://ma8p.com/~opengate @TigroSpottystripes:
See previous comment. sure, no need to reinvent the wheel if we already got one that rolls well enough
@Doran:
Yes, a distributed network of servers would work much better then a single central database, and it would be best if they were spread across many different owners/organizations. I believe that most DNS is distributed anyhow, but there is still a single point on entry for registration to start, and a record maintainer (allows entry changes and propagates to others.) whether they were external webservers or inworld 'object servers' wouldn't matter, though I imagine the external web servers would be more scalable and efficient. there are some decentralized darknets that use distributed DNS in a first come first served basis, and they do things like using hashs, public/private keys, and msg signing and such for control over domains and other data (updating, deleting etc), there is quite a bit of info about how some of these distributed darknets work on Wikipedia
if you wanna know more, perhaps you probably could start with http://en.wikipedia.org/wiki/AnoNet
@Lex:
The fun part about my suggestion is that it does not move the load to the profile servers entirely: By limiting the number of entries you can save within your profile, it will force you to use your own, LSL made DNS server. Its not intended to store all of your capability URLs on the dataserver, and not intended to be refreshed constantly. Thats why its design will discourage such use and instead try to push people to use their own DNS servers with the profile fields only used as a pointer to that DNS server in case of a prim failure (auto return, delete, etc) @anthony reisman: The reason for manual editing being superior is that it will force people to use this field only to point at their DNS service prim and avoid using it for anything else that may hammer the dataserver with updates - because their LSL based domain name server will be easier to update automatically compared with the profile that must be edited manually. I have made a small script that i use for retrieving data (dns) stored in my profile. http://pastebin.com/f6d179b10
That is a inventive way to do it too, you would have to be certain that your script is secure enough though. People will try them and see what they spit out or do.
Can we rely on all links being on either port 80 or port 443? The examples on http://wiki.secondlife.com/wiki/LSL_http_server
I ask because I'd like to use Google App Engine to create services that interface with LSL scripts through http-in, but App Engine's urlfetch service is (deliberately) limited to ports 80 and 443. See http://code.google.com/appengine/docs/python/urlfetch/overview.html#Requests Is there any reason to use non-standard ports in http-in? The examples on the wiki page you link do NOT mention 80 or 443 that I can see. I specifically didn't put ports in my example URLs, but I think that gave the wrong impression. A full URL looks like:
http://sim3015.aditi.lindenlab.com:12046/cap/3ff4f3f2-ea08-76c1-cef6-a22b4a573a7c or https://sim3015.aditi.lindenlab.com:12043/cap/a7717681-2c04-e4ac-35e3-1f01c9861322 These urls are atomic, and the port is part of that. It is possible the port will vary between url requests, just as the host might (for example if the region restarted and the simulator came up on a new host). I'm not sure on google app engine's reasoning for limiting request ports but it is unfortunate in this case since it will not be compatible with this feature. For your last question: We run a fair number of services on each simulator host. The cap server is far from the first, and does not get the standard ports. Probably just me. Given the length of discussion, both here and on sl-dev ----- wouldn't it have been simpler to just fix up the original xml-rpc? As I say, probably just my super-naive, super-simplistic, super-stupid idea.
Discussion is good. And unfortunately it would not be easier to "just fix up" xml-rpc. Our xml-rpc implementation is fundamentally busted, mostly for the reasons that cause discussion on this feature. Fixing it would cause many of the same discussions and concerns.
Also, just to make sure everyone is on the same page. This feature is complete and on aditi right now on the regions labeled 'http-in sandbox'. It will be deployed to agni with server 1.27 as it exists on aditi.
Thank you for the quick answer Kelly! Yes, it's very unfortunate that App Engine will be incompatible with this feature. To clarify, I didn't mean to say that the examples on the wiki mentioned ports 80 and 443, but by using "http" and "https" urls without specifying the port, they do use only 80 and 443. Any objection to me modifying the wiki page to use the url examples you just provided, instead of the port-less ".agni" ones it uses currently?
Updating the wiki thus would be fine.
I don't know the technical details, but aren't there free proxies that would allow reading the data using default ports while the endpoint is actually using non-standard ports?
https://wiki.secondlife.com/wiki/LSL_http_server
Alright - I see the mention that this functionality will be relased with server 1.27 ... do we have a timeline on when 1.27 will be released to the main grid? Seeing the functions listed as "currently active" on the LSL Wiki has me feeling stalemated on my updating of web-communications in-world scripts and web-end programming ... not to mention that I'm sure having the functions listed as "currently active" has confused any number of scripters who are probably wondering why they can't get their scripts to compile with those functions in them
If I were to re-write my XML-RPC communication protocol ... how long would it last until HTTP-IN was released? If I release a new product heavily reliant on XML-RPC communication (as I am planning to do in the next 2-3 days), how long would it be valid before I needed to essentially force all buyers to update? 1.27 will be in beta, on the beta grid *very soon now. HTTP-In is already on Aditi, look for regions with http-in in their name.
My personal wish would be for you to build out and test your system on aditi (where there are regions with HTTP-In now, and will be regions with 1.27 w/ http-in soon) and then wait to deploy live until 1.27 is on the main grid. I completely understand however that timing is always important and it may not be feasible to delay your product deployment until the undefined release of 1.27. It is also difficult to transfer complex objects / systems from beta to main grid. Which is why I'm just trying to give as much information to you as I have.
Thank you Kelly ... I understand that release schedules are never exact ... I just don't want to release something that is out-of-date the next day.
The current project I'm looking to release will have XML-RPC communications about twice / day / object ... current number of objects in world is about 100 ... so the load is very low. I've got several other products reliant on XML-RPC (as it's currently the only way to initiate comms from the web), but they are similarly rare in communication frequency (most average around 10 comms / day). I'll re-build my web-comms script for HTTP-IN and test all my products on Aditi so that I'm at least ready for the switch whenever it happens - but 4 weeks is a bit too long for me to wait for product release (especially because the 10 and 20 after make me a bit leery). Thanks again for the info. Quote: Seeing the functions listed as "currently active" on the LSL Wiki has me feeling stalemated on my updating of web-communications in-world scripts and web-end programming ... not to mention that I'm sure having the functions listed as "currently active" has confused any number of scripters who are probably wondering why they can't get their scripts to compile with those functions in them
Given that many are concerned about resolving the URL for their service, and it frequently changing, and the discussions about the longevity of 3rd party services, and the costs associated with having a web server, It became clear to me the best solution was something low cost (or even free), under the user's control, and which could be used by virtually anyone (no pun intended). So head to this post on the forums to see how to set up your own Dynamic DNS service using the freely available Google App Engine. http://forums.secondlife.com/showthread.php?t=323981
I still think a distributed system (completly in world or otherwise) would be better, no issues with single point of failure, less reliance on resources managed connected to a single person etc
if done well I believe it will quite fault-tolerant, resilient and scalable Hey Kelly,
First of all congrats on getting this feature implemented. I was testing it extensively on the beta gird now that 1.27 server there and it works very well. The only crippling problem I encounter is limiting query string to 255 characters. Let me try to explain a bit. The way to get data to LSL scripts can be via POST request where you can send up to 2K of data. The problem with POST however is that its not "redirectable". Because we would need to have some external name service, it would be optimal to use it with a GET request which will transparently return a 302 with Location: of the last registered llGetURL(). I have implemented such a service and are testing it atm on the beta. So for example no matter how many times I request: http://gridurl.appspot.com/go/4bf16fdc-4968-40b6-8e39-dca23e4b0767/?foo=bar It will always send the request to the appropriate URL including passing on parameters passed in the query string. So I can have another object using llHttpRequest() always use this url and pass the data to the destination object. This transparent redirection with POST is not possible, therefore limiting the query string to 255 becomes more problematic. Are there any reasons why we cannot have query string header have the same limit of at least 2K since GET request don't have a body. Or if the request type is GET pass the query string as the body (doing this will actually make it transparent to the script no matter if data was sent via POST or GET). can the purl services ( http://purl.org/
and would the usage by scripts be bellow the abuse threshold? Tigro: I don't really know much about purl.
Latif: Transparent redirection with POST is possible, just harder. Well, you may lose some header information if for example you have the persistent url service make the full request on behalf of the requester instead of just returning a redirect. The capability server that hosts the url does this - acts as a real proxy to forward requests, even posts, puts and deletes, to the simulator host. Unfortunately I don't think we can raise the limit on the query string. To do so we would have to lower the max body size or have a 'max total size' shared by them which I think would just be too confusing in practice. Lex: I just added a new blog which you saw, but yes http-in should be real soon now. Assuming everything goes smoothly during the pilot roll of course. Kelly: Redirect of POST is not possible, proxying POST is, but that's a whole different issue. Since there is no body in GET request, is it possible to return full query string as the body?
Latif, You may want to look at my service, which is similar to yours, and consider adding the ability to retrieve the actual URL as an alternative to redirection only. When I first wrote my service I didn't support redirection at all, because of the issues you cite. I have since added it due to popular demand, but for handling large amounts of Data, it's probably better to retrieve the actual URL and talk directly rather than going through a redirect. Saves on your Google resource limits too.
Tigro, after reading their FAQ, it seems HTTP-IN could probably use such a service, however, I don't see they provide any automatic method of creating or updating PURLS. The source code for their service is available, so you could run your own modified version that was set up for that purpose. But then you're back to the original issue, having your own server. I'd really recommend trying something along the lines of what Latif and I are doing, It's literally 0 cost and works very well.
This is now live in Server 1.27.
The example wiki page has been expanded: And there was a recent blog post as well: Yay! Was anything ever done about allowing through the extra SL HTTP headers injected by llHTTPRequest()? I see no indication of this in any of the wiki pages. If so, are all of those headers passed through, or only a subset? Is the 255 character limit on headers for EACH header, or for all headers put together (ouch! considering those URLs are pretty long...)? If the latter, has any exception been made for the llHTTPRequest() injected headers?
Yes, the extra headers from llHTTPRequest are available via llGetHTTPHeader.
All of them are passed through. The 255 limit is per header. Shameless plug: Developers, if you're looking for a reliable URL redirection service specifically for SL, Apez Corp has just launched one.
See here for details: http://wiki.apez.biz/Development (It is implemented using Amazon's cloud computing infrastructure, if you're curious) If anyone has something neat they have done with http-in please let me know! I want to hear about any success stories (also any difficulties).
Prims as servers is a very cool idea.
I related this issue to SVC-3297 because it's such a pain to use only global variables with the numerous state changes required for the app I'm working on. State-scope variables would make it so much more convenient and portable. RE:
kelly linden: If anyone has something neat they have done with http-in please let me know! I want to hear about any success stories (also any difficulties). ------------ I was trying the PHP example for a update server system that uses my PHP and MySQL - even the example script and PHP seems not to on the live grid. Have I missed something?
Re: If anyone has something neat they have done with http-in please let me know! I want to hear about any success stories (also any difficulties).
We are close to rolling out a whole new freebies system for NCI. We are now using http-in. It is not something that is novel, but in our initial tests the latencies and script over head have dropped dramatically. On the http-in side of things there have been almost no difficulties, and it has been amazingly smooth. Kudos to a job well done. Your efforts have made our jobs a lot easier, thank you! PS: As a bonus, the http-in has also made it much easier for us to include automatic updating that will be a great help to us in the future. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Kelly, does the fact that this is listed as critical mean that it's a fairly high priority on LL's plate to get it implemented ASAP? and if so when might we see it at least in beta form?