Expose http client sockets to "luup-plugins" / "requests.lua" namespace

Hello Ak, I’m trying to get socket object from:
“development/openLuup/io.lua”, line 491
to “development/openLuup/requests.lua”, line 787

Please, would you show workarounds to get that socket-object and make scheduler.socket_unwatch() for it in “requests” code? or, if not, maybe, would it be possible to discuss the possibility to provide patch to openLuup that will expose altUI<–>luup sockets" to “openLuup/requests.lua” code (so it will be possible to take control on socket). I can write a patch.
I just need to know for now, if such a patch be acceptable ideologically to the project.

This will allow to provide continuous/delayed response sending for luup requests but to avoid complex “async_send” mechanisms or openLuup-core major modification.

1 Like

@akbooer Here is a old implementation approach but We believe with your opinion it is possible to tune it a get it just right.
from https://github.com/ronluna/openLuup
openLuup/requests.lua, line 1243:
client_sock = shared.get_current_client_sock()

http server puts clients sockets into global table into “shared.lua”, and requests.lua takes them from there

Hi there.

You are trying to get access to the socket related to an incoming data_request?id=request_image call, is that correct?

If so, then be aware that not all requests arrive over TCP, so there may not even be a socket. This would be the case for a luup.inet.wget() request issued by the same openLuup instance to itself (plugins do do this!) So whatever special code you add would have to deal with that case.

scheduler.socket_unwatch() is already available to you in the requests module, so all you need is the socket itself. I’d be interested to know what you’re planning to do with it after unwatching it!

It seems to me, after a quick look, that the simplest way to get at the socket would be to have it passed as an optional fourth parameter to the standard request handler, so the parameter list would look like:

local function request_image (_, p, _, sock)

and you could use this directly to unwatch and do the rest of the I/O asynchronously yourself. You might get spurious “EXPIRED” messages in the log, depending on how you handle the socket and whether the specified timeout for the HTTP server is exceeded.

I think that this would be a straight-forward change which could be in the baseline, and the fourth handler parameter would be available to ALL luup request handlers (including user-defined ones.)

Does that help?

AK

@akbooer

You are trying to get access to the socket related to an incoming data_request?id=request_image call, is that correct?

Yes.

I’d be interested to know what you’re planning to do with it after unwatching it!

There are two practical cases I could need that socket for now:

  1. request_image retrieves image from camera for too long sometimes and blocks engine for several seconds during process. In case of many cameras in configuration it become a problem. In this case I need image retrieving “in background” (let engine continue working until image on camera will be ready, transfer data by small portions, not blocking engine for too long, then close it after use for simplicity of implementation. but, maybe it would be good to return socket-to-user to scheduler again)
  2. In several past implementations, request_streaming requested streams from video camera. It captured socket and forwarded data from camera continuously after posix.fork(). In many cases, socket was closed on user side, so there were no need to return socket to luup-engine-scheduler after use. Video data forwarding over Lua-code was inefficient, so we search more efficient (but easy to implement and support) way to forward videostreams for home automation these days. It is no final solution yet. I guess, request_streaming that forwards video stream over Lua-code can be used several more times in future, until good solution will be implemented or as backup to this “good” solution.

It seems to me, after a quick look, that the simplest way to get at the socket would be to have it passed as an optional fourth parameter to the standard request handler…

so simple. let me do this then.

Does that help?

Yes, Thanks. This was almost all info I wanted to get.

If so, then be aware that not all requests arrive over TCP, so there may not even be a socket… [INTERNAL REQUESTS]

Can sock=nil as fourth parameter of request callbacks mean that it is non-TCP request?
or it would be better to place flag
server.current_request_is_internal -- is true or false
or
server.is_current_request_internal()
somewhere in global namespace? What do you think?
In case it will be a flag or is_*() function, in what module will be better to place it?
Or, maybe, it better to place it into 2nd parameter “p”:
p.request_is_internal = true?

No need, it’s already in the latest development version v19.11.29

Yes, that’s exactly what it means.

I’ve updated the id=test request handler to show the value of this additional parameter.

This request:

http://openLuupIP:3480/data_request?id=test&foo=garp&output_format=xxx

yields:

data_request:  id=test
output_format: xxx
client_socket: tcp{client}: 0x2197018
user_parameters:
  foo=garp

but runnning this Lua Test code:

local _,x = luup.inet.wget "http://0.0.0.0:3480/data_request?id=test&foo=garp&output_format=xxx"
print (x)

gives:

data_request:  id=test
output_format: xxx
client_socket: nil
user_parameters:
  foo=garp

Enjoy.

AK

1 Like

Many Many Thanks!

© 2019 Vera Control Ltd., All Rights Reserved. Terms of Use | Privacy Policy