Home of the Squeezebox™ & Transporter® network music players.
Page 1 of 2 12 LastLast
Results 1 to 10 of 13
  1. #1
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204

    call a Perl function in an html page

    Hi - Is it possible to call a Perl routine onclick of a button in the basic.html page? I know I can do a JS, but I'm 0.0 in JS. All I want is to send a POST to an host that will be a parameter to the call (no return expected, just need to do the POST, that will trigger a pin code to be displayed on the host and that code should be captured through the JS prompt box)
    Code:
    [% "PLUGIN_RAOPBRIDGE_PLAYERLIST" | string %]
    
    
    
    
    function getPIN() {
    var PIN = prompt("Please enter PIN code");
    document.getElementById('pincode').value = PIN;
    }
    
    
    
    [% FOREACH entry IN devices %]
    [% IF entry.udn != '.common.' %]
    
    [% entry.name %]&nbsp[% entry.mac %]&nbsp[% entry.udn %]&nbsp[% entry.friendly_name %]
    &nbsp
    
    [% END %]
    [% END %]
    Last edited by philippe_44; 2017-07-05 at 00:05.
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  2. #2
    Babelfish's Best Boy mherger's Avatar
    Join Date
    Apr 2005
    Location
    Switzerland
    Posts
    19,746

    call a Perl function in an html page

    > Hi - Is it possible to call a Perl routine onclick of a button in the

    Now you'd expect a clear NO! But there's always an exception to this
    answer: you can install Perl on Windows and as part of this it would
    install PerlScript.

    http://docs.activestate.com/activepe...ml#client_side

    But that's likely not what you wanted to hear :-).

    > basic.html page? I know I can do a JS, but I'm 0.0 in JS. All I want is
    > to send a POST to an host (no return expected, just need to do the POST,
    > that will trigger a pin code to be displayed on the host and that code
    > should be captured through the JS prompt)


    There's no way around JS. And you'll likely have to implement a handler
    for this in your plugin, too, because JS usually can't reach out to
    servers other than the one where it was loaded from for security reasons.

    So you'll need:

    - a JS snippet calling LMS
    - a page handler in your LMS plugin calling the remote server

    --

    Michael

  3. #3
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204
    Quote Originally Posted by mherger View Post
    > Hi - Is it possible to call a Perl routine onclick of a button in the

    Now you'd expect a clear NO! But there's always an exception to this
    answer: you can install Perl on Windows and as part of this it would
    install PerlScript.

    http://docs.activestate.com/activepe...ml#client_side

    But that's likely not what you wanted to hear :-).

    > basic.html page? I know I can do a JS, but I'm 0.0 in JS. All I want is
    > to send a POST to an host (no return expected, just need to do the POST,
    > that will trigger a pin code to be displayed on the host and that code
    > should be captured through the JS prompt)


    There's no way around JS. And you'll likely have to implement a handler
    for this in your plugin, too, because JS usually can't reach out to
    servers other than the one where it was loaded from for security reasons.

    So you'll need:

    - a JS snippet calling LMS
    - a page handler in your LMS plugin calling the remote server

    --

    Michael
    Thanks Michael - Understood, though it still sucks as I'll have to do all that for a very simple function that is likley used once in the lifetime of the plugin, just for pairing ... anyway
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  4. #4
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204

    Keep-Alive on SimpleAsyncHTTP?

    So, one problem at a time with this AppleTV pairing ... I need to make sure that the HTTP connection is kept alive during the whole exchange. Is there a way to keep-alive a SimpleAsyncHTTP? I guess no (looking at the code a bit), so what the best advice to do that? I was thinking of overloading Async::HTTP::_http_read_body to not close the socket and Async:HTTP::_http_read_body to not insert a Connection: close
    Last edited by philippe_44; 2017-07-06 at 00:44.
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  5. #5
    Babelfish's Best Boy mherger's Avatar
    Join Date
    Apr 2005
    Location
    Switzerland
    Posts
    19,746

    call a Perl function in an html page

    > So, once problem at a time with this AppleTV pairing ... I need to make
    > sure that the HTTP connection is kept alive durin the whole exchange. Is
    > there a way to keep-alive a SimpleAsyncHTTP? I guess no (looking at the
    > code a bit), so what the best advice to do that?


    I'm not sure I follow: an HTTP connection would only be closed when the
    server has responded, or after some timeout. The timeout can be set in
    the request in LMS. What else would it have to wait for?

    You can add custom headers to the request as the last parameters in the
    get/post call. You need to add them in pairs: first header name, second
    header value.

    --

    Michael

  6. #6
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204
    Quote Originally Posted by mherger View Post
    > So, once problem at a time with this AppleTV pairing ... I need to make
    > sure that the HTTP connection is kept alive durin the whole exchange. Is
    > there a way to keep-alive a SimpleAsyncHTTP? I guess no (looking at the
    > code a bit), so what the best advice to do that?


    I'm not sure I follow: an HTTP connection would only be closed when the
    server has responded, or after some timeout. The timeout can be set in
    the request in LMS. What else would it have to wait for?

    You can add custom headers to the request as the last parameters in the
    get/post call. You need to add them in pairs: first header name, second
    header value.

    --

    Michael
    But if client sends Connection:Close, the server is allowed to close the connection once it has answered and the client also can close once it has received the answer, no?. I've already added a Connection:Keep-Alive in the headers, but the client still close the connection (according to code and experience) when the body of the response has been received

    Form Slim::Networking::Aynsc::HTTP, I see
    Code:
    sub _http_read_body {
    	my ( $socket, $self, $args ) = @_;
    	
    	Slim::Utils::Timers::killTimers( $socket, \&_http_socket_error );
    	Slim::Utils::Timers::killTimers( $socket, \&_http_read_timeout );
    	
    	my $result = $socket->read_entity_body( my $buf, BUFSIZE );
    
           .....
    	
    	if ( !defined $result || $result == 0 ) {
    		# if here, we've reached the end of the body
    		
    		# close and remove the socket
    		$self->fh->close if $self->fh;
    		$self->disconnect;
    		
    		main::DEBUGLOG && $log->debug("Body read");
    		
    		if ( my $cb = $args->{onBody} ) {
    			my $passthrough = $args->{passthrough} || [];
    			$cb->( $self, @{$passthrough} );
    		}
    	}
    	else {
    		# More body data to read
    		
    		# Some servers may never send EOF, but we want to return whatever data we've read
    		my $timeout = $self->timeout || $prefs->get('remotestreamtimeout');
    		Slim::Utils::Timers::setTimer( $socket, Time::HiRes::time() + $timeout, \&_http_read_timeout, $self, $args );
    	}
    }
    Maybe where I was not clear is that for the pairing to be successful, all the client / server exchanges must be made using the same socket, it fails if you open/close a socket for every POST (and the exchange includes 2 posts - there is a first "start pairing" POST that initiates the exchange that can be made on a different socket)
    Last edited by philippe_44; 2017-07-06 at 10:44.
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  7. #7
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204
    So I've decided to patch Slim::Networking::Async::HTTP to accept keep-alive connections. This is almost fine, except that I found what looks like a bug that was not visible before.

    In _http_read handler (called because set on a Slim::Networking:Select::addRead) , the headers of a response are read and then Slim::Networking::addRead is called to set _http_read_body) to get the body if any

    The problem is that if the body has already been buffered when the addRead called its handler, and maybe because addRead is called from an addRead handler, the event "data available" is missed (as already triggered) so the handler _http_read_body if never called ==> stuck

    This handler is only called when the socket closes. Which is fine with non persistent sockets as the server does that quickly, but of course when I set keep-alive, it's a disaster as _http_read_body is never called by the Async loop handler, and the socket surveillance timeout expires.

    I'm trying to find a good way to call _http_read_body a first time in the _http_read handler when there is data pending, but it looks goofy
    Last edited by philippe_44; 2017-07-07 at 00:23.
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  8. #8
    Babelfish's Best Boy mherger's Avatar
    Join Date
    Apr 2005
    Location
    Switzerland
    Posts
    19,746

    call a Perl function in an html page

    > So I've decided to path Slim::Networking::Async::HTTP to accept
    > keep-alive connections.


    _accept_, or support? You do a call from LMS to something else, not the
    other way around, don't you?

    I'm definitely looking forward to seeing your patch. I'm always
    surprised (and scared...) when some fundamental flaw gets discovered
    after all this time :-).

    --

    Michael

  9. #9
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204
    Quote Originally Posted by mherger View Post
    > So I've decided to path Slim::Networking::Async::HTTP to accept
    > keep-alive connections.


    _accept_, or support? You do a call from LMS to something else, not the
    other way around, don't you?

    I'm definitely looking forward to seeing your patch. I'm always
    surprised (and scared...) when some fundamental flaw gets discovered
    after all this time :-).

    --

    Michael
    Yes I mean supporting keep-alive acting as a client sending a request with a "Connection:keep-alive" header. I do not mean accept in the context of a server and accept()

    I still have to look at the addRead code and understand if I'm correct in my assessment that

    - do addRead(sock, oldcb)
    - in oldcb, when called, do a removeRead then a addRead(sock, newcb)
    - then newcb() is not called when some data were pending at the time of oldcb() call
    - it's only called when sock closes or if new data becomes available on that socket

    I assume that the event loop does more than just a select() and calls the callback if something is pending or ... I'm facing another ZindoZs specificity
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

  10. #10
    Senior Member
    Join Date
    May 2008
    Location
    Canada
    Posts
    3,204
    Quote Originally Posted by philippe_44 View Post
    Yes I mean supporting keep-alive acting as a client sending a request with a "Connection:keep-alive" header. I do not mean accept in the context of a server and accept()

    I still have to look at the addRead code and understand if I'm correct in my assessment that

    - do addRead(sock, oldcb)
    - in oldcb, when called, do a removeRead then a addRead(sock, newcb)
    - then newcb() is not called when some data were pending at the time of oldcb() call
    - it's only called when sock closes or if new data becomes available on that socket

    I assume that the event loop does more than just a select() and calls the callback if something is pending or ... I'm facing another ZindoZs specificity
    I've proposed a patch, although this touches a very sensitive piece of LMS, so you probably do not want to mofigy that lightly and I'm not really good at Perl, so my code probably contains some "naive" errors.

    Finally, the issue was not due to addRead but to the fact that the _http_read_header does not read line by line, but reads by chunks of 1024 bytes, consumes what is needed for headers, sets _http_read_body event read loop (using addRead) and exits. As a consequence, if the whole body is already in the read chunk, there is no event (no select) generated and _htpp_read_body is not called until the socket receives and EOF. This does not matter with a 'connection-close' mode (although it might be considered a bit odd) because the server will send the EOF "soon enough" (or more data than what's read will be available), but of course that does not work with keep-alive.
    LMS 7.7, 7.8 and 7.9 - 5xRadio, 3xBoom, 4xDuet, 1xTouch, 1 SB2. Sonos PLAY:3, PLAY:5, Marantz NR1603, JBL OnBeat, XBoxOne, XBMC, Foobar2000, ShairPortW, JRiver 21, 2xChromecast Audio, Chromecast v1 and v2, , Pi B3, B2, Pi B+, 2xPi A+, Odroid-C1, Odroid-C2, Cubie2, Yamaha WX-010, AppleTV 4, Airport Express

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •