Project

General

Profile

[Solved] live555 rtp/rtsp over http reverse proxy 1.4.73

Added by xandey 3 months ago

Hi, I'm trying to run a live555 rtsp server and reverse proxy that through mod_proxy.

The short version of my question is that my backend is not seeing the request body from a GET request.

The streaming protocol utilizes two connections to the server a GET which returns the stream data, an a POST which contains the control channel. My problem is that when some clients (some vlc versions, Onvif Device Manager) connect to the GET, they send receiver reports (RR) through the GET body and this doesn't go through the proxy. This causes the backend server to not get them and timeout the stream. I can connect the client directly to the backend port and everything works fine.

I tried stracing lighttpd and I see that its not attempting to read the GET socket after it reads the header. These reports come every 5 seconds or so.

I did find this, but I don't think they tried with these clients.
https://redmine.lighttpd.net/boards/2/topics/9682

I have a minimal config:

server.document-root               = "/var/www/lighttpd" 
server.modules = ("mod_proxy")
proxy.server = ( "/" => ( ( "host" => "127.0.0.1", "port" => 5554 ) ) )
server.stream-response-body = 2
server.stream-request-body  = 2
# server.max-read-idle        = 31536000 # I believe I need these, but I don't think they are the problem here.
# server.max-write-idle       = 31536000
server.protocol-http11      = "disable" 

Here's the get from the client:

GET /mpeg1 HTTP/1.1
CSeq: 1
User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28)
Host: 192.168.60.40
x-sessioncookie: 2fecd1e3f3e2ccc71fb805a
Accept: application/x-rtsp-tunnelled
Pragma: no-cache
Cache-Control: no-cache

And here's the proxied header:

GET /mpeg1 HTTP/1.1
Host: 192.168.60.40
CSeq: 1
User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28)
x-sessioncookie: 2fecd1e3f3e2ccc71fb805a
Accept: application/x-rtsp-tunnelled
Pragma: no-cache
Cache-Control: no-cache
X-Forwarded-For: 192.168.60.157
X-Host: 192.168.60.40
X-Forwarded-Host: 192.168.60.40
X-Forwarded-Proto: http
Connection: close

I tried looking in connection.c and following the state, but I think I just got muddled up. It kinda looked like GET requests didn't have a way to check for more data in the request body with stream-request-body.

Thanks


Replies (28)

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

The short version of my question is that my backend is not seeing the request body from a GET request.

That is not actually phrased as a question, but see server.http-parseopts
server.http-parseopts += ("method-get-body" => "enable") The default is to reject such requests with 400 Bad Request.

Are you seeing 400 Bad Request for GET requests sent with a request body?


Separately, are you sure you need server.protocol-http11 = "disable" ? You probably should comment this out and test.

If you do need that, then you might need to see server.feature-flags and set
server.feature-flags += ("proxy.force-http10" => "enable")
to force connections to the backend to HTTP/1.0

BTW, if clients send Upgrade requests, then you need to configure mod_proxy to allow Upgrade and you must not disable HTTP/1.1.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

# server.max-read-idle        = 31536000 # I believe I need these, but I don't think they are the problem here.
# server.max-write-idle       = 31536000

Please see the documentation. The maximum values accepted by lighttpd for these are 65535 seconds, which is about 3/4 day.
server.max-read-idle
server.max-write-idle

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

Thank you so much for the reply.

The short version of my question is that my backend is not seeing the request body from a GET request.

That is not actually phrased as a question, but see server.http-parseopts

I will be more careful with my questions. Touche! I very much appreciate your time.

server.http-parseopts += ("method-get-body" => "enable") The default is to reject such requests with 400 Bad Request.

Are you seeing 400 Bad Request for GET requests sent with a request body?

I am not seeing a 400 Bad Request. method-get-body doesn't seem to help. The request headers (see first post) don't have any content-length, maybe that's related?

I should have been more clear on the timing:
  • 0.0s Client sends GET with associated headers, see original post.
  • 0.13s The back-end (port 5554) has done it's response headers and is staring to stream the video. I see everything correctly to here in wireshark for both connections. The protocol has a POST channel that gets opened before here and the responses to that come through in the GET response, but that's all working as expected.
  • 1.3s I see the Receiver Report come through in the GET connection port 80 request body. But doesn't go through to the back-end port 5554.
  • 7.2s Next RR comes though and isn't forwarded either. They repeat every 5s or so from here on.

So the response has already started by the time the additional GET body is sent.

Separately, are you sure you need server.protocol-http11 = "disable" ? You probably should comment this out and test.

If you do need that, then you might need to see server.feature-flags and set
server.feature-flags += ("proxy.force-http10" => "enable")
to force connections to the backend to HTTP/1.0

BTW, if clients send Upgrade requests, then you need to configure mod_proxy to allow Upgrade and you must not disable HTTP/1.1.

So far, vlc 3.0.20 on windows 10 doesn't work without disabling http11. It looks like it's closing the connection after the first chunk. I think it's supposed to wait for a 0 length chunk to close it right? So perhaps that's a client bug? Onvif Device Manager works fine with respect to this, but requests http 1.0 instead.

Please see the documentation. The maximum values accepted by lighttpd for these are 65535 seconds, which is about 3/4 day.
server.max-read-idle
server.max-write-idle

Thanks. I didn't realize this. I haven't had the connection work long enough to test this so I wasn't sure if it was necessary or not. It was set in an alternative implementation we have that uses CGI to do the proxying (but that doesn't currently work because of live555 upgrades. But that's another story.

Oh, I'm mostly testing against 1.4.64, but I did test my stripped down config with 1.4.73. I can't test ODM agaist 73 because I need to do more work to upgrade my system to the newer lighttpd, build changes or something.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

I do not quite understand how the application is sending GET requests or expecting multiple responses (?), perhaps because the GET requests from the client are not strictly compliant with the HTTP protocols. HTTP/1.1 RFC2616 was published in 1999. If your "advanced" application requires HTTP/1.0, then that application is definitely not "advanced".

HTTP is generally a stateless request/response protocol. There is a single request and a single (final) response, though with HTTP/1.1 and later, there may be intermediate 1xx responses prior to the final response. With HTTP/1.0, Connection: keep-alive may be specified to keep the connection open for further HTTP requests on the same connection, but depending on server configuration, the server may or may not honor the additional requests, or, more commonly, the server may set a limit on the number of keep-alive requests before the server closes the connection. HTTP/1.1 and later enable keep-alive by default, but the server is still permitted to set limits, including a limit of 0 keep-alive requests.

HTTP/1.1 requires that a request send Content-Length or Transfer-Encoding: chunked for all request methods (POST, PUT, etc) that have a request body, and this includes GET if there is a request body. Most request methods require Content-Length or Transfer-Encoding: chunked and are rejected if one is not present in the request. HEAD and GET do not require Content-Length or Transfer-Encoding: chunked, but HEAD must not have a request body, and GET must provide Content-Length or Transfer-Encoding: chunked if there is a request body. If neither are provided in a GET request, lighttpd treats the GET request as equivalent to Content-Length: 0. If a GET request contains a non-zero Content-Length or if the GET request contains Transfer-Encoding: chunked, then lighttpd sends 400 Bad Request unless lighttpd is configured to accept request bodies (see my prior comment).

With HTTP/0.9 (not supported by lighttpd) and with HTTP/1.0 -- and before HTTP/1.1 -- some ancient servers would read the request body from the client until the connection was closed if no Content-Length was specified (and if Connection: keep-alive was not specified.

I have a hunch that your application makes assumptions about HTTP/1.0 that may have been acceptable DECADES ago (>= 25+ years ago!), but is not HTTP protocol compliant for HTTP/1.1 and later. Again, HTTP/1.1 was published in 1999. Your application should be using HTTP/1.1 properly, or should upgrade the HTTP connection to websocket or webtransport or some other more advanced protocol to send multiple (non-HTTP) messages over a long-lived connection.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

For others which may come across this post, I would like to note that you are correctly setting
server.stream-response-body = 2
server.stream-request-body = 2
to enable streaming, as lighttpd does not stream by default. Instead (by default), lighttpd performs HTTP request/response offloading and will buffer the entire HTTP request or response body prior to forwarding (proxying) the HTTP request (including full request body) to a backend, or sending the completed HTTP response (including full response body) to the client.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

If you have a dedicated IP or domain name for the streaming application and want to use lighttpd to serve that and to have lighttpd server HTTP on other IPs or virtual hosts, then you might also consider lighttpd mod_sockproxy to forward connections to a specific IP to your backend, instead of using lighttpd mod_proxy, which requires proper use of HTTP protocols.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

Well thanks for your time. I'm not sure where to go from here. Just for informations:

The spec I'm trying to use is actually quite old, and appears to only be described in this 6 page apple document: https://opensource.apple.com/source/QuickTimeStreamingServer/QuickTimeStreamingServer-412.42/Documentation/RTSP_Over_HTTP.pdf (also from 1999!) and it's required for ONVIF conformance https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf (which is current) they just link to the quicktime document.

I wish I didn't have to work with these ancient protocols as well.

We don't have a dedicated IP or domain, so mod_socksproxy won't work. I did get it to stream but it stops for some reason and I can't use it anyway.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Maybe try sending the client through a client-side proxy? An HTTP/1.1 compliant proxy might then forward the request to lighttpd using request method GET along with Transfer-Encoding: chunked

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Have you tried reading those documents more carefully?
https://opensource.apple.com/source/QuickTimeStreamingServer/QuickTimeStreamingServer-412.42/Documentation/RTSP_Over_HTTP.pdf
https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf

The ONVIF specification supports WebSockets. So does lighttpd. See lighttpd WebSockets

On the other hand, the RTSP_Over_HTTP doc requires HTTP/1.0 which is a sure sign that you should look for better solutions, i.e. see WebSockets above. RTSP over HTTP expects a server responding with HTTP/1.0 to send a response without Content-Length and without HTTP/1.1 Transfer-Encoding: chunked, but to nevertheless continue sending a response until the connection is closed. The HTTP/1.0 misfeature of sending a response without Content-Length is HTTP/1.0 only, and not permitted in HTTP/1.1 or later. Supporting a streaming or otherwise unknown body length is why HTTP/1.1 added Transfer-Encoding: chunked.

RE: live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

My problem is that when some clients (some vlc versions, Onvif Device Manager) connect to the GET, they send receiver reports (RR) through the GET body and this doesn't go through the proxy.

Shouldn't RTCP receiver reports be sent on the connection created with POST request?


In any case, you should use ONVIF with lighttpd WebSockets.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

Maybe try sending the client through a client-side proxy? An HTTP/1.1 compliant proxy might then forward the request to lighttpd using request method GET along with Transfer-Encoding: chunked

Are you suggesting changing the client? I am developing a camera and testing against publicly available software. I can't really control the clients, other than making the decision that they're doing it wrong and I don't care, but I think live555 isn't something I can ignore. live555 appears to have added a keep-alive in the POST in addition to sending the RR through the GET in more recent versions, so ignoring the GET body still works until they fill up the socket buffer... Even the current library still sends data on the POST though (fedora builds vlc with current live555 library). There is a discussion about why live555 sends them this way here:
http://lists.live555.com/pipermail/live-devel/2017-August/020739.html

Yeah, I would love to add support for the websocket version. However, the predicament I'm in is that ONVIF requires RTP/RTSP/HTTP/TCP (you'll see the word "shall" in the ONVIF doc) while support for RTP/RTSP/TCP/WebSocket is an optional ("devices indicating support..."). The websocket version also requires implementing profile G which is a whole other pile of work.

Perhaps I'm not understanding your client side comment. Is this something I can do in my camera's lighttpd config? That's the only place port 80 is open.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

http://lists.live555.com/pipermail/live-devel/2017-August/020739.html

That message strongly suggests that Ross (the poster there) has faulty logic and did not understand the most basic and very explicitly documented reasons for have unidirectional communication over the channels set up over HTTP/1.0 connections.

Ross writes:

From this, when I implemented this RTSP-over-HTTP tunneling protocol myself, I decided that it would make the most sense for RTCP "RR" packets to be sent over the "GET" channel (making it a two-way channel,

That is such an obvious failure to understand why RTSP-over-HTTP was designed with unidirectional channels.

You might not be able to change things, but Ross does not understand the limitations of the simple protocol that is HTTP/1.0, and the well-documented RTSP-over-HTTP protocol which EXPLICITLY documents the direction of data flows.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

To be clearer, anyone with half a clue designing live555 and wanting to send RTCP RR over the GET connection would have used HTTP/1.1 with Transfer-Encoding: chunked. I would have preferred sending over the POST connection, but have not looked in detail why that was not the most preferred solution.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Practical considerations (which were practical considerations for servers in the 1990's) include an origin server such as lighttpd being a gateway to CGI (Common Gateway Interface), which requires specification of CONTENT_LENGTH in the environment. When lighttpd is configured to stream the request body to the backend, lighttpd returns 411 Length Required if Content-Length is not present in a request to a backend (e.g. mod_cgi) which requires specifying CONTENT_LENGTH (or similar). When lighttpd is not configured to stream the request body to the backend, lighttpd performs request offloading and defers starting or connecting to backends, which may be resource hogs (memory hungry, CPU intensive, etc), and should not hold on to resources while waiting for the request body to finish being received. For these reasons (and others), lighttpd treats GET requests which do not specify Content-Length (or HTTP/1.1 Transfer-Encoding: chunked) as if the request sent Content-Length: 0. As noted in an earlier post, lighttpd will reject GET with request body by sending a 400 Bad Request response unless lighttpd.conf is explicitly configured with server.http-parseopts += ("method-get-body" => "enable")

Perhaps I'm not understanding your client side comment. Is this something I can do in my camera's lighttpd config? That's the only place port 80 is open.

Your posts provide piece-meal information, and it seems that you assume that I knew about the details of RTSP-over-HTTP and Onvif. I did not until I skimmed the links you provided, so the confusion is probably mine. As I posted before I read those links, the requirement to use HTTP/1.0 and sending a GET request without a Content-Length (or HTTP/1.1 Transfer-Encoding: chunked) were "questionable" at best. I have since concluded that Ross's implementation choice for live555 sending RTCP RR was ill-informed.

The earliest entry in http://live555.com/liveMedia/public/changelog.txt is dated 2002.06.25. I surmise that continuing to use HTTP/1.0 for RTCP RR was chosen since at that time plenty of braindead HTTP/1.0 proxies were still widely used. In that light, the choice to require bidirectional communication on the GET connection is even more suspect, since many simple servers do not support simultaneous bidirectional communication -- they receive a completed request and then process the request to produce and send a complete response. lighttpd -- which is fairly advanced -- did not support simultaneous bidirectional streaming until I added the feature and configuration options in lighttpd 1.4.40, released in 2016.


I have no plans to add extraneous code to lighttpd high-performance request processing critical code paths. That includes code to support the special-case of RTCP RR for live555 sending HTTP/1.0 GET request bodies streaming with unspecified content-length. However, I may consider other alternatives. Are you comfortable building and testing a version of lighttpd using the source code? See InstallFromSource and please confirm.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Looking again at your original post, if the client sends GET /mpeg1 HTTP/1.1, then that is an HTTP/1.1 request. Content-Length is 0 with request method GET unless the request contains Content-Length or Transfer-Encoding: chunked. What is the client producing this and have you tried testing with different clients? Is this VLC? User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) From where does one obtain "Onvif Device Manager" and what version is it? What/where are these "public" clients and why can't they be upgraded? Can you detect an old version and then send a web page that says "ummm, hi, you're using software over 10 years old. You'll have a better time using something more recent." ?

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

https://www.rfc-editor.org/rfc/rfc9110#GET

Although request message framing is independent of the method used, content received in a GET request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a GET request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported.

https://www.rfc-editor.org/rfc/rfc9110#name-framing-and-completeness

HTTP/0.9 and early deployments of HTTP/1.0 used closure of the underlying connection to end a response. For backwards compatibility, this implicit framing is also allowed in HTTP/1.1. However, implicit framing can fail to distinguish an incomplete response if the connection closes early. For that reason, almost all modern implementations use explicit framing in the form of length-delimited sequences of message data.

(note that the above HTTP/1.1 exception is for response message body, not for request message body)

https://www.rfc-editor.org/rfc/rfc9112#name-message-body

The presence of a message body in a request is signaled by a Content-Length or Transfer-Encoding header field.

tl;dr: sending HTTP/1.1 request with a message body requires Content-Length or Transfer-Encoding

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

I apologize for my slow response. It is difficult to find time over the weekend as I have multiple small children.

I currently compile lighttpd from source for our camera, so testing that is no problem.

One option to implement the RTSP-over-HTTP protocol in a CGI which allows me to fake RR to keep the server streaming, that way the clients RR's can sit ignored in the socket buffer.

An alternative might be to allow HTTP/1.0 GET requests to stream the body with a config option that can be selected for this route ($HTTP["url"] =~ "^/mpeg.$" {)? I'm a little bit lost as to how to try or implement this though as I think it would require some heavy surgery to connections.c (In case you can't tell I"m wildly guessing here)? I believe this has a good shot at fixing ONVIF device manager, but not VLC, but I think that would be acceptable as VLC RTSP-over-HTTP streaming isn't important to our clients.

I don't post a lot of these, but I've been learning what is important as I go. I'm sorry I didn't get all the pertinent information in one go.

Here's a recap of the clients I've been trying (mostly in a win10 pro vm):
  • Onvif Device Manager - https://sourceforge.net/projects/onvifdm/ - odm-v2.2.250r.msi - This tends to be the first pass at testing in the ONVIF world. The official ONVIF test tool is much more cumbersome and requires paying membership dues. This is important to us because it helps us work with video management companies. Even though they only had once release in the last 6 years. If you want to test yourself, you would need an onvif camera and would need to click the settings icon at the top right and select http streaming transport.
    • GET /mpeg1 HTTP/1.0
    • User-Agent: LIVE555 Streaming Media v2013.02.11
    • Sends RR in GET body.
  • VLC - https://videolan.org/ - Official windows Version 3.0.20 64 bit installer vlc-3.0.20-win64.exe - Preferences -> show all settings -> rtp/rtsp -> check "use rtp over rtsp (tcp)" and check "tunnel rtsp and rtp over http".
    • GET /mpeg1 HTTP/1.1
    • User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28)
    • This requires server.protocol-http11 = "disable" as it fails to parse the chunked response correctly and closes the connection after the first chunk.
    • Sends RR in GET/1.1 body without content-length.
  • MPV - mpv 0.36.0 Copyright © 2000-2023 mpv/MPlayer/mplayer2 projects - FFmpeg version: 6.0-6ubuntu1 - Ubuntu 23.10 - mpv --rtsp-transport=http rtsp://[ip]:80/mpeg1
    • GET /mpeg1 HTTP/1.1
    • User-Agent: Lavf/60.3.100
    • Does not send RR in GET body
    • I'm pretty sure FFmpeg is doing this better.
  • live555 - I believe live555 has a rtsp client. It's on my todo list to test this directly. If you would like something you can run yourself I can probably build a standalone testcase using this. However, that Ross from the live555 listserve doesn't have a publicly available archive for live555 so we can probably only test against the current version and read the changelog.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Many of these client are configurable, and may need to be configured to use RTSP-over-HTTP. Some appear to use UDP by default. Are you sure that you have tried to clearly state the client requirements? I can't read your mind.


Aside: VLC is open source. Someone should file a bug that VLC is sending HTTP/1.1 and unable to receive Transfer-Encoding: chunked in response. Supporting Transfer-Encoding: chunked in responses is a hard requirement of HTTP/1.1. (I haven't looked to see if there is already an open bug in VLC for that.)

[Edit: a quick search via search engine provides annecdotal evidence that VLC does support Transfer-Encoding: chunked, so you might look more carefully at the configs and test again]


You wrote:

An alternative might be to allow HTTP/1.0 GET requests to stream the body with a config option that can be selected for this route ($HTTP["url"] =~ "^/mpeg.$" {)? I'm a little bit lost as to how to try or implement this though as I think it would require some heavy surgery to connections.c (In case you can't tell I"m wildly guessing here)?

As I stated in an earlier post above:

I have no plans to add extraneous code to lighttpd high-performance request processing critical code paths. That includes code to support the special-case of RTCP RR for live555 sending HTTP/1.0 GET request bodies streaming with unspecified content-length. However, I may consider other alternatives.

Heavy surgery is out of the question, as is slowing down lighttpd's critical path for request processing in order to special case this use for HTTP/1.0, and which can break existing, widely-used, and simplistic use of HTTP/1.0 requests, e.g. a simple "GET / HTTP/1.0" handled by a CGI script expecting env variable CONTENT_LENGTH=0.

There are better ways. I pushed some experimental code on my dev branch
https://git.lighttpd.net/lighttpd/lighttpd1.4/src/branch/personal/gstrauss/master
which adds an API to mod_magnet allowing you to enable reading request body to EOF for HTTP/1.0 requests.
Note: this requires that you build lighttpd --with-lua enabled. (lighttpd supports any version of lua 5.1 or later)

lighttpd.conf snippet

server.modules += ("mod_magnet")
magnet.attract-raw-url-to = ("/etc/lighttpd/rtcp-rr-over-get.lua")

$REQUEST_HEADER["User-Agent"] =^ "LibVLC/" {
  server.protocol-http11 = "disable" 
}

/etc/lighttpd/rtcp-rr-over-get.lua

local r = lighty.r
if (r.req_attr["request.protocol"] == "HTTP/1.0") then  -- duplicated check for clarity; enforced by r.req_body.unspecified_len
  if (r.req_header["Accept"] == "application/x-rtsp-tunnelled") then
    local rc = r.req_body.unspecified_len
    -- if rc then print 'rtcp-rr-over-get: yes' else print 'rtcp-rr-over-get: no' end
  end
end
return 0

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

One additional note: lighttpd mod_proxy sends requests to backends using HTTP/1.1

If your backend does not support HTTP/1.1 and Transfer-Encoding: chunked when there is a request body and no Content-Length specified, then you may have to configure lighttpd mod_proxy with
proxy.header += ("force-http10" => "enable")


Curiousity: what are the reasons why are you are using lighttpd mod_proxy as a reverse proxy in front of your live555 rtsp server (versus having clients connect directly)? using lighttpd mod_auth? other services? ...?

One alternative to the mod_magnet patch I posted above would be for mod_proxy to have a config option similar to "force-http10" to allow unspecified request body when "force-http10" is also enabled. (not implemented)

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

I believe the reason for RTSP-over-HTTP is to allow firewall traversal using port 80 I'm not clear on the details here but this is what I've been told. We also have to explain all of our open ports and I don't want to have to open a new external port for our customers to find in port scans.

I'm still working on trying out your mod_magnet patch. I'll keep you posted. I had looked into mod_proxy before my original post, but I didn't make enough progress to try anything. I might take a look as to what it would entail from the magnet patch if that works.

I'm not using mod_auth or anything here, rtsp has its own auth solution.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

You already mentioned that you do not have a dedicated IP or domain, and so you can not use mod_sockproxy. For others who might read this: If you're not using lighttpd for anything other than the reverse proxy, and if your only requirement is port 80, and if you can not modify the listening port of your live555 rtsp server, then you might consider simply adjusting your firewall to route port 80 on your public IP to 127.0.0.1 port 5554.

However, you already mentioned that the above does not apply to your situation.


NB: I modified the mod_magnet patch on my dev branch to add

                && 0 == r->reqbody_length
                   /*(r->reqbody == -1 if HTTP/1.1 Transfer-Encoding: chunked)*/

to avoid an edge case where the client sends HTTP/1.1 Transfer-Encoding: chunked, but you have configured server.protocol-http11 = "disable"

This change has been force-pushed to my dev branch.


Here is a completely untested patch for mod_proxy if you wanted to maintain it yourself. It is similar to my patch to mod_magnet, but at this moment it is unlikely to be included in lighttpd, whereas the patch to mod_magnet is more likely to be included.

--- a/src/mod_proxy.c
+++ b/src/mod_proxy.c
@@ -879,6 +879,18 @@ static handler_t proxy_create_env(gw_handler_ctx *gwhctx) {
                b->ptr[b->used-2] = '0'; /*(overwrite end of request line)*/
        }

+#if 1 /* custom patch */
+       if (HTTP_VERSION_1_0 == r->http_version
+           && hctx->conf.header.force_http10
+           /*&& hctx->conf.header.force_http10_unspecified_len*//*(option not implemented)*/
+           && 0 == r->reqbody_length
+              /*(r->reqbody == -1 if HTTP/1.1 Transfer-Encoding: chunked)*/
+           && !r->keep_alive
+           && !light_btst(r->rqst_htags, HTTP_HEADER_CONTENT_LENGTH)) {
+               http_response_upgrade_read_body_unknown(r);
+       }
+       else
+#endif
        if (r->reqbody_length > 0
            || (0 == r->reqbody_length
                && !http_method_get_or_head(r->http_method))) {

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

@xandey: I am planning to release lighttpd 1.4.74 in the next couple days, so it is in your best interest to priortize your interop testing.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

So I've tested the mod_magnet solution and it's working quite well. I will now stream the GET request body and it forwards the RR through the proxy. I am testing I think your patch is good and works for me. I tested commit 90598f4ceb, and am now re-testing with 10c7592ea5 (which is up 30m so far, so it should be good too). I am using the commit applied to lighttpd-1.4.73.tar.xz release, not the git tree.

I hope you'll entertain one last question (hopefully). I see comments from various places that server.max-read-idle maxes out at 18 hours, and all the posts I've found don't offer any alternatives. Is this in fact true? Is there no way to achieve an unlimited POST connection without the client sending keep-alives?

I ask because ONVIF Device Manager and windows VLC both open the POST connection, send some setup stuff and then don't send anything else. However, when lighttpd times out and closes the connection they stop streaming.

POST /mpeg1 HTTP/1.0
CSeq: 1
User-Agent: LIVE555 Streaming Media v2013.02.11
x-sessioncookie: 7f7b60bc99b36606f69e760
Content-Type: application/x-rtsp-tunnelled
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 32767
Expires: Sun, 9 Jan 1972 00:00:00 GMT

POST /mpeg1 HTTP/1.1
CSeq: 1
User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28)
Host: 192.168.60.40
x-sessioncookie: a7bce84be281d4effe222a7
Content-Type: application/x-rtsp-tunnelled
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 32767
Expires: Sun, 9 Jan 1972 00:00:00 GMT

For anyone following along at home I have the following config:

$HTTP["url"] =~ "^/mpeg.$" {
    proxy.server = ("/" => (("host" => "127.0.0.1", "port" => 5554)))
    magnet.attract-raw-url-to = ("/etc/lighttpd/rtcp-rr-over-get.lua")
    server.stream-response-body = 2
    server.stream-request-body = 2

    $REQUEST_HEADER["User-Agent"] =^ "LibVLC/" {
        server.protocol-http11 = "disable" 
    }
    $HTTP["request-method"] =~ "^POST$" {
        server.max-read-idle = 65535
    }
}

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by xandey 3 months ago

This not streaming may be OK. I don't really care if vlc and onvif device manager times out after 18 hours, but it's very difficult for me to test against every video management system out there so I try to make the easy tests work.

RE: [Solved] live555 rtp/rtsp over http reverse proxy 1.4.73 - Added by gstrauss 3 months ago

Thank you for testing.

FYI: $HTTP["request-method"] =~ "^POST$" is more simply written at $HTTP["request-method"] == "POST"

I hope you'll entertain one last question (hopefully). I see comments from various places that server.max-read-idle maxes out at 18 hours, and all the posts I've found don't offer any alternatives. Is this in fact true? Is there no way to achieve an unlimited POST connection without the client sending keep-alives?

If the RTCP RRs were sent over the POST connection, you wouldn't have to ask that question, would you? ;)

The server.max-read-idle value is currently stored in lighttpd in an unsigned short, so max value is 65535 seconds (18 hrs 12 mins 15 secs). If it were possible to disable the timeout, then that might be abused or might possibly lead to some connections never getting cleaned up. Since connections can drop for any reason and at any time, long-running clients should be prepared to reconnect. Modern (and intelligent) clients are not using HTTP/1.0 and modern (and intelligent) applications are written to avoid this timeout by incorporating some sort of keep-alive probe or no-op message, if needed.

I don't really care if vlc and onvif device manager times out after 18 hours, but it's very difficult for me to test against every video management system out there so I try to make the easy tests work.

I am not quite convinced that 18 hours is not "long enough". If you needed to patch server.max-read-idle to be int-sized (up to ~2 billion seconds), then it requires trivially modifying three lines of lighttpd code and maintaining you own patch to lighttpd, but if you do that, then I'd be interested in the real-world use. "I try to make the easy tests work" is predictive, not an actual real-world requirement.

(1-25/28)