GNOME Bugzilla – Bug 702652
rtspconnection: tunneled connections do not work
Last modified: 2013-06-24 07:48:47 UTC
When tunneling RTSP over HTTP a socket is transfered from the web server to the RTSP server. The RTSP server will create a GstRTSPConnection using this socket, put in a GstRTSPWatch, which it will attach to a suitable context. However, since polling child sources were introduced tunneling has been broken. A client that wants to connect over HTTP will not get an RTSP reply and will time out.
When the socket is transferred by the web server it will have read the data (i.e. the RTSP request), and it will be saved in the GstRTSPConnection's 'initial_buffer' member when the GstRTSPConnection is created. Before these changes were made the same GSource was used to poll if the source was writable as well as if it was readable. The same dispatcher function, gst_rtsp_source_dispatch, was called in both cases. That function checked if 'initial_buffer' was non-NULL and, if so, called 'watch->funcs.tunnel_start()' to initiate the tunneling and replied to the client. Since that function was called when the source was writable as well as when it was readable, the tunnel was always started.
But now we use separate child sources for reading and writing, with separate dispatch functions, and the checking of whether the 'initial_buffer' variable is non-NULL, and thus the starting of the tunnel, is only done in he read dispatcher, gst_rtsp_source_dispatch_read(). But the client waits for our response, and there will be nothing to read until it gets it and makes another request. Thus we will never reply.
I have tried to find a solution, but have not managed to come up with a nice one. One obvious thing to test was to check for 'watch->conn->initial_buffer != NULL' in the write dispatcher, gst_rtsp_source_dispatch_write(), and, if so, call gst_rtsp_source_dispatch_read(). That solves the problem, but it seems a bit ugly to me. Ideally the read and write dispatcher functions should not depend on each other. It also adds one more statement to the write dispatcher, which is called a lot.
I think that ideally the reply should be constructed (and sent?) before the watch is attached to the context, if that's possible. At a stage where we know that it's a tunnel, that there's request data remaining to be parsed, and replied to. So, any ideas?
Created attachment 247304 [details] [review]
One possible solution
This patch mimics the behavior from before the child sources were introduced.
In the write dispatcher a check is made whether there is any initial request data present in the connection, and if so it simply calls the read dispatcher.
This is probably not the best solution, but it works.
I did something similar in the main dispatch function because the write dispatch is now only called when something to write is pending. Does this work for you too?
Author: Wim Taymans <email@example.com>
Date: Fri Jun 21 11:50:33 2013 +0200
rtsp: dispatch when initial buffer has data
When we have data in the inital buffer, dispath the read function to read it
even if the socket has no data to read.
(In reply to comment #2)
> I did something similar in the main dispatch function because the write
> dispatch is now only called when something to write is pending. Does this work
> for you too?
Yes, it works just fine.