Websocket in for LSL
closed
Chaser Zaks
The pitch:
Websockets are a web standard based off the HTTP protocol that allows bi-directional communication between a client and server. In this case, LSL would be the server. A client could be a web browser or another server hosted by a resident.
What makes this different from LSL HTTP is that with Websockets, you are able to keep a session open and communicate back and forth without having to continuously make HTTP requests. Think of it like Websockets is going to someone's house to talk, versus HTTP being sending a letter back and forth over the mail.
Use cases include, but are not limited to:
* Live chat, including that of with an AI
* Time critical syncing such as lighting effects
* Real time input from external sources
The current alternative we have is LSL HTTP, which can be used to behave like websockets, but instead use what is called "HTTP Long polling", which includes issues such as latency and HTTP request overhead, where as with Websockets, once the headers are sent, it is just a chat back and forth without the need for additional headers.
Feasibility:
Websockets use a "message based" system, in which each message is a frame. Each frame has a max size that the server can choose to reject if it is too big by sending a "Frame too big". This is perfect for LSL as it can be limited to specific frame sizes as to avoid stack heap collisions.
Additionally, websockets supports "Binary" and "Text" modes, which LSL can choose to only support text mode (for now), which fits with LSL's strings.
Implementation considerations:
I can think of two ways for this, one would be a single session per object, or single session per region solution. Both have their pros and cons:
* Per object: It is simple, don't have to worry about addressing different handles / scripts / objects, is similar to llRequestURL's syntax. However, you have to open a session for each object you want to communicate with on the region.
* Per region: Slightly more complex, have to specify an handle / script / object ID each frame, but endpoint would be shared between objects.
* Best of both worlds: Make it scripter's choice! (During initial llRequestWebsocket or whatever the function shall be called)
Log In
Maestro Linden
closed
Hello, and thank you for your feature request.
Incoming suggestions are reviewed in the order they are received by a team of Lindens with diverse areas of expertise. We consider a number of factors: Is this change possible? Will it increase lag? Will it break existing content? Is it likely that the number of residents using this feature will justify the time to develop it? This wiki page further describes the reasoning we use: Feature Requests
This particular suggestion, unfortunately, cannot be tackled at this time. However, we regularly review previously deferred suggestions when circumstances change or resources become available.
We are grateful for the time you took to submit this feature request. We hope that you are not discouraged from submitting others in the future. Many excellent ideas to improve Second Life come from you, our residents. We can’t do it alone.
Thank you for your continued commitment to Second Life.
Jeremy Duport
I have a good few projects that websockets on the LSL side would drastically simplify. For example, the most practical current way to talk to MOAP HUDs is by updating their URL with data serialized as an anchor/fragment (foo.bar/baz
#blahblah
), which is noticeably slower than ideal because it has to rely on script->world queue, world->viewer LLSD passing, then viewer->dullahan IPC -- and that's only one direction.A single global port provisioning virtual endpoints with UUIDs would be in keeping with the requesturl pattern and provides decent traffic privacy; sort of webhookish. Negotiation would be a little odd, perhaps. A client trying to start talking to your endpoint would have to know the right region url and uuid to specify in the first place, which is a bit limiting in terms of use cases, and the world would need to assign identity to clients so that they can be talked to.
I feel it would be most practical to only allow one endpoint per script (or even per object) so, a cludgy potential surface:
// Ask the current region for an endpoint.
llRequestSocket(list options);
// Tell the current region we're done with our endpoint.
llReleaseSocket();
// Try to send a message to a client, returning a signal value below.
string llSocketSend(key client_uuid, string message);
// An attempt was made. This is websockets, not HTTP!
#define SOCKET_SEND_OK ""
/* An attempt was not made. client_uuid is not known to the region.
It's either incorrect or they have since disconnected somehow. */
#define SOCKET_SEND_INVALID_CLIENT "U+E005"
#define SOCKET_REQUEST_GRANTED "U+E001"
#define SOCKET_REQUEST_DENIED "U+E002"
#define SOCKET_CLIENT_JOIN "U+E003"
#define SOCKET_CLIENT_LEAVE "U+E004"
socket_message(key uuid, string message) {
if (message == SOCKET_REQUEST_GRANTED ) {
/* We already or newly have an endpoint.
uuid is our endpoint. */
}
else if (message == SOCKET_REQUEST_DENIED) {
/* The region refused us a socket.
uuid is NULL_KEY. */
}
else if (message == SOCKET_CLIENT_JOIN) {
/* A client has successfully negotiated a connection.
uuid is the client. */
}
else if (message == SOCKET_CLIENT_LEAVE) {
/* A client has told us they're leaving OR been timed out.
uuid is the client. */
}
else {
/* We have a message from the client!
uuid is the client. */
}
}
I specify a
list options
in llRequestSocket as it could be used to set a maximum expected message size, ask the server to handle heartbeat behavior for us, etc.Also good lord canny's markdown behavior and layout are horrendous. Give back my content width.