+static GstRTSPStatusCode
+tunnel_start (GstRTSPWatch *watch, gpointer user_data)
+{
+ GstRTSPClient *client;
+ const gchar *tunnelid;
+
+ client = GST_RTSP_CLIENT (user_data);
+
+ g_message ("client %p: tunnel start", client);
+
+ /* store client in the pending tunnels */
+ tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
+
+ g_message ("client %p: inserting %s", client, tunnelid);
+
+ /* we can't have two clients connecting with the same tunnelid */
+ g_mutex_lock (tunnels_lock);
+ if (g_hash_table_lookup (tunnels, tunnelid))
+ goto tunnel_existed;
+
+ g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
+ g_mutex_unlock (tunnels_lock);
+
+ return GST_RTSP_STS_OK;
+
+ /* ERRORS */
+tunnel_existed:
+ {
+ g_mutex_unlock (tunnels_lock);
+ g_message ("client %p: tunnel session %s existed", client, tunnelid);
+ return GST_RTSP_STS_SERVICE_UNAVAILABLE;
+ }
+}
+
+static GstRTSPResult
+tunnel_complete (GstRTSPWatch *watch, gpointer user_data)
+{
+ const gchar *tunnelid;
+ GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
+ GstRTSPClient *oclient;
+
+ g_message ("client %p: tunnel complete", client);
+
+ /* find previous tunnel */
+ tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
+
+ g_mutex_lock (tunnels_lock);
+ if (!(oclient = g_hash_table_lookup (tunnels, tunnelid)))
+ goto no_tunnel;
+
+ /* remove the old client from the table. ref before because removing it will
+ * remove the ref to it. */
+ g_object_ref (oclient);
+ g_hash_table_remove (tunnels, tunnelid);
+ g_mutex_unlock (tunnels_lock);
+
+ g_message ("client %p: found tunnel %p", client, oclient);
+
+ /* merge the tunnels into the first client */
+ gst_rtsp_connection_do_tunnel (oclient->connection, client->connection);
+ gst_rtsp_watch_reset (oclient->watch);
+ g_object_unref (oclient);
+
+ /* we don't need this watch anymore */
+ g_source_remove (client->watchid);
+
+ return GST_RTSP_OK;
+
+ /* ERRORS */
+no_tunnel:
+ {
+ g_mutex_unlock (tunnels_lock);
+ g_message ("client %p: tunnel session %s not found", client, tunnelid);
+ return GST_RTSP_OK;
+ }
+}
+