Merge branch 'upstream/1.22.7' into tizen_gst_1.22.7
[platform/upstream/gstreamer.git] / subprojects / gst-rtsp-server / gst / rtsp-server / rtsp-client.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  * Copyright (C) 2015 Centricular Ltd
4  *     Author: Sebastian Dröge <sebastian@centricular.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 /**
22  * SECTION:rtsp-client
23  * @short_description: A client connection state
24  * @see_also: #GstRTSPServer, #GstRTSPThreadPool
25  *
26  * The client object handles the connection with a client for as long as a TCP
27  * connection is open.
28  *
29  * A #GstRTSPClient is created by #GstRTSPServer when a new connection is
30  * accepted and it inherits the #GstRTSPMountPoints, #GstRTSPSessionPool,
31  * #GstRTSPAuth and #GstRTSPThreadPool from the server.
32  *
33  * The client connection should be configured with the #GstRTSPConnection using
34  * gst_rtsp_client_set_connection() before it can be attached to a #GMainContext
35  * using gst_rtsp_client_attach(). From then on the client will handle requests
36  * on the connection.
37  *
38  * Use gst_rtsp_client_session_filter() to iterate or modify all the
39  * #GstRTSPSession objects managed by the client object.
40  *
41  * Last reviewed on 2013-07-11 (1.0.0)
42  */
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include <stdio.h>
48 #include <string.h>
49
50 #include <gst/sdp/gstmikey.h>
51 #include <gst/rtsp/gstrtsp-enumtypes.h>
52
53 #include "rtsp-client.h"
54 #include "rtsp-sdp.h"
55 #include "rtsp-params.h"
56 #include "rtsp-server-internal.h"
57
58 typedef enum
59 {
60   TUNNEL_STATE_UNKNOWN,
61   TUNNEL_STATE_GET,
62   TUNNEL_STATE_POST
63 } GstRTSPTunnelState;
64
65 /* locking order:
66  * send_lock, lock, tunnels_lock
67  */
68
69 struct _GstRTSPClientPrivate
70 {
71   GMutex lock;                  /* protects everything else */
72   GMutex send_lock;
73   GMutex watch_lock;
74   GstRTSPConnection *connection;
75   GstRTSPWatch *watch;
76   GMainContext *watch_context;
77   gchar *server_ip;
78   gboolean is_ipv6;
79
80   /* protected by send_lock */
81   GstRTSPClientSendFunc send_func;
82   gpointer send_data;
83   GDestroyNotify send_notify;
84   GstRTSPClientSendMessagesFunc send_messages_func;
85   gpointer send_messages_data;
86   GDestroyNotify send_messages_notify;
87   GArray *data_seqs;
88
89   GstRTSPSessionPool *session_pool;
90   gulong session_removed_id;
91   GstRTSPMountPoints *mount_points;
92   GstRTSPAuth *auth;
93   GstRTSPThreadPool *thread_pool;
94
95   /* used to cache the media in the last requested DESCRIBE so that
96    * we can pick it up in the next SETUP immediately */
97   gchar *path;
98   GstRTSPMedia *media;
99
100   GHashTable *transports;
101   GList *sessions;
102   guint sessions_cookie;
103
104   gboolean drop_backlog;
105   gint post_session_timeout;
106
107   guint content_length_limit;
108
109   gboolean had_session;
110   GSource *rtsp_ctrl_timeout;
111   guint rtsp_ctrl_timeout_cnt;
112
113   /* The version currently being used */
114   GstRTSPVersion version;
115
116   GHashTable *pipelined_requests;       /* pipelined_request_id -> session_id */
117   GstRTSPTunnelState tstate;
118 };
119
120 typedef struct
121 {
122   guint8 channel;
123   guint seq;
124 } DataSeq;
125
126 static GMutex tunnels_lock;
127 static GHashTable *tunnels;     /* protected by tunnels_lock */
128
129 #define WATCH_BACKLOG_SIZE              100
130
131 #define DEFAULT_SESSION_POOL            NULL
132 #define DEFAULT_MOUNT_POINTS            NULL
133 #define DEFAULT_DROP_BACKLOG            TRUE
134 #define DEFAULT_POST_SESSION_TIMEOUT    -1
135
136 #define RTSP_CTRL_CB_INTERVAL           1
137 #define RTSP_CTRL_TIMEOUT_VALUE         60
138
139 enum
140 {
141   PROP_0,
142   PROP_SESSION_POOL,
143   PROP_MOUNT_POINTS,
144   PROP_DROP_BACKLOG,
145   PROP_POST_SESSION_TIMEOUT,
146   PROP_LAST
147 };
148
149 enum
150 {
151   SIGNAL_CLOSED,
152   SIGNAL_NEW_SESSION,
153   SIGNAL_PRE_OPTIONS_REQUEST,
154   SIGNAL_OPTIONS_REQUEST,
155   SIGNAL_PRE_DESCRIBE_REQUEST,
156   SIGNAL_DESCRIBE_REQUEST,
157   SIGNAL_PRE_SETUP_REQUEST,
158   SIGNAL_SETUP_REQUEST,
159   SIGNAL_PRE_PLAY_REQUEST,
160   SIGNAL_PLAY_REQUEST,
161   SIGNAL_PRE_PAUSE_REQUEST,
162   SIGNAL_PAUSE_REQUEST,
163   SIGNAL_PRE_TEARDOWN_REQUEST,
164   SIGNAL_TEARDOWN_REQUEST,
165   SIGNAL_PRE_SET_PARAMETER_REQUEST,
166   SIGNAL_SET_PARAMETER_REQUEST,
167   SIGNAL_PRE_GET_PARAMETER_REQUEST,
168   SIGNAL_GET_PARAMETER_REQUEST,
169   SIGNAL_HANDLE_RESPONSE,
170   SIGNAL_SEND_MESSAGE,
171   SIGNAL_PRE_ANNOUNCE_REQUEST,
172   SIGNAL_ANNOUNCE_REQUEST,
173   SIGNAL_PRE_RECORD_REQUEST,
174   SIGNAL_RECORD_REQUEST,
175   SIGNAL_CHECK_REQUIREMENTS,
176   SIGNAL_LAST
177 };
178
179 GST_DEBUG_CATEGORY_STATIC (rtsp_client_debug);
180 #define GST_CAT_DEFAULT rtsp_client_debug
181
182 static guint gst_rtsp_client_signals[SIGNAL_LAST] = { 0 };
183
184 static void gst_rtsp_client_get_property (GObject * object, guint propid,
185     GValue * value, GParamSpec * pspec);
186 static void gst_rtsp_client_set_property (GObject * object, guint propid,
187     const GValue * value, GParamSpec * pspec);
188 static void gst_rtsp_client_finalize (GObject * obj);
189
190 static void rtsp_ctrl_timeout_remove (GstRTSPClient * client);
191
192 static GstSDPMessage *create_sdp (GstRTSPClient * client, GstRTSPMedia * media);
193 static gboolean handle_sdp (GstRTSPClient * client, GstRTSPContext * ctx,
194     GstRTSPMedia * media, GstSDPMessage * sdp);
195 static gboolean default_configure_client_media (GstRTSPClient * client,
196     GstRTSPMedia * media, GstRTSPStream * stream, GstRTSPContext * ctx);
197 static gboolean default_configure_client_transport (GstRTSPClient * client,
198     GstRTSPContext * ctx, GstRTSPTransport * ct);
199 static GstRTSPResult default_params_set (GstRTSPClient * client,
200     GstRTSPContext * ctx);
201 static GstRTSPResult default_params_get (GstRTSPClient * client,
202     GstRTSPContext * ctx);
203 static gchar *default_make_path_from_uri (GstRTSPClient * client,
204     const GstRTSPUrl * uri);
205 static gboolean default_handle_options_request (GstRTSPClient * client,
206     GstRTSPContext * ctx, GstRTSPVersion version);
207 static gboolean default_handle_set_param_request (GstRTSPClient * client,
208     GstRTSPContext * ctx);
209 static gboolean default_handle_get_param_request (GstRTSPClient * client,
210     GstRTSPContext * ctx);
211 static gboolean default_handle_play_request (GstRTSPClient * client,
212     GstRTSPContext * ctx);
213
214 static void client_session_removed (GstRTSPSessionPool * pool,
215     GstRTSPSession * session, GstRTSPClient * client);
216 static GstRTSPStatusCode default_pre_signal_handler (GstRTSPClient * client,
217     GstRTSPContext * ctx);
218 static gboolean pre_signal_accumulator (GSignalInvocationHint * ihint,
219     GValue * return_accu, const GValue * handler_return, gpointer data);
220
221 G_DEFINE_TYPE_WITH_PRIVATE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
222
223 static void
224 gst_rtsp_client_class_init (GstRTSPClientClass * klass)
225 {
226   GObjectClass *gobject_class;
227
228   gobject_class = G_OBJECT_CLASS (klass);
229
230   gobject_class->get_property = gst_rtsp_client_get_property;
231   gobject_class->set_property = gst_rtsp_client_set_property;
232   gobject_class->finalize = gst_rtsp_client_finalize;
233
234   klass->create_sdp = create_sdp;
235   klass->handle_sdp = handle_sdp;
236   klass->configure_client_media = default_configure_client_media;
237   klass->configure_client_transport = default_configure_client_transport;
238   klass->params_set = default_params_set;
239   klass->params_get = default_params_get;
240   klass->make_path_from_uri = default_make_path_from_uri;
241   klass->handle_options_request = default_handle_options_request;
242   klass->handle_set_param_request = default_handle_set_param_request;
243   klass->handle_get_param_request = default_handle_get_param_request;
244   klass->handle_play_request = default_handle_play_request;
245
246   klass->pre_options_request = default_pre_signal_handler;
247   klass->pre_describe_request = default_pre_signal_handler;
248   klass->pre_setup_request = default_pre_signal_handler;
249   klass->pre_play_request = default_pre_signal_handler;
250   klass->pre_pause_request = default_pre_signal_handler;
251   klass->pre_teardown_request = default_pre_signal_handler;
252   klass->pre_set_parameter_request = default_pre_signal_handler;
253   klass->pre_get_parameter_request = default_pre_signal_handler;
254   klass->pre_announce_request = default_pre_signal_handler;
255   klass->pre_record_request = default_pre_signal_handler;
256
257   g_object_class_install_property (gobject_class, PROP_SESSION_POOL,
258       g_param_spec_object ("session-pool", "Session Pool",
259           "The session pool to use for client session",
260           GST_TYPE_RTSP_SESSION_POOL,
261           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
262
263   g_object_class_install_property (gobject_class, PROP_MOUNT_POINTS,
264       g_param_spec_object ("mount-points", "Mount Points",
265           "The mount points to use for client session",
266           GST_TYPE_RTSP_MOUNT_POINTS,
267           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
268
269   g_object_class_install_property (gobject_class, PROP_DROP_BACKLOG,
270       g_param_spec_boolean ("drop-backlog", "Drop Backlog",
271           "Drop data when the backlog queue is full",
272           DEFAULT_DROP_BACKLOG, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
273
274   /**
275    * GstRTSPClient::post-session-timeout:
276    *
277    * An extra tcp timeout ( > 0) after session timeout, in seconds.
278    * The tcp connection will be kept alive until this timeout happens to give
279    * the client a possibility to reuse the connection.
280    * 0 means that the connection will be closed immediately after the session
281    * timeout.
282    *
283    * Default value is -1 seconds, meaning that we let the system close
284    * the connection.
285    *
286    * Since: 1.18
287    */
288   g_object_class_install_property (gobject_class, PROP_POST_SESSION_TIMEOUT,
289       g_param_spec_int ("post-session-timeout", "Post Session Timeout",
290           "An extra TCP connection timeout after session timeout", G_MININT,
291           G_MAXINT, DEFAULT_POST_SESSION_TIMEOUT,
292           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
293
294   gst_rtsp_client_signals[SIGNAL_CLOSED] =
295       g_signal_new ("closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
296       G_STRUCT_OFFSET (GstRTSPClientClass, closed), NULL, NULL, NULL,
297       G_TYPE_NONE, 0, G_TYPE_NONE);
298
299   gst_rtsp_client_signals[SIGNAL_NEW_SESSION] =
300       g_signal_new ("new-session", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
301       G_STRUCT_OFFSET (GstRTSPClientClass, new_session), NULL, NULL, NULL,
302       G_TYPE_NONE, 1, GST_TYPE_RTSP_SESSION);
303
304   /**
305    * GstRTSPClient::pre-options-request:
306    * @client: a #GstRTSPClient
307    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
308    *
309    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
310    *          otherwise an appropriate return code
311    *
312    * Since: 1.12
313    */
314   gst_rtsp_client_signals[SIGNAL_PRE_OPTIONS_REQUEST] =
315       g_signal_new ("pre-options-request", G_TYPE_FROM_CLASS (klass),
316       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
317           pre_options_request), pre_signal_accumulator, NULL, NULL,
318       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
319
320   /**
321    * GstRTSPClient::options-request:
322    * @client: a #GstRTSPClient
323    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
324    */
325   gst_rtsp_client_signals[SIGNAL_OPTIONS_REQUEST] =
326       g_signal_new ("options-request", G_TYPE_FROM_CLASS (klass),
327       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, options_request),
328       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
329
330   /**
331    * GstRTSPClient::pre-describe-request:
332    * @client: a #GstRTSPClient
333    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
334    *
335    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
336    *          otherwise an appropriate return code
337    *
338    * Since: 1.12
339    */
340   gst_rtsp_client_signals[SIGNAL_PRE_DESCRIBE_REQUEST] =
341       g_signal_new ("pre-describe-request", G_TYPE_FROM_CLASS (klass),
342       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
343           pre_describe_request), pre_signal_accumulator, NULL, NULL,
344       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
345
346   /**
347    * GstRTSPClient::describe-request:
348    * @client: a #GstRTSPClient
349    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
350    */
351   gst_rtsp_client_signals[SIGNAL_DESCRIBE_REQUEST] =
352       g_signal_new ("describe-request", G_TYPE_FROM_CLASS (klass),
353       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, describe_request),
354       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
355
356   /**
357    * GstRTSPClient::pre-setup-request:
358    * @client: a #GstRTSPClient
359    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
360    *
361    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
362    *          otherwise an appropriate return code
363    *
364    * Since: 1.12
365    */
366   gst_rtsp_client_signals[SIGNAL_PRE_SETUP_REQUEST] =
367       g_signal_new ("pre-setup-request", G_TYPE_FROM_CLASS (klass),
368       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
369           pre_setup_request), pre_signal_accumulator, NULL, NULL,
370       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
371
372   /**
373    * GstRTSPClient::setup-request:
374    * @client: a #GstRTSPClient
375    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
376    */
377   gst_rtsp_client_signals[SIGNAL_SETUP_REQUEST] =
378       g_signal_new ("setup-request", G_TYPE_FROM_CLASS (klass),
379       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, setup_request),
380       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
381
382   /**
383    * GstRTSPClient::pre-play-request:
384    * @client: a #GstRTSPClient
385    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
386    *
387    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
388    *          otherwise an appropriate return code
389    *
390    * Since: 1.12
391    */
392   gst_rtsp_client_signals[SIGNAL_PRE_PLAY_REQUEST] =
393       g_signal_new ("pre-play-request", G_TYPE_FROM_CLASS (klass),
394       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
395           pre_play_request), pre_signal_accumulator, NULL,
396       NULL, GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
397
398   /**
399    * GstRTSPClient::play-request:
400    * @client: a #GstRTSPClient
401    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
402    */
403   gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST] =
404       g_signal_new ("play-request", G_TYPE_FROM_CLASS (klass),
405       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, play_request),
406       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
407
408   /**
409    * GstRTSPClient::pre-pause-request:
410    * @client: a #GstRTSPClient
411    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
412    *
413    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
414    *          otherwise an appropriate return code
415    *
416    * Since: 1.12
417    */
418   gst_rtsp_client_signals[SIGNAL_PRE_PAUSE_REQUEST] =
419       g_signal_new ("pre-pause-request", G_TYPE_FROM_CLASS (klass),
420       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
421           pre_pause_request), pre_signal_accumulator, NULL, NULL,
422       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
423
424   /**
425    * GstRTSPClient::pause-request:
426    * @client: a #GstRTSPClient
427    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
428    */
429   gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST] =
430       g_signal_new ("pause-request", G_TYPE_FROM_CLASS (klass),
431       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, pause_request),
432       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
433
434   /**
435    * GstRTSPClient::pre-teardown-request:
436    * @client: a #GstRTSPClient
437    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
438    *
439    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
440    *          otherwise an appropriate return code
441    *
442    * Since: 1.12
443    */
444   gst_rtsp_client_signals[SIGNAL_PRE_TEARDOWN_REQUEST] =
445       g_signal_new ("pre-teardown-request", G_TYPE_FROM_CLASS (klass),
446       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
447           pre_teardown_request), pre_signal_accumulator, NULL, NULL,
448       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
449
450   /**
451    * GstRTSPClient::teardown-request:
452    * @client: a #GstRTSPClient
453    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
454    */
455   gst_rtsp_client_signals[SIGNAL_TEARDOWN_REQUEST] =
456       g_signal_new ("teardown-request", G_TYPE_FROM_CLASS (klass),
457       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, teardown_request),
458       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
459
460   /**
461    * GstRTSPClient::pre-set-parameter-request:
462    * @client: a #GstRTSPClient
463    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
464    *
465    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
466    *          otherwise an appropriate return code
467    *
468    * Since: 1.12
469    */
470   gst_rtsp_client_signals[SIGNAL_PRE_SET_PARAMETER_REQUEST] =
471       g_signal_new ("pre-set-parameter-request", G_TYPE_FROM_CLASS (klass),
472       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
473           pre_set_parameter_request), pre_signal_accumulator, NULL, NULL,
474       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
475
476   /**
477    * GstRTSPClient::set-parameter-request:
478    * @client: a #GstRTSPClient
479    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
480    */
481   gst_rtsp_client_signals[SIGNAL_SET_PARAMETER_REQUEST] =
482       g_signal_new ("set-parameter-request", G_TYPE_FROM_CLASS (klass),
483       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
484           set_parameter_request), NULL, NULL, NULL,
485       G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
486
487   /**
488    * GstRTSPClient::pre-get-parameter-request:
489    * @client: a #GstRTSPClient
490    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
491    *
492    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
493    *          otherwise an appropriate return code
494    *
495    * Since: 1.12
496    */
497   gst_rtsp_client_signals[SIGNAL_PRE_GET_PARAMETER_REQUEST] =
498       g_signal_new ("pre-get-parameter-request", G_TYPE_FROM_CLASS (klass),
499       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
500           pre_get_parameter_request), pre_signal_accumulator, NULL, NULL,
501       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
502
503   /**
504    * GstRTSPClient::get-parameter-request:
505    * @client: a #GstRTSPClient
506    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
507    */
508   gst_rtsp_client_signals[SIGNAL_GET_PARAMETER_REQUEST] =
509       g_signal_new ("get-parameter-request", G_TYPE_FROM_CLASS (klass),
510       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
511           get_parameter_request), NULL, NULL, NULL,
512       G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
513
514   /**
515    * GstRTSPClient::handle-response:
516    * @client: a #GstRTSPClient
517    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
518    */
519   gst_rtsp_client_signals[SIGNAL_HANDLE_RESPONSE] =
520       g_signal_new ("handle-response", G_TYPE_FROM_CLASS (klass),
521       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
522           handle_response), NULL, NULL, NULL,
523       G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
524
525   /**
526    * GstRTSPClient::send-message:
527    * @client: The RTSP client
528    * @session: (type GstRtspServer.RTSPSession): The session
529    * @message: (type GstRtsp.RTSPMessage): The message
530    */
531   gst_rtsp_client_signals[SIGNAL_SEND_MESSAGE] =
532       g_signal_new ("send-message", G_TYPE_FROM_CLASS (klass),
533       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
534           send_message), NULL, NULL, NULL,
535       G_TYPE_NONE, 2, GST_TYPE_RTSP_CONTEXT, G_TYPE_POINTER);
536
537   /**
538    * GstRTSPClient::pre-announce-request:
539    * @client: a #GstRTSPClient
540    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
541    *
542    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
543    *          otherwise an appropriate return code
544    *
545    * Since: 1.12
546    */
547   gst_rtsp_client_signals[SIGNAL_PRE_ANNOUNCE_REQUEST] =
548       g_signal_new ("pre-announce-request", G_TYPE_FROM_CLASS (klass),
549       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
550           pre_announce_request), pre_signal_accumulator, NULL, NULL,
551       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
552
553   /**
554    * GstRTSPClient::announce-request:
555    * @client: a #GstRTSPClient
556    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
557    */
558   gst_rtsp_client_signals[SIGNAL_ANNOUNCE_REQUEST] =
559       g_signal_new ("announce-request", G_TYPE_FROM_CLASS (klass),
560       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, announce_request),
561       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
562
563   /**
564    * GstRTSPClient::pre-record-request:
565    * @client: a #GstRTSPClient
566    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
567    *
568    * Returns: a #GstRTSPStatusCode, GST_RTSP_STS_OK in case of success,
569    *          otherwise an appropriate return code
570    *
571    * Since: 1.12
572    */
573   gst_rtsp_client_signals[SIGNAL_PRE_RECORD_REQUEST] =
574       g_signal_new ("pre-record-request", G_TYPE_FROM_CLASS (klass),
575       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
576           pre_record_request), pre_signal_accumulator, NULL, NULL,
577       GST_TYPE_RTSP_STATUS_CODE, 1, GST_TYPE_RTSP_CONTEXT);
578
579   /**
580    * GstRTSPClient::record-request:
581    * @client: a #GstRTSPClient
582    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
583    */
584   gst_rtsp_client_signals[SIGNAL_RECORD_REQUEST] =
585       g_signal_new ("record-request", G_TYPE_FROM_CLASS (klass),
586       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass, record_request),
587       NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_RTSP_CONTEXT);
588
589   /**
590    * GstRTSPClient::check-requirements:
591    * @client: a #GstRTSPClient
592    * @ctx: (type GstRtspServer.RTSPContext): a #GstRTSPContext
593    * @arr: a NULL-terminated array of strings
594    *
595    * Returns: a newly allocated string with comma-separated list of
596    *          unsupported options. An empty string must be returned if
597    *          all options are supported.
598    *
599    * Since: 1.6
600    */
601   gst_rtsp_client_signals[SIGNAL_CHECK_REQUIREMENTS] =
602       g_signal_new ("check-requirements", G_TYPE_FROM_CLASS (klass),
603       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPClientClass,
604           check_requirements), NULL, NULL, NULL,
605       G_TYPE_STRING, 2, GST_TYPE_RTSP_CONTEXT, G_TYPE_STRV);
606
607   tunnels =
608       g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
609   g_mutex_init (&tunnels_lock);
610
611   GST_DEBUG_CATEGORY_INIT (rtsp_client_debug, "rtspclient", 0, "GstRTSPClient");
612 }
613
614 static void
615 gst_rtsp_client_init (GstRTSPClient * client)
616 {
617   GstRTSPClientPrivate *priv = gst_rtsp_client_get_instance_private (client);
618
619   client->priv = priv;
620
621   g_mutex_init (&priv->lock);
622   g_mutex_init (&priv->send_lock);
623   g_mutex_init (&priv->watch_lock);
624   priv->data_seqs = g_array_new (FALSE, FALSE, sizeof (DataSeq));
625   priv->drop_backlog = DEFAULT_DROP_BACKLOG;
626   priv->post_session_timeout = DEFAULT_POST_SESSION_TIMEOUT;
627   priv->transports =
628       g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
629       g_object_unref);
630   priv->pipelined_requests = g_hash_table_new_full (g_str_hash,
631       g_str_equal, g_free, g_free);
632   priv->tstate = TUNNEL_STATE_UNKNOWN;
633   priv->content_length_limit = G_MAXUINT;
634 }
635
636 static GstRTSPFilterResult
637 filter_session_media (GstRTSPSession * sess, GstRTSPSessionMedia * sessmedia,
638     gpointer user_data)
639 {
640   gboolean *closed = user_data;
641   GstRTSPMedia *media;
642   guint i, n_streams;
643   gboolean is_all_udp = TRUE;
644
645   media = gst_rtsp_session_media_get_media (sessmedia);
646   n_streams = gst_rtsp_media_n_streams (media);
647
648   for (i = 0; i < n_streams; i++) {
649     GstRTSPStreamTransport *transport =
650         gst_rtsp_session_media_get_transport (sessmedia, i);
651     const GstRTSPTransport *rtsp_transport;
652
653     if (!transport)
654       continue;
655
656     rtsp_transport = gst_rtsp_stream_transport_get_transport (transport);
657     if (rtsp_transport
658         && rtsp_transport->lower_transport != GST_RTSP_LOWER_TRANS_UDP
659         && rtsp_transport->lower_transport != GST_RTSP_LOWER_TRANS_UDP_MCAST) {
660       is_all_udp = FALSE;
661       break;
662     }
663   }
664
665   if (!is_all_udp || gst_rtsp_media_is_stop_on_disconnect (media)) {
666     gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
667     return GST_RTSP_FILTER_REMOVE;
668   } else {
669     *closed = FALSE;
670     return GST_RTSP_FILTER_KEEP;
671   }
672 }
673
674 static void
675 client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
676 {
677   GstRTSPClientPrivate *priv = client->priv;
678
679   g_mutex_lock (&priv->lock);
680   /* check if we already know about this session */
681   if (g_list_find (priv->sessions, session) == NULL) {
682     GST_INFO ("watching session %p", session);
683
684     priv->sessions = g_list_prepend (priv->sessions, g_object_ref (session));
685     priv->sessions_cookie++;
686
687     /* connect removed session handler, it will be disconnected when the last
688      * session gets removed  */
689     if (priv->session_removed_id == 0)
690       priv->session_removed_id = g_signal_connect_data (priv->session_pool,
691           "session-removed", G_CALLBACK (client_session_removed),
692           g_object_ref (client), (GClosureNotify) g_object_unref, 0);
693   }
694   g_mutex_unlock (&priv->lock);
695
696   return;
697 }
698
699 /* should be called with lock */
700 static void
701 client_unwatch_session (GstRTSPClient * client, GstRTSPSession * session,
702     GList * link)
703 {
704   GstRTSPClientPrivate *priv = client->priv;
705
706   GST_INFO ("client %p: unwatch session %p", client, session);
707
708   if (link == NULL) {
709     link = g_list_find (priv->sessions, session);
710     if (link == NULL)
711       return;
712   }
713
714   priv->sessions = g_list_delete_link (priv->sessions, link);
715   priv->sessions_cookie++;
716
717   /* if this was the last session, disconnect the handler.
718    * This will also drop the extra client ref */
719   if (!priv->sessions) {
720     g_signal_handler_disconnect (priv->session_pool, priv->session_removed_id);
721     priv->session_removed_id = 0;
722   }
723
724   if (!priv->drop_backlog) {
725     /* unlink all media managed in this session */
726     gst_rtsp_session_filter (session, filter_session_media, client);
727   }
728
729   /* remove the session */
730   g_object_unref (session);
731 }
732
733 static GstRTSPFilterResult
734 cleanup_session (GstRTSPClient * client, GstRTSPSession * sess,
735     gpointer user_data)
736 {
737   gboolean *closed = user_data;
738   GstRTSPClientPrivate *priv = client->priv;
739
740   if (priv->drop_backlog) {
741     /* unlink all media managed in this session. This needs to happen
742      * without the client lock, so we really want to do it here. */
743     gst_rtsp_session_filter (sess, filter_session_media, user_data);
744   }
745
746   if (*closed)
747     return GST_RTSP_FILTER_REMOVE;
748   else
749     return GST_RTSP_FILTER_KEEP;
750 }
751
752 static void
753 clean_cached_media (GstRTSPClient * client, gboolean unprepare)
754 {
755   GstRTSPClientPrivate *priv = client->priv;
756
757   if (priv->path) {
758     g_free (priv->path);
759     priv->path = NULL;
760   }
761   if (priv->media) {
762     if (unprepare)
763       gst_rtsp_media_unprepare (priv->media);
764     g_object_unref (priv->media);
765     priv->media = NULL;
766   }
767 }
768
769 /* A client is finalized when the connection is broken */
770 static void
771 gst_rtsp_client_finalize (GObject * obj)
772 {
773   GstRTSPClient *client = GST_RTSP_CLIENT (obj);
774   GstRTSPClientPrivate *priv = client->priv;
775
776   GST_INFO ("finalize client %p", client);
777
778   /* the watch and related state should be cleared before finalize
779    * as the watch actually holds a strong reference to the client */
780   g_assert (priv->watch == NULL);
781   g_assert (priv->rtsp_ctrl_timeout == NULL);
782
783   if (priv->watch_context) {
784     g_main_context_unref (priv->watch_context);
785     priv->watch_context = NULL;
786   }
787
788   gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
789   gst_rtsp_client_set_send_messages_func (client, NULL, NULL, NULL);
790
791   /* all sessions should have been removed by now. We keep a ref to
792    * the client object for the session removed handler. The ref is
793    * dropped when the last session is removed from the list. */
794   g_assert (priv->sessions == NULL);
795   g_assert (priv->session_removed_id == 0);
796
797   g_array_unref (priv->data_seqs);
798   g_hash_table_unref (priv->transports);
799   g_hash_table_unref (priv->pipelined_requests);
800
801   if (priv->connection)
802     gst_rtsp_connection_free (priv->connection);
803   if (priv->session_pool) {
804     g_object_unref (priv->session_pool);
805   }
806   if (priv->mount_points)
807     g_object_unref (priv->mount_points);
808   if (priv->auth)
809     g_object_unref (priv->auth);
810   if (priv->thread_pool)
811     g_object_unref (priv->thread_pool);
812
813   clean_cached_media (client, TRUE);
814
815   g_free (priv->server_ip);
816   g_mutex_clear (&priv->lock);
817   g_mutex_clear (&priv->send_lock);
818   g_mutex_clear (&priv->watch_lock);
819
820   G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
821 }
822
823 static void
824 gst_rtsp_client_get_property (GObject * object, guint propid,
825     GValue * value, GParamSpec * pspec)
826 {
827   GstRTSPClient *client = GST_RTSP_CLIENT (object);
828   GstRTSPClientPrivate *priv = client->priv;
829
830   switch (propid) {
831     case PROP_SESSION_POOL:
832       g_value_take_object (value, gst_rtsp_client_get_session_pool (client));
833       break;
834     case PROP_MOUNT_POINTS:
835       g_value_take_object (value, gst_rtsp_client_get_mount_points (client));
836       break;
837     case PROP_DROP_BACKLOG:
838       g_value_set_boolean (value, priv->drop_backlog);
839       break;
840     case PROP_POST_SESSION_TIMEOUT:
841       g_value_set_int (value, priv->post_session_timeout);
842       break;
843     default:
844       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
845   }
846 }
847
848 static void
849 gst_rtsp_client_set_property (GObject * object, guint propid,
850     const GValue * value, GParamSpec * pspec)
851 {
852   GstRTSPClient *client = GST_RTSP_CLIENT (object);
853   GstRTSPClientPrivate *priv = client->priv;
854
855   switch (propid) {
856     case PROP_SESSION_POOL:
857       gst_rtsp_client_set_session_pool (client, g_value_get_object (value));
858       break;
859     case PROP_MOUNT_POINTS:
860       gst_rtsp_client_set_mount_points (client, g_value_get_object (value));
861       break;
862     case PROP_DROP_BACKLOG:
863       g_mutex_lock (&priv->lock);
864       priv->drop_backlog = g_value_get_boolean (value);
865       g_mutex_unlock (&priv->lock);
866       break;
867     case PROP_POST_SESSION_TIMEOUT:
868       g_mutex_lock (&priv->lock);
869       priv->post_session_timeout = g_value_get_int (value);
870       g_mutex_unlock (&priv->lock);
871       break;
872     default:
873       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
874   }
875 }
876
877 /**
878  * gst_rtsp_client_new:
879  *
880  * Create a new #GstRTSPClient instance.
881  *
882  * Returns: (transfer full): a new #GstRTSPClient
883  */
884 GstRTSPClient *
885 gst_rtsp_client_new (void)
886 {
887   GstRTSPClient *result;
888
889   result = g_object_new (GST_TYPE_RTSP_CLIENT, NULL);
890
891   return result;
892 }
893
894 static void
895 send_message (GstRTSPClient * client, GstRTSPContext * ctx,
896     GstRTSPMessage * message, gboolean close)
897 {
898   GstRTSPClientPrivate *priv = client->priv;
899
900   gst_rtsp_message_add_header (message, GST_RTSP_HDR_SERVER,
901       "GStreamer RTSP server");
902
903   /* remove any previous header */
904   gst_rtsp_message_remove_header (message, GST_RTSP_HDR_SESSION, -1);
905
906   /* add the new session header for new session ids */
907   if (ctx->session) {
908     gst_rtsp_message_take_header (message, GST_RTSP_HDR_SESSION,
909         gst_rtsp_session_get_header (ctx->session));
910   }
911
912   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
913     gst_rtsp_message_dump (message);
914   }
915
916   if (close)
917     gst_rtsp_message_add_header (message, GST_RTSP_HDR_CONNECTION, "close");
918
919   if (ctx->request)
920     message->type_data.response.version =
921         ctx->request->type_data.request.version;
922
923   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SEND_MESSAGE],
924       0, ctx, message);
925
926   g_mutex_lock (&priv->send_lock);
927   if (priv->send_messages_func) {
928     priv->send_messages_func (client, message, 1, close, priv->send_data);
929   } else if (priv->send_func) {
930     priv->send_func (client, message, close, priv->send_data);
931   }
932   g_mutex_unlock (&priv->send_lock);
933
934   gst_rtsp_message_unset (message);
935 }
936
937 static void
938 send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
939     GstRTSPContext * ctx)
940 {
941   gst_rtsp_message_init_response (ctx->response, code,
942       gst_rtsp_status_as_text (code), ctx->request);
943
944   ctx->session = NULL;
945
946   send_message (client, ctx, ctx->response, FALSE);
947 }
948
949 static void
950 send_generic_error_response (GstRTSPClient * client, GstRTSPStatusCode code,
951     GstRTSPContext * ctx)
952 {
953   GstRTSPClientClass *klass = GST_RTSP_CLIENT_GET_CLASS (client);
954   GstRTSPStatusCode adjusted_code = code;
955
956   if (klass->adjust_error_code != NULL) {
957     adjusted_code = klass->adjust_error_code (client, ctx, code);
958     if (adjusted_code != code) {
959       GST_DEBUG ("adjusted response error code from %d to %d", code,
960           adjusted_code);
961     }
962   }
963   send_generic_response (client, adjusted_code, ctx);
964 }
965
966 static void
967 send_option_not_supported_response (GstRTSPClient * client,
968     GstRTSPContext * ctx, const gchar * unsupported_options)
969 {
970   GstRTSPStatusCode code = GST_RTSP_STS_OPTION_NOT_SUPPORTED;
971
972   gst_rtsp_message_init_response (ctx->response, code,
973       gst_rtsp_status_as_text (code), ctx->request);
974
975   if (unsupported_options != NULL) {
976     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_UNSUPPORTED,
977         unsupported_options);
978   }
979
980   ctx->session = NULL;
981
982   send_message (client, ctx, ctx->response, FALSE);
983 }
984
985 static gboolean
986 paths_are_equal (const gchar * path1, const gchar * path2, gint len2)
987 {
988   if (path1 == NULL || path2 == NULL)
989     return FALSE;
990
991   if (strlen (path1) != len2)
992     return FALSE;
993
994   if (strncmp (path1, path2, len2))
995     return FALSE;
996
997   return TRUE;
998 }
999
1000 /* this function is called to initially find the media for the DESCRIBE request
1001  * but is cached for when the same client (without breaking the connection) is
1002  * doing a setup for the exact same url. */
1003 static GstRTSPMedia *
1004 find_media (GstRTSPClient * client, GstRTSPContext * ctx, gchar * path,
1005     gint * matched)
1006 {
1007   GstRTSPClientPrivate *priv = client->priv;
1008   GstRTSPMediaFactory *factory;
1009   GstRTSPMedia *media;
1010   GstRTSPUrl *url;
1011   gint path_len;
1012
1013   /* find the longest matching factory for the uri first */
1014   if (!(factory = gst_rtsp_mount_points_match (priv->mount_points,
1015               path, matched)))
1016     goto no_factory;
1017
1018   ctx->factory = factory;
1019
1020   if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS))
1021     goto no_factory_access;
1022
1023   if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT))
1024     goto not_authorized;
1025
1026   if (matched)
1027     path_len = *matched;
1028   else
1029     path_len = strlen (path);
1030
1031   url = gst_rtsp_url_copy (ctx->uri);
1032   /* normalize rtsp://<IP>:<PORT> to rtsp://<IP>:<PORT>/ */
1033   if (url->abspath[0] == 0) {
1034     g_free (url->abspath);
1035     url->abspath = g_strdup ("/");
1036   }
1037
1038   if (!paths_are_equal (priv->path, path, path_len)) {
1039     /* remove any previously cached values before we try to construct a new
1040      * media for uri */
1041     clean_cached_media (client, TRUE);
1042
1043     /* prepare the media and add it to the pipeline */
1044     if (!(media = gst_rtsp_media_factory_construct (factory, url)))
1045       goto no_media;
1046
1047     ctx->media = media;
1048
1049     if (!(gst_rtsp_media_get_transport_mode (media) &
1050             GST_RTSP_TRANSPORT_MODE_RECORD)) {
1051       GstRTSPThread *thread;
1052
1053       thread = gst_rtsp_thread_pool_get_thread (priv->thread_pool,
1054           GST_RTSP_THREAD_TYPE_MEDIA, ctx);
1055       if (thread == NULL)
1056         goto no_thread;
1057
1058       /* prepare the media */
1059       if (!gst_rtsp_media_prepare (media, thread))
1060         goto no_prepare;
1061     }
1062
1063     /* now keep track of the uri and the media */
1064     priv->path = g_strndup (path, path_len);
1065     priv->media = media;
1066   } else {
1067     /* we have seen this path before, used cached media */
1068     media = priv->media;
1069     ctx->media = media;
1070     GST_INFO ("reusing cached media %p for path %s", media, priv->path);
1071   }
1072
1073   gst_rtsp_url_free (url);
1074   g_object_unref (factory);
1075   ctx->factory = NULL;
1076
1077   if (media)
1078     g_object_ref (media);
1079
1080   return media;
1081
1082   /* ERRORS */
1083 no_factory:
1084   {
1085     GST_ERROR ("client %p: no factory for path %s", client, path);
1086     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
1087     return NULL;
1088   }
1089 no_factory_access:
1090   {
1091     g_object_unref (factory);
1092     ctx->factory = NULL;
1093     GST_ERROR ("client %p: not authorized to see factory path %s", client,
1094         path);
1095     /* error reply is already sent */
1096     return NULL;
1097   }
1098 not_authorized:
1099   {
1100     g_object_unref (factory);
1101     ctx->factory = NULL;
1102     GST_ERROR ("client %p: not authorized for factory path %s", client, path);
1103     /* error reply is already sent */
1104     return NULL;
1105   }
1106 no_media:
1107   {
1108     GST_ERROR ("client %p: can't create media", client);
1109     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1110     gst_rtsp_url_free (url);
1111     g_object_unref (factory);
1112     ctx->factory = NULL;
1113     return NULL;
1114   }
1115 no_thread:
1116   {
1117     GST_ERROR ("client %p: can't create thread", client);
1118     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
1119     gst_rtsp_url_free (url);
1120     g_object_unref (media);
1121     ctx->media = NULL;
1122     g_object_unref (factory);
1123     ctx->factory = NULL;
1124     return NULL;
1125   }
1126 no_prepare:
1127   {
1128     GST_ERROR ("client %p: can't prepare media", client);
1129     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
1130     gst_rtsp_url_free (url);
1131     g_object_unref (media);
1132     ctx->media = NULL;
1133     g_object_unref (factory);
1134     ctx->factory = NULL;
1135     return NULL;
1136   }
1137 }
1138
1139 static inline DataSeq *
1140 get_data_seq_element (GstRTSPClient * client, guint8 channel)
1141 {
1142   GstRTSPClientPrivate *priv = client->priv;
1143   GArray *data_seqs = priv->data_seqs;
1144   gint i = 0;
1145
1146   while (i < data_seqs->len) {
1147     DataSeq *data_seq = &g_array_index (data_seqs, DataSeq, i);
1148     if (data_seq->channel == channel)
1149       return data_seq;
1150     i++;
1151   }
1152
1153   return NULL;
1154 }
1155
1156 static void
1157 add_data_seq (GstRTSPClient * client, guint8 channel)
1158 {
1159   GstRTSPClientPrivate *priv = client->priv;
1160   DataSeq data_seq = {.channel = channel,.seq = 0 };
1161
1162   if (get_data_seq_element (client, channel) == NULL)
1163     g_array_append_val (priv->data_seqs, data_seq);
1164 }
1165
1166 static void
1167 set_data_seq (GstRTSPClient * client, guint8 channel, guint seq)
1168 {
1169   DataSeq *data_seq;
1170
1171   data_seq = get_data_seq_element (client, channel);
1172   g_assert_nonnull (data_seq);
1173   data_seq->seq = seq;
1174 }
1175
1176 static guint
1177 get_data_seq (GstRTSPClient * client, guint8 channel)
1178 {
1179   DataSeq *data_seq;
1180
1181   data_seq = get_data_seq_element (client, channel);
1182   g_assert_nonnull (data_seq);
1183   return data_seq->seq;
1184 }
1185
1186 static gboolean
1187 get_data_channel (GstRTSPClient * client, guint seq, guint8 * channel)
1188 {
1189   GstRTSPClientPrivate *priv = client->priv;
1190   GArray *data_seqs = priv->data_seqs;
1191   gint i = 0;
1192
1193   while (i < data_seqs->len) {
1194     DataSeq *data_seq = &g_array_index (data_seqs, DataSeq, i);
1195     if (data_seq->seq == seq) {
1196       *channel = data_seq->channel;
1197       return TRUE;
1198     }
1199     i++;
1200   }
1201
1202   return FALSE;
1203 }
1204
1205 static gboolean
1206 do_close (gpointer user_data)
1207 {
1208   GstRTSPClient *client = user_data;
1209
1210   gst_rtsp_client_close (client);
1211
1212   return G_SOURCE_REMOVE;
1213 }
1214
1215 static gboolean
1216 do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
1217 {
1218   GstRTSPClientPrivate *priv = client->priv;
1219   GstRTSPMessage message = { 0 };
1220   gboolean ret = TRUE;
1221
1222   gst_rtsp_message_init_data (&message, channel);
1223
1224   gst_rtsp_message_set_body_buffer (&message, buffer);
1225
1226   g_mutex_lock (&priv->send_lock);
1227   if (get_data_seq (client, channel) != 0) {
1228     GST_WARNING ("already a queued data message for channel %d", channel);
1229     g_mutex_unlock (&priv->send_lock);
1230     return FALSE;
1231   }
1232   if (priv->send_messages_func) {
1233     ret =
1234         priv->send_messages_func (client, &message, 1, FALSE, priv->send_data);
1235   } else if (priv->send_func) {
1236     ret = priv->send_func (client, &message, FALSE, priv->send_data);
1237   }
1238   g_mutex_unlock (&priv->send_lock);
1239
1240   gst_rtsp_message_unset (&message);
1241
1242   if (!ret) {
1243     GSource *idle_src;
1244
1245     /* close in watch context */
1246     idle_src = g_idle_source_new ();
1247     g_source_set_callback (idle_src, do_close, client, NULL);
1248     g_source_attach (idle_src, priv->watch_context);
1249     g_source_unref (idle_src);
1250   }
1251
1252   return ret;
1253 }
1254
1255 static gboolean
1256 do_check_back_pressure (guint8 channel, GstRTSPClient * client)
1257 {
1258   return get_data_seq (client, channel) != 0;
1259 }
1260
1261 static gboolean
1262 do_send_data_list (GstBufferList * buffer_list, guint8 channel,
1263     GstRTSPClient * client)
1264 {
1265   GstRTSPClientPrivate *priv = client->priv;
1266   gboolean ret = TRUE;
1267   guint i, n = gst_buffer_list_length (buffer_list);
1268   GstRTSPMessage *messages;
1269
1270   g_mutex_lock (&priv->send_lock);
1271   if (get_data_seq (client, channel) != 0) {
1272     GST_WARNING ("already a queued data message for channel %d", channel);
1273     g_mutex_unlock (&priv->send_lock);
1274     return FALSE;
1275   }
1276
1277   messages = g_newa (GstRTSPMessage, n);
1278   memset (messages, 0, sizeof (GstRTSPMessage) * n);
1279   for (i = 0; i < n; i++) {
1280     GstBuffer *buffer = gst_buffer_list_get (buffer_list, i);
1281     gst_rtsp_message_init_data (&messages[i], channel);
1282     gst_rtsp_message_set_body_buffer (&messages[i], buffer);
1283   }
1284
1285   if (priv->send_messages_func) {
1286     ret =
1287         priv->send_messages_func (client, messages, n, FALSE, priv->send_data);
1288   } else if (priv->send_func) {
1289     for (i = 0; i < n; i++) {
1290       ret = priv->send_func (client, &messages[i], FALSE, priv->send_data);
1291       if (!ret)
1292         break;
1293     }
1294   }
1295   g_mutex_unlock (&priv->send_lock);
1296
1297   for (i = 0; i < n; i++) {
1298     gst_rtsp_message_unset (&messages[i]);
1299   }
1300
1301   if (!ret) {
1302     GSource *idle_src;
1303
1304     /* close in watch context */
1305     idle_src = g_idle_source_new ();
1306     g_source_set_callback (idle_src, do_close, client, NULL);
1307     g_source_attach (idle_src, priv->watch_context);
1308     g_source_unref (idle_src);
1309   }
1310
1311   return ret;
1312 }
1313
1314 /**
1315  * gst_rtsp_client_close:
1316  * @client: a #GstRTSPClient
1317  *
1318  * Close the connection of @client and remove all media it was managing.
1319  *
1320  * Since: 1.4
1321  */
1322 void
1323 gst_rtsp_client_close (GstRTSPClient * client)
1324 {
1325   GstRTSPClientPrivate *priv = client->priv;
1326   const gchar *tunnelid;
1327
1328   GST_DEBUG ("client %p: closing connection", client);
1329
1330   g_mutex_lock (&priv->watch_lock);
1331
1332   /* Work around the lack of thread safety of gst_rtsp_connection_close */
1333   if (priv->watch) {
1334     gst_rtsp_watch_set_flushing (priv->watch, TRUE);
1335   }
1336
1337   if (priv->connection) {
1338     if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) {
1339       g_mutex_lock (&tunnels_lock);
1340       /* remove from tunnelids */
1341       g_hash_table_remove (tunnels, tunnelid);
1342       g_mutex_unlock (&tunnels_lock);
1343     }
1344     gst_rtsp_connection_flush (priv->connection, TRUE);
1345     gst_rtsp_connection_close (priv->connection);
1346   }
1347
1348   if (priv->watch) {
1349     GST_DEBUG ("client %p: destroying watch", client);
1350     g_source_destroy ((GSource *) priv->watch);
1351     priv->watch = NULL;
1352     gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
1353     gst_rtsp_client_set_send_messages_func (client, NULL, NULL, NULL);
1354     rtsp_ctrl_timeout_remove (client);
1355   }
1356
1357   g_mutex_unlock (&priv->watch_lock);
1358 }
1359
1360 static gchar *
1361 default_make_path_from_uri (GstRTSPClient * client, const GstRTSPUrl * uri)
1362 {
1363   gchar *path;
1364
1365   if (uri->query) {
1366     path = g_strconcat (uri->abspath, "?", uri->query, NULL);
1367   } else {
1368     /* normalize rtsp://<IP>:<PORT> to rtsp://<IP>:<PORT>/ */
1369     path = g_strdup (uri->abspath[0] ? uri->abspath : "/");
1370   }
1371
1372   return path;
1373 }
1374
1375 /* Default signal handler function for all "pre-command" signals, like
1376  * pre-options-request. It just returns the RTSP return code 200.
1377  * Subclasses can override this to get another default behaviour.
1378  */
1379 static GstRTSPStatusCode
1380 default_pre_signal_handler (GstRTSPClient * client, GstRTSPContext * ctx)
1381 {
1382   GST_LOG_OBJECT (client, "returning GST_RTSP_STS_OK");
1383   return GST_RTSP_STS_OK;
1384 }
1385
1386 /* The pre-signal accumulator function checks the return value of the signal
1387  * handlers. If any of them returns an RTSP status code that does not start
1388  * with 2 it will return FALSE, no more signal handlers will be called, and
1389  * this last RTSP status code will be the result of the signal emission.
1390  */
1391 static gboolean
1392 pre_signal_accumulator (GSignalInvocationHint * ihint, GValue * return_accu,
1393     const GValue * handler_return, gpointer data)
1394 {
1395   GstRTSPStatusCode handler_value = g_value_get_enum (handler_return);
1396   GstRTSPStatusCode accumulated_value = g_value_get_enum (return_accu);
1397
1398   if (handler_value < 200 || handler_value > 299) {
1399     GST_DEBUG ("handler_value : %d, returning FALSE", handler_value);
1400     g_value_set_enum (return_accu, handler_value);
1401     return FALSE;
1402   }
1403
1404   /* the accumulated value is initiated to 0 by GLib. if current handler value is
1405    * bigger then use that instead
1406    *
1407    * FIXME: Should we prioritize the 2xx codes in a smarter way?
1408    *        Like, "201 Created" > "250 Low On Storage Space" > "200 OK"?
1409    */
1410   if (handler_value > accumulated_value)
1411     g_value_set_enum (return_accu, handler_value);
1412
1413   return TRUE;
1414 }
1415
1416 /* The cleanup_transports function is called from handle_teardown_request() to
1417  * remove any stream transports from the newly closed session that were added to
1418  * priv->transports in handle_setup_request(). This is done to avoid forwarding
1419  * data from the client on a channel that we just closed.
1420  */
1421 static void
1422 cleanup_transports (GstRTSPClient * client, GPtrArray * transports)
1423 {
1424   GstRTSPClientPrivate *priv = client->priv;
1425   GstRTSPStreamTransport *stream_transport;
1426   const GstRTSPTransport *rtsp_transport;
1427   guint i;
1428
1429   GST_LOG_OBJECT (client, "potentially removing %u transports",
1430       transports->len);
1431
1432   for (i = 0; i < transports->len; i++) {
1433     stream_transport = g_ptr_array_index (transports, i);
1434     if (stream_transport == NULL) {
1435       GST_LOG_OBJECT (client, "stream transport %u is NULL, continue", i);
1436       continue;
1437     }
1438
1439     rtsp_transport = gst_rtsp_stream_transport_get_transport (stream_transport);
1440     if (rtsp_transport == NULL) {
1441       GST_LOG_OBJECT (client, "RTSP transport %u is NULL, continue", i);
1442       continue;
1443     }
1444
1445     /* priv->transport only stores transports where RTP is tunneled over RTSP */
1446     if (rtsp_transport->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
1447       if (!g_hash_table_remove (priv->transports,
1448               GINT_TO_POINTER (rtsp_transport->interleaved.min))) {
1449         GST_WARNING_OBJECT (client,
1450             "failed removing transport with key '%d' from priv->transports",
1451             rtsp_transport->interleaved.min);
1452       }
1453       if (!g_hash_table_remove (priv->transports,
1454               GINT_TO_POINTER (rtsp_transport->interleaved.max))) {
1455         GST_WARNING_OBJECT (client,
1456             "failed removing transport with key '%d' from priv->transports",
1457             rtsp_transport->interleaved.max);
1458       }
1459     } else {
1460       GST_LOG_OBJECT (client, "transport %u not RTP/RTSP, skip it", i);
1461     }
1462   }
1463 }
1464
1465 static gboolean
1466 handle_teardown_request (GstRTSPClient * client, GstRTSPContext * ctx)
1467 {
1468   GstRTSPClientPrivate *priv = client->priv;
1469   GstRTSPClientClass *klass;
1470   GstRTSPSession *session;
1471   GstRTSPSessionMedia *sessmedia;
1472   GstRTSPMedia *media;
1473   GstRTSPStatusCode code;
1474   gchar *path;
1475   gint matched;
1476   gboolean keep_session;
1477   GstRTSPStatusCode sig_result;
1478   GPtrArray *session_media_transports;
1479
1480   if (!ctx->session)
1481     goto no_session;
1482
1483   session = ctx->session;
1484
1485   if (!ctx->uri)
1486     goto no_uri;
1487
1488   klass = GST_RTSP_CLIENT_GET_CLASS (client);
1489   path = klass->make_path_from_uri (client, ctx->uri);
1490
1491   /* get a handle to the configuration of the media in the session */
1492   sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
1493   if (!sessmedia)
1494     goto not_found;
1495
1496   /* only aggregate control for now.. */
1497   if (path[matched] != '\0')
1498     goto no_aggregate;
1499
1500   g_free (path);
1501
1502   ctx->sessmedia = sessmedia;
1503
1504   media = gst_rtsp_session_media_get_media (sessmedia);
1505   g_object_ref (media);
1506   gst_rtsp_media_lock (media);
1507
1508   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_TEARDOWN_REQUEST],
1509       0, ctx, &sig_result);
1510   if (sig_result != GST_RTSP_STS_OK) {
1511     goto sig_failed;
1512   }
1513
1514   /* get a reference to the transports in the session media so we can clean up
1515    * our priv->transports before returning */
1516   session_media_transports = gst_rtsp_session_media_get_transports (sessmedia);
1517
1518   /* we emit the signal before closing the connection */
1519   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_TEARDOWN_REQUEST],
1520       0, ctx);
1521
1522   gst_rtsp_session_media_set_state (sessmedia, GST_STATE_NULL);
1523
1524   /* unmanage the media in the session, returns false if all media session
1525    * are torn down. */
1526   keep_session = gst_rtsp_session_release_media (session, sessmedia);
1527   g_object_unref (sessmedia);
1528
1529   /* construct the response now */
1530   code = GST_RTSP_STS_OK;
1531   gst_rtsp_message_init_response (ctx->response, code,
1532       gst_rtsp_status_as_text (code), ctx->request);
1533
1534   send_message (client, ctx, ctx->response, TRUE);
1535
1536   if (!keep_session) {
1537     /* remove the session */
1538     gst_rtsp_session_pool_remove (priv->session_pool, session);
1539   }
1540
1541   gst_rtsp_media_unlock (media);
1542   g_object_unref (media);
1543
1544   /* remove all transports that were present in the session media which we just
1545    * unmanaged from the priv->transports array, so we do not try to handle data
1546    * on channels that were just closed */
1547   cleanup_transports (client, session_media_transports);
1548   g_ptr_array_unref (session_media_transports);
1549
1550   return TRUE;
1551
1552   /* ERRORS */
1553 no_session:
1554   {
1555     GST_ERROR ("client %p: no session", client);
1556     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
1557     return FALSE;
1558   }
1559 no_uri:
1560   {
1561     GST_ERROR ("client %p: no uri supplied", client);
1562     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1563     return FALSE;
1564   }
1565 not_found:
1566   {
1567     GST_ERROR ("client %p: no media for uri", client);
1568     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
1569     g_free (path);
1570     return FALSE;
1571   }
1572 no_aggregate:
1573   {
1574     GST_ERROR ("client %p: no aggregate path %s", client, path);
1575     send_generic_error_response (client,
1576         GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
1577     g_free (path);
1578     g_object_unref (sessmedia);
1579     return FALSE;
1580   }
1581 sig_failed:
1582   {
1583     GST_ERROR ("client %p: pre signal returned error: %s", client,
1584         gst_rtsp_status_as_text (sig_result));
1585     send_generic_error_response (client, sig_result, ctx);
1586     gst_rtsp_media_unlock (media);
1587     g_object_unref (media);
1588     g_object_unref (sessmedia);
1589     return FALSE;
1590   }
1591 }
1592
1593 static GstRTSPResult
1594 default_params_set (GstRTSPClient * client, GstRTSPContext * ctx)
1595 {
1596   GstRTSPResult res;
1597
1598   res = gst_rtsp_params_set (client, ctx);
1599
1600   return res;
1601 }
1602
1603 static GstRTSPResult
1604 default_params_get (GstRTSPClient * client, GstRTSPContext * ctx)
1605 {
1606   GstRTSPResult res;
1607
1608   res = gst_rtsp_params_get (client, ctx);
1609
1610   return res;
1611 }
1612
1613 static gboolean
1614 default_handle_get_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1615 {
1616   GstRTSPResult res;
1617   guint8 *data;
1618   guint size;
1619   GstRTSPStatusCode sig_result;
1620
1621   g_signal_emit (client,
1622       gst_rtsp_client_signals[SIGNAL_PRE_GET_PARAMETER_REQUEST], 0, ctx,
1623       &sig_result);
1624   if (sig_result != GST_RTSP_STS_OK) {
1625     goto sig_failed;
1626   }
1627
1628   res = gst_rtsp_message_get_body (ctx->request, &data, &size);
1629   if (res != GST_RTSP_OK)
1630     goto bad_request;
1631
1632   if (size == 0 || !data || strlen ((char *) data) == 0) {
1633     if (ctx->request->type_data.request.version >= GST_RTSP_VERSION_2_0) {
1634       GST_ERROR_OBJECT (client, "Using PLAY request for keep-alive is forbidden"
1635           " in RTSP 2.0");
1636       goto bad_request;
1637     }
1638
1639     /* no body (or only '\0'), keep-alive request */
1640     send_generic_response (client, GST_RTSP_STS_OK, ctx);
1641   } else {
1642     /* there is a body, handle the params */
1643     res = GST_RTSP_CLIENT_GET_CLASS (client)->params_get (client, ctx);
1644     if (res != GST_RTSP_OK)
1645       goto bad_request;
1646
1647     send_message (client, ctx, ctx->response, FALSE);
1648   }
1649
1650   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_GET_PARAMETER_REQUEST],
1651       0, ctx);
1652
1653   return TRUE;
1654
1655   /* ERRORS */
1656 sig_failed:
1657   {
1658     GST_ERROR ("client %p: pre signal returned error: %s", client,
1659         gst_rtsp_status_as_text (sig_result));
1660     send_generic_error_response (client, sig_result, ctx);
1661     return FALSE;
1662   }
1663 bad_request:
1664   {
1665     GST_ERROR ("client %p: bad request", client);
1666     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1667     return FALSE;
1668   }
1669 }
1670
1671 static gboolean
1672 default_handle_set_param_request (GstRTSPClient * client, GstRTSPContext * ctx)
1673 {
1674   GstRTSPResult res;
1675   guint8 *data;
1676   guint size;
1677   GstRTSPStatusCode sig_result;
1678
1679   g_signal_emit (client,
1680       gst_rtsp_client_signals[SIGNAL_PRE_SET_PARAMETER_REQUEST], 0, ctx,
1681       &sig_result);
1682   if (sig_result != GST_RTSP_STS_OK) {
1683     goto sig_failed;
1684   }
1685
1686   res = gst_rtsp_message_get_body (ctx->request, &data, &size);
1687   if (res != GST_RTSP_OK)
1688     goto bad_request;
1689
1690   if (size == 0 || !data || strlen ((char *) data) == 0) {
1691     /* no body (or only '\0'), keep-alive request */
1692     send_generic_response (client, GST_RTSP_STS_OK, ctx);
1693   } else {
1694     /* there is a body, handle the params */
1695     res = GST_RTSP_CLIENT_GET_CLASS (client)->params_set (client, ctx);
1696     if (res != GST_RTSP_OK)
1697       goto bad_request;
1698
1699     send_message (client, ctx, ctx->response, FALSE);
1700   }
1701
1702   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SET_PARAMETER_REQUEST],
1703       0, ctx);
1704
1705   return TRUE;
1706
1707   /* ERRORS */
1708 sig_failed:
1709   {
1710     GST_ERROR ("client %p: pre signal returned error: %s", client,
1711         gst_rtsp_status_as_text (sig_result));
1712     send_generic_error_response (client, sig_result, ctx);
1713     return FALSE;
1714   }
1715 bad_request:
1716   {
1717     GST_ERROR ("client %p: bad request", client);
1718     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1719     return FALSE;
1720   }
1721 }
1722
1723 static gboolean
1724 handle_pause_request (GstRTSPClient * client, GstRTSPContext * ctx)
1725 {
1726   GstRTSPSession *session;
1727   GstRTSPClientClass *klass;
1728   GstRTSPSessionMedia *sessmedia;
1729   GstRTSPMedia *media;
1730   GstRTSPStatusCode code;
1731   GstRTSPState rtspstate;
1732   gchar *path;
1733   gint matched;
1734   GstRTSPStatusCode sig_result;
1735   guint i, n;
1736
1737   if (!(session = ctx->session))
1738     goto no_session;
1739
1740   if (!ctx->uri)
1741     goto no_uri;
1742
1743   klass = GST_RTSP_CLIENT_GET_CLASS (client);
1744   path = klass->make_path_from_uri (client, ctx->uri);
1745
1746   /* get a handle to the configuration of the media in the session */
1747   sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
1748   if (!sessmedia)
1749     goto not_found;
1750
1751   if (path[matched] != '\0')
1752     goto no_aggregate;
1753
1754   g_free (path);
1755
1756   media = gst_rtsp_session_media_get_media (sessmedia);
1757   g_object_ref (media);
1758   gst_rtsp_media_lock (media);
1759   n = gst_rtsp_media_n_streams (media);
1760   for (i = 0; i < n; i++) {
1761     GstRTSPStream *stream = gst_rtsp_media_get_stream (media, i);
1762
1763     if (gst_rtsp_stream_get_publish_clock_mode (stream) ==
1764         GST_RTSP_PUBLISH_CLOCK_MODE_CLOCK_AND_OFFSET)
1765       goto not_supported;
1766   }
1767
1768   ctx->sessmedia = sessmedia;
1769
1770   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_PAUSE_REQUEST], 0,
1771       ctx, &sig_result);
1772   if (sig_result != GST_RTSP_STS_OK) {
1773     goto sig_failed;
1774   }
1775
1776   rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
1777   /* the session state must be playing or recording */
1778   if (rtspstate != GST_RTSP_STATE_PLAYING &&
1779       rtspstate != GST_RTSP_STATE_RECORDING)
1780     goto invalid_state;
1781
1782   /* then pause sending */
1783   gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PAUSED);
1784
1785   /* construct the response now */
1786   code = GST_RTSP_STS_OK;
1787   gst_rtsp_message_init_response (ctx->response, code,
1788       gst_rtsp_status_as_text (code), ctx->request);
1789
1790   send_message (client, ctx, ctx->response, FALSE);
1791
1792   /* the state is now READY */
1793   gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY);
1794   g_object_unref (sessmedia);
1795
1796   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PAUSE_REQUEST], 0, ctx);
1797
1798   gst_rtsp_media_unlock (media);
1799   g_object_unref (media);
1800
1801   return TRUE;
1802
1803   /* ERRORS */
1804 no_session:
1805   {
1806     GST_ERROR ("client %p: no session", client);
1807     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
1808     return FALSE;
1809   }
1810 no_uri:
1811   {
1812     GST_ERROR ("client %p: no uri supplied", client);
1813     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1814     return FALSE;
1815   }
1816 not_found:
1817   {
1818     GST_ERROR ("client %p: no media for uri", client);
1819     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
1820     g_free (path);
1821     return FALSE;
1822   }
1823 no_aggregate:
1824   {
1825     GST_ERROR ("client %p: no aggregate path %s", client, path);
1826     send_generic_error_response (client,
1827         GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
1828     g_object_unref (sessmedia);
1829     g_free (path);
1830     return FALSE;
1831   }
1832 sig_failed:
1833   {
1834     GST_ERROR ("client %p: pre signal returned error: %s", client,
1835         gst_rtsp_status_as_text (sig_result));
1836     send_generic_error_response (client, sig_result, ctx);
1837     gst_rtsp_media_unlock (media);
1838     g_object_unref (sessmedia);
1839     g_object_unref (media);
1840     return FALSE;
1841   }
1842 invalid_state:
1843   {
1844     GST_ERROR ("client %p: not PLAYING or RECORDING", client);
1845     send_generic_error_response (client,
1846         GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, ctx);
1847     gst_rtsp_media_unlock (media);
1848     g_object_unref (sessmedia);
1849     g_object_unref (media);
1850     return FALSE;
1851   }
1852 not_supported:
1853   {
1854     GST_ERROR ("client %p: pausing not supported", client);
1855     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
1856     gst_rtsp_media_unlock (media);
1857     g_object_unref (sessmedia);
1858     g_object_unref (media);
1859     return FALSE;
1860   }
1861 }
1862
1863 /* convert @url and @path to a URL used as a content base for the factory
1864  * located at @path */
1865 static gchar *
1866 make_base_url (GstRTSPClient * client, GstRTSPUrl * url, const gchar * path)
1867 {
1868   GstRTSPUrl tmp;
1869   gchar *result;
1870   const gchar *trail;
1871
1872   /* check for trailing '/' and append one */
1873   trail = (path[strlen (path) - 1] != '/' ? "/" : "");
1874
1875   tmp = *url;
1876   tmp.user = NULL;
1877   tmp.passwd = NULL;
1878   tmp.abspath = g_strdup_printf ("%s%s", path, trail);
1879   tmp.query = NULL;
1880   result = gst_rtsp_url_get_request_uri (&tmp);
1881   g_free (tmp.abspath);
1882
1883   return result;
1884 }
1885
1886 /* Check if the given header of type double is present and, if so,
1887  * put it's value in the supplied variable.
1888  */
1889 static GstRTSPStatusCode
1890 parse_header_value_double (GstRTSPClient * client, GstRTSPContext * ctx,
1891     GstRTSPHeaderField header, gboolean * present, gdouble * value)
1892 {
1893   GstRTSPResult res;
1894   gchar *str;
1895   gchar *end;
1896
1897   res = gst_rtsp_message_get_header (ctx->request, header, &str, 0);
1898   if (res == GST_RTSP_OK) {
1899     *value = g_ascii_strtod (str, &end);
1900     if (end == str)
1901       goto parse_header_failed;
1902
1903     GST_DEBUG ("client %p: got '%s', value %f", client,
1904         gst_rtsp_header_as_text (header), *value);
1905     *present = TRUE;
1906   } else {
1907     *present = FALSE;
1908   }
1909
1910   return GST_RTSP_STS_OK;
1911
1912 parse_header_failed:
1913   {
1914     GST_ERROR ("client %p: failed parsing '%s' header", client,
1915         gst_rtsp_header_as_text (header));
1916     return GST_RTSP_STS_BAD_REQUEST;
1917   }
1918 }
1919
1920 /* Parse scale and speed headers, if present, and set the rate to
1921  * (rate * scale * speed) */
1922 static GstRTSPStatusCode
1923 parse_scale_and_speed (GstRTSPClient * client, GstRTSPContext * ctx,
1924     gboolean * scale_present, gboolean * speed_present, gdouble * rate,
1925     GstSeekFlags * flags)
1926 {
1927   gdouble scale = 1.0;
1928   gdouble speed = 1.0;
1929   GstRTSPStatusCode status;
1930
1931   GST_DEBUG ("got rate %f", *rate);
1932
1933   status = parse_header_value_double (client, ctx, GST_RTSP_HDR_SCALE,
1934       scale_present, &scale);
1935   if (status != GST_RTSP_STS_OK)
1936     return status;
1937
1938   if (*scale_present) {
1939     GST_DEBUG ("got Scale %f", scale);
1940     if (scale == 0)
1941       goto bad_scale_value;
1942     *rate *= scale;
1943
1944     if (ABS (scale) != 1.0)
1945       *flags |= GST_SEEK_FLAG_TRICKMODE;
1946   }
1947
1948   GST_DEBUG ("rate after parsing Scale %f", *rate);
1949
1950   status = parse_header_value_double (client, ctx, GST_RTSP_HDR_SPEED,
1951       speed_present, &speed);
1952   if (status != GST_RTSP_STS_OK)
1953     return status;
1954
1955   if (*speed_present) {
1956     GST_DEBUG ("got Speed %f", speed);
1957     if (speed <= 0)
1958       goto bad_speed_value;
1959     *rate *= speed;
1960   }
1961
1962   GST_DEBUG ("rate after parsing Speed %f", *rate);
1963
1964   return status;
1965
1966 bad_scale_value:
1967   {
1968     GST_ERROR ("client %p: bad 'Scale' header value (%f)", client, scale);
1969     return GST_RTSP_STS_BAD_REQUEST;
1970   }
1971 bad_speed_value:
1972   {
1973     GST_ERROR ("client %p: bad 'Speed' header value (%f)", client, speed);
1974     return GST_RTSP_STS_BAD_REQUEST;
1975   }
1976 }
1977
1978 static GstRTSPStatusCode
1979 setup_play_mode (GstRTSPClient * client, GstRTSPContext * ctx,
1980     GstRTSPRangeUnit * unit, gboolean * scale_present, gboolean * speed_present)
1981 {
1982   gchar *str;
1983   GstRTSPResult res;
1984   GstRTSPTimeRange *range = NULL;
1985   gdouble rate = 1.0;
1986   GstSeekFlags flags = GST_SEEK_FLAG_NONE;
1987   GstRTSPClientClass *klass = GST_RTSP_CLIENT_GET_CLASS (client);
1988   GstRTSPStatusCode rtsp_status_code;
1989   GstClockTime trickmode_interval = 0;
1990   gboolean enable_rate_control = TRUE;
1991
1992   /* parse the range header if we have one */
1993   res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_RANGE, &str, 0);
1994   if (res == GST_RTSP_OK) {
1995     gchar *seek_style = NULL;
1996
1997     res = gst_rtsp_range_parse (str, &range);
1998     if (res != GST_RTSP_OK)
1999       goto parse_range_failed;
2000
2001     *unit = range->unit;
2002
2003     /* parse seek style header, if present */
2004     res = gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_SEEK_STYLE,
2005         &seek_style, 0);
2006
2007     if (res == GST_RTSP_OK) {
2008       if (g_strcmp0 (seek_style, "RAP") == 0)
2009         flags = GST_SEEK_FLAG_ACCURATE;
2010       else if (g_strcmp0 (seek_style, "CoRAP") == 0)
2011         flags = GST_SEEK_FLAG_KEY_UNIT;
2012       else if (g_strcmp0 (seek_style, "First-Prior") == 0)
2013         flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_BEFORE;
2014       else if (g_strcmp0 (seek_style, "Next") == 0)
2015         flags = GST_SEEK_FLAG_KEY_UNIT & GST_SEEK_FLAG_SNAP_AFTER;
2016       else
2017         GST_FIXME_OBJECT (client, "Add support for seek style %s", seek_style);
2018     } else if (range->min.type == GST_RTSP_TIME_END) {
2019       flags = GST_SEEK_FLAG_ACCURATE;
2020     } else {
2021       flags = GST_SEEK_FLAG_KEY_UNIT;
2022     }
2023
2024     if (seek_style)
2025       gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_SEEK_STYLE,
2026           seek_style);
2027   } else {
2028     flags = GST_SEEK_FLAG_ACCURATE;
2029   }
2030
2031   /* check for scale and/or speed headers
2032    * we will set the seek rate to (speed * scale) and let the media decide
2033    * the resulting scale and speed. in the response we will use rate and applied
2034    * rate from the resulting segment as values for the speed and scale headers
2035    * respectively */
2036   rtsp_status_code = parse_scale_and_speed (client, ctx, scale_present,
2037       speed_present, &rate, &flags);
2038   if (rtsp_status_code != GST_RTSP_STS_OK)
2039     goto scale_speed_failed;
2040
2041   /* give the application a chance to tweak range, flags, or rate */
2042   if (klass->adjust_play_mode != NULL) {
2043     rtsp_status_code =
2044         klass->adjust_play_mode (client, ctx, &range, &flags, &rate,
2045         &trickmode_interval, &enable_rate_control);
2046     if (rtsp_status_code != GST_RTSP_STS_OK)
2047       goto adjust_play_mode_failed;
2048   }
2049
2050   gst_rtsp_media_set_rate_control (ctx->media, enable_rate_control);
2051
2052   /* now do the seek with the seek options */
2053   gst_rtsp_media_seek_trickmode (ctx->media, range, flags, rate,
2054       trickmode_interval);
2055   if (range != NULL)
2056     gst_rtsp_range_free (range);
2057
2058   if (gst_rtsp_media_get_status (ctx->media) == GST_RTSP_MEDIA_STATUS_ERROR)
2059     goto seek_failed;
2060
2061   return GST_RTSP_STS_OK;
2062
2063 parse_range_failed:
2064   {
2065     GST_ERROR ("client %p: failed parsing range header", client);
2066     return GST_RTSP_STS_BAD_REQUEST;
2067   }
2068 scale_speed_failed:
2069   {
2070     if (range != NULL)
2071       gst_rtsp_range_free (range);
2072     GST_ERROR ("client %p: failed parsing Scale or Speed headers", client);
2073     return rtsp_status_code;
2074   }
2075 adjust_play_mode_failed:
2076   {
2077     GST_ERROR ("client %p: sub class returned bad code (%d)", client,
2078         rtsp_status_code);
2079     if (range != NULL)
2080       gst_rtsp_range_free (range);
2081     return rtsp_status_code;
2082   }
2083 seek_failed:
2084   {
2085     GST_ERROR ("client %p: seek failed", client);
2086     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
2087   }
2088 }
2089
2090 static gboolean
2091 default_handle_play_request (GstRTSPClient * client, GstRTSPContext * ctx)
2092 {
2093   GstRTSPSession *session;
2094   GstRTSPClientClass *klass;
2095   GstRTSPSessionMedia *sessmedia;
2096   GstRTSPMedia *media;
2097   GstRTSPStatusCode code;
2098   GstRTSPUrl *uri;
2099   gchar *str;
2100   GstRTSPState rtspstate;
2101   GstRTSPRangeUnit unit = GST_RTSP_RANGE_NPT;
2102   gchar *path, *rtpinfo = NULL;
2103   gint matched;
2104   GstRTSPStatusCode sig_result;
2105   GPtrArray *transports;
2106   gboolean scale_present;
2107   gboolean speed_present;
2108   gdouble rate;
2109   gdouble applied_rate;
2110
2111   if (!(session = ctx->session))
2112     goto no_session;
2113
2114   if (!(uri = ctx->uri))
2115     goto no_uri;
2116
2117   klass = GST_RTSP_CLIENT_GET_CLASS (client);
2118   path = klass->make_path_from_uri (client, uri);
2119
2120   /* get a handle to the configuration of the media in the session */
2121   sessmedia = gst_rtsp_session_dup_media (session, path, &matched);
2122   if (!sessmedia)
2123     goto not_found;
2124
2125   if (path[matched] != '\0')
2126     goto no_aggregate;
2127
2128   g_free (path);
2129
2130   ctx->sessmedia = sessmedia;
2131   ctx->media = media = gst_rtsp_session_media_get_media (sessmedia);
2132
2133   g_object_ref (media);
2134   gst_rtsp_media_lock (media);
2135
2136   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_PLAY_REQUEST], 0,
2137       ctx, &sig_result);
2138   if (sig_result != GST_RTSP_STS_OK) {
2139     goto sig_failed;
2140   }
2141
2142   if (!(gst_rtsp_media_get_transport_mode (media) &
2143           GST_RTSP_TRANSPORT_MODE_PLAY))
2144     goto unsupported_mode;
2145
2146   /* the session state must be playing or ready */
2147   rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
2148   if (rtspstate != GST_RTSP_STATE_PLAYING && rtspstate != GST_RTSP_STATE_READY)
2149     goto invalid_state;
2150
2151   /* update the pipeline */
2152   transports = gst_rtsp_session_media_get_transports (sessmedia);
2153   if (!gst_rtsp_media_complete_pipeline (media, transports)) {
2154     g_ptr_array_unref (transports);
2155     goto pipeline_error;
2156   }
2157   g_ptr_array_unref (transports);
2158
2159   /* in play we first unsuspend, media could be suspended from SDP or PAUSED */
2160   if (!gst_rtsp_media_unsuspend (media))
2161     goto unsuspend_failed;
2162
2163   code = setup_play_mode (client, ctx, &unit, &scale_present, &speed_present);
2164   if (code != GST_RTSP_STS_OK)
2165     goto invalid_mode;
2166
2167   /* grab RTPInfo from the media now */
2168   if (gst_rtsp_media_has_completed_sender (media) &&
2169       !(rtpinfo = gst_rtsp_session_media_get_rtpinfo (sessmedia)))
2170     goto rtp_info_error;
2171
2172   /* construct the response now */
2173   code = GST_RTSP_STS_OK;
2174   gst_rtsp_message_init_response (ctx->response, code,
2175       gst_rtsp_status_as_text (code), ctx->request);
2176
2177   /* add the RTP-Info header */
2178   if (rtpinfo)
2179     gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_RTP_INFO,
2180         rtpinfo);
2181
2182   /* add the range */
2183   str = gst_rtsp_media_get_range_string (media, TRUE, unit);
2184   if (str)
2185     gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_RANGE, str);
2186
2187   if (gst_rtsp_media_has_completed_sender (media)) {
2188     /* the scale and speed headers must always be added if they were present in
2189      * the request. however, even if they were not, we still add them if
2190      * applied_rate or rate deviate from the "normal", i.e. 1.0 */
2191 #ifdef TIZEN_PROFILE_TV
2192     /* Temporal workaround fix for TV */
2193     rate = applied_rate = 1.0;
2194 #else
2195     if (!gst_rtsp_media_get_rates (media, &rate, &applied_rate))
2196       goto get_rates_error;
2197     g_assert (rate != 0 && applied_rate != 0);
2198 #endif
2199     if (scale_present || applied_rate != 1.0)
2200       gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_SCALE,
2201           g_strdup_printf ("%1.3f", applied_rate));
2202
2203     if (speed_present || rate != 1.0)
2204       gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_SPEED,
2205           g_strdup_printf ("%1.3f", rate));
2206   }
2207
2208   if (klass->adjust_play_response) {
2209     code = klass->adjust_play_response (client, ctx);
2210     if (code != GST_RTSP_STS_OK)
2211       goto adjust_play_response_failed;
2212   }
2213
2214   send_message (client, ctx, ctx->response, FALSE);
2215
2216   /* start playing after sending the response */
2217   gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PLAYING);
2218
2219   gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_PLAYING);
2220   g_object_unref (sessmedia);
2221
2222   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PLAY_REQUEST], 0, ctx);
2223
2224   gst_rtsp_media_unlock (media);
2225   g_object_unref (media);
2226
2227   return TRUE;
2228
2229   /* ERRORS */
2230 no_session:
2231   {
2232     GST_ERROR ("client %p: no session", client);
2233     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
2234     return FALSE;
2235   }
2236 no_uri:
2237   {
2238     GST_ERROR ("client %p: no uri supplied", client);
2239     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
2240     return FALSE;
2241   }
2242 not_found:
2243   {
2244     GST_ERROR ("client %p: media not found", client);
2245     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
2246     return FALSE;
2247   }
2248 no_aggregate:
2249   {
2250     GST_ERROR ("client %p: no aggregate path %s", client, path);
2251     send_generic_error_response (client,
2252         GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
2253     g_object_unref (sessmedia);
2254     g_free (path);
2255     return FALSE;
2256   }
2257 sig_failed:
2258   {
2259     GST_ERROR ("client %p: pre signal returned error: %s", client,
2260         gst_rtsp_status_as_text (sig_result));
2261     send_generic_error_response (client, sig_result, ctx);
2262     gst_rtsp_media_unlock (media);
2263     g_object_unref (media);
2264     g_object_unref (sessmedia);
2265     return FALSE;
2266   }
2267 invalid_state:
2268   {
2269     GST_ERROR ("client %p: not PLAYING or READY", client);
2270     send_generic_error_response (client,
2271         GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, ctx);
2272     gst_rtsp_media_unlock (media);
2273     g_object_unref (media);
2274     g_object_unref (sessmedia);
2275     return FALSE;
2276   }
2277 pipeline_error:
2278   {
2279     GST_ERROR ("client %p: failed to configure the pipeline", client);
2280     send_generic_error_response (client,
2281         GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, ctx);
2282     gst_rtsp_media_unlock (media);
2283     g_object_unref (media);
2284     g_object_unref (sessmedia);
2285     return FALSE;
2286   }
2287 unsuspend_failed:
2288   {
2289     GST_ERROR ("client %p: unsuspend failed", client);
2290     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
2291     gst_rtsp_media_unlock (media);
2292     g_object_unref (media);
2293     g_object_unref (sessmedia);
2294     return FALSE;
2295   }
2296 invalid_mode:
2297   {
2298     GST_ERROR ("client %p: seek failed", client);
2299     send_generic_error_response (client, code, ctx);
2300     gst_rtsp_media_unlock (media);
2301     g_object_unref (media);
2302     g_object_unref (sessmedia);
2303     return FALSE;
2304   }
2305 unsupported_mode:
2306   {
2307     GST_ERROR ("client %p: media does not support PLAY", client);
2308     send_generic_error_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx);
2309     gst_rtsp_media_unlock (media);
2310     g_object_unref (media);
2311     g_object_unref (sessmedia);
2312     return FALSE;
2313   }
2314 get_rates_error:
2315   {
2316     GST_ERROR ("client %p: failed obtaining rate and applied_rate", client);
2317     send_generic_error_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR,
2318         ctx);
2319     gst_rtsp_media_unlock (media);
2320     g_object_unref (media);
2321     g_object_unref (sessmedia);
2322     return FALSE;
2323   }
2324 adjust_play_response_failed:
2325   {
2326     GST_ERROR ("client %p: failed to adjust play response", client);
2327     send_generic_error_response (client, code, ctx);
2328     gst_rtsp_media_unlock (media);
2329     g_object_unref (media);
2330     g_object_unref (sessmedia);
2331     return FALSE;
2332   }
2333 rtp_info_error:
2334   {
2335     GST_ERROR ("client %p: failed to add RTP-Info", client);
2336     send_generic_error_response (client, GST_RTSP_STS_INTERNAL_SERVER_ERROR,
2337         ctx);
2338     gst_rtsp_media_unlock (media);
2339     g_object_unref (media);
2340     g_object_unref (sessmedia);
2341     return FALSE;
2342   }
2343 }
2344
2345 static void
2346 do_keepalive (GstRTSPSession * session)
2347 {
2348   GST_INFO ("keep session %p alive", session);
2349   gst_rtsp_session_touch (session);
2350 }
2351
2352 /* parse @transport and return a valid transport in @tr. only transports
2353  * supported by @stream are returned. Returns FALSE if no valid transport
2354  * was found. */
2355 static gboolean
2356 parse_transport (const char *transport, GstRTSPStream * stream,
2357     GstRTSPTransport * tr)
2358 {
2359   gint i;
2360   gboolean res;
2361   gchar **transports;
2362
2363   res = FALSE;
2364   gst_rtsp_transport_init (tr);
2365
2366   GST_DEBUG ("parsing transports %s", transport);
2367
2368   transports = g_strsplit (transport, ",", 0);
2369
2370   /* loop through the transports, try to parse */
2371   for (i = 0; transports[i]; i++) {
2372     g_strstrip (transports[i]);
2373     res = gst_rtsp_transport_parse (transports[i], tr);
2374     if (res != GST_RTSP_OK) {
2375       /* no valid transport, search some more */
2376       GST_WARNING ("could not parse transport %s", transports[i]);
2377       goto next;
2378     }
2379
2380     /* we have a transport, see if it's supported */
2381     if (!gst_rtsp_stream_is_transport_supported (stream, tr)) {
2382       GST_WARNING ("unsupported transport %s", transports[i]);
2383       goto next;
2384     }
2385
2386     /* we have a valid transport */
2387     GST_INFO ("found valid transport %s", transports[i]);
2388     res = TRUE;
2389     break;
2390
2391   next:
2392     gst_rtsp_transport_init (tr);
2393   }
2394   g_strfreev (transports);
2395
2396   return res;
2397 }
2398
2399 static gboolean
2400 default_configure_client_media (GstRTSPClient * client, GstRTSPMedia * media,
2401     GstRTSPStream * stream, GstRTSPContext * ctx)
2402 {
2403   GstRTSPMessage *request = ctx->request;
2404   gchar *blocksize_str;
2405
2406   if (!gst_rtsp_stream_is_sender (stream))
2407     return TRUE;
2408
2409   if (gst_rtsp_message_get_header (request, GST_RTSP_HDR_BLOCKSIZE,
2410           &blocksize_str, 0) == GST_RTSP_OK) {
2411     guint64 blocksize;
2412     gchar *end;
2413
2414     blocksize = g_ascii_strtoull (blocksize_str, &end, 10);
2415     if (end == blocksize_str)
2416       goto parse_failed;
2417
2418     /* we don't want to change the mtu when this media
2419      * can be shared because it impacts other clients */
2420     if (gst_rtsp_media_is_shared (media))
2421       goto done;
2422
2423     if (blocksize > G_MAXUINT)
2424       blocksize = G_MAXUINT;
2425
2426     gst_rtsp_stream_set_mtu (stream, blocksize);
2427   }
2428 done:
2429   return TRUE;
2430
2431   /* ERRORS */
2432 parse_failed:
2433   {
2434     GST_ERROR_OBJECT (client, "failed to parse blocksize");
2435     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
2436     return FALSE;
2437   }
2438 }
2439
2440 static gboolean
2441 default_configure_client_transport (GstRTSPClient * client,
2442     GstRTSPContext * ctx, GstRTSPTransport * ct)
2443 {
2444   GstRTSPClientPrivate *priv = client->priv;
2445
2446   /* we have a valid transport now, set the destination of the client. */
2447   if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST ||
2448       ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP) {
2449     /* allocate UDP ports */
2450     GSocketFamily family;
2451     gboolean use_client_settings = FALSE;
2452
2453     family = priv->is_ipv6 ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_IPV4;
2454
2455     if ((ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) &&
2456         gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS) &&
2457         (ct->destination != NULL)) {
2458
2459       if (!gst_rtsp_stream_verify_mcast_ttl (ctx->stream, ct->ttl))
2460         goto error_ttl;
2461
2462       use_client_settings = TRUE;
2463     }
2464
2465     /* We need to allocate the sockets for both families before starting
2466      * multiudpsink, otherwise multiudpsink won't accept new clients with
2467      * a different family.
2468      */
2469     /* FIXME: could be more adequately solved by making it possible
2470      * to set a socket on multiudpsink after it has already been started */
2471     if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream,
2472             G_SOCKET_FAMILY_IPV4, ct, use_client_settings)
2473         && family == G_SOCKET_FAMILY_IPV4)
2474       goto error_allocating_ports;
2475
2476     if (!gst_rtsp_stream_allocate_udp_sockets (ctx->stream,
2477             G_SOCKET_FAMILY_IPV6, ct, use_client_settings)
2478         && family == G_SOCKET_FAMILY_IPV6)
2479       goto error_allocating_ports;
2480
2481     if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
2482       if (use_client_settings) {
2483         /* FIXME: the address has been successfully allocated, however, in
2484          * the use_client_settings case we need to verify that the allocated
2485          * address is the one requested by the client and if this address is
2486          * an allowed destination. Verifying this via the address pool in not
2487          * the proper way as the address pool should only be used for choosing
2488          * the server-selected address/port pairs. */
2489         GSocket *rtp_socket;
2490         guint ttl;
2491
2492         rtp_socket =
2493             gst_rtsp_stream_get_rtp_multicast_socket (ctx->stream, family);
2494         if (rtp_socket == NULL)
2495           goto no_socket;
2496         ttl = g_socket_get_multicast_ttl (rtp_socket);
2497         g_object_unref (rtp_socket);
2498         if (ct->ttl < ttl) {
2499           /* use the maximum ttl that is requested by multicast clients */
2500           GST_DEBUG ("requested ttl %u, but keeping ttl %u", ct->ttl, ttl);
2501           ct->ttl = ttl;
2502         }
2503
2504       } else {
2505         GstRTSPAddress *addr = NULL;
2506
2507         g_free (ct->destination);
2508         addr = gst_rtsp_stream_get_multicast_address (ctx->stream, family);
2509         if (addr == NULL)
2510           goto no_address;
2511         ct->destination = g_strdup (addr->address);
2512         ct->port.min = addr->port;
2513         ct->port.max = addr->port + addr->n_ports - 1;
2514         ct->ttl = addr->ttl;
2515         gst_rtsp_address_free (addr);
2516       }
2517
2518       if (!gst_rtsp_stream_add_multicast_client_address (ctx->stream,
2519               ct->destination, ct->port.min, ct->port.max, family))
2520         goto error_mcast_transport;
2521
2522     } else {
2523       GstRTSPUrl *url;
2524
2525       url = gst_rtsp_connection_get_url (priv->connection);
2526       g_free (ct->destination);
2527       ct->destination = g_strdup (url->host);
2528     }
2529   } else {
2530     GstRTSPUrl *url;
2531
2532     url = gst_rtsp_connection_get_url (priv->connection);
2533     g_free (ct->destination);
2534     ct->destination = g_strdup (url->host);
2535
2536     if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) {
2537       GSocket *sock;
2538       GSocketAddress *addr;
2539
2540       sock = gst_rtsp_connection_get_read_socket (priv->connection);
2541       if ((addr = g_socket_get_remote_address (sock, NULL))) {
2542         /* our read port is the sender port of client */
2543         ct->client_port.min =
2544             g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
2545         g_object_unref (addr);
2546       }
2547       if ((addr = g_socket_get_local_address (sock, NULL))) {
2548         ct->server_port.max =
2549             g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
2550         g_object_unref (addr);
2551       }
2552       sock = gst_rtsp_connection_get_write_socket (priv->connection);
2553       if ((addr = g_socket_get_remote_address (sock, NULL))) {
2554         /* our write port is the receiver port of client */
2555         ct->client_port.max =
2556             g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
2557         g_object_unref (addr);
2558       }
2559       if ((addr = g_socket_get_local_address (sock, NULL))) {
2560         ct->server_port.min =
2561             g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr));
2562         g_object_unref (addr);
2563       }
2564       /* check if the client selected channels for TCP */
2565       if (ct->interleaved.min == -1 || ct->interleaved.max == -1) {
2566         gst_rtsp_session_media_alloc_channels (ctx->sessmedia,
2567             &ct->interleaved);
2568       }
2569       /* alloc new channels if they are already taken */
2570       while (g_hash_table_contains (priv->transports,
2571               GINT_TO_POINTER (ct->interleaved.min))
2572           || g_hash_table_contains (priv->transports,
2573               GINT_TO_POINTER (ct->interleaved.max))) {
2574         gst_rtsp_session_media_alloc_channels (ctx->sessmedia,
2575             &ct->interleaved);
2576         if (ct->interleaved.max > 255)
2577           goto error_allocating_channels;
2578       }
2579     }
2580   }
2581   return TRUE;
2582
2583   /* ERRORS */
2584 error_ttl:
2585   {
2586     GST_ERROR_OBJECT (client,
2587         "Failed to allocate UDP ports: invalid ttl value");
2588     return FALSE;
2589   }
2590 error_allocating_ports:
2591   {
2592     GST_ERROR_OBJECT (client, "Failed to allocate UDP ports");
2593     return FALSE;
2594   }
2595 no_address:
2596   {
2597     GST_ERROR_OBJECT (client, "Failed to acquire address for stream");
2598     return FALSE;
2599   }
2600 no_socket:
2601   {
2602     GST_ERROR_OBJECT (client, "Failed to get UDP socket");
2603     return FALSE;
2604   }
2605 error_mcast_transport:
2606   {
2607     GST_ERROR_OBJECT (client, "Failed to add multicast client transport");
2608     return FALSE;
2609   }
2610 error_allocating_channels:
2611   {
2612     GST_ERROR_OBJECT (client, "Failed to allocate interleaved channels");
2613     return FALSE;
2614   }
2615 }
2616
2617 static GstRTSPTransport *
2618 make_server_transport (GstRTSPClient * client, GstRTSPMedia * media,
2619     GstRTSPContext * ctx, GstRTSPTransport * ct)
2620 {
2621   GstRTSPTransport *st;
2622   GInetAddress *addr;
2623   GSocketFamily family;
2624
2625   /* prepare the server transport */
2626   gst_rtsp_transport_new (&st);
2627
2628   st->trans = ct->trans;
2629   st->profile = ct->profile;
2630   st->lower_transport = ct->lower_transport;
2631   st->mode_play = ct->mode_play;
2632   st->mode_record = ct->mode_record;
2633
2634   addr = g_inet_address_new_from_string (ct->destination);
2635
2636   if (!addr) {
2637     GST_ERROR ("failed to get inet addr from client destination");
2638     family = G_SOCKET_FAMILY_IPV4;
2639   } else {
2640     family = g_inet_address_get_family (addr);
2641     g_object_unref (addr);
2642     addr = NULL;
2643   }
2644
2645   switch (st->lower_transport) {
2646     case GST_RTSP_LOWER_TRANS_UDP:
2647       st->client_port = ct->client_port;
2648       gst_rtsp_stream_get_server_port (ctx->stream, &st->server_port, family);
2649       break;
2650     case GST_RTSP_LOWER_TRANS_UDP_MCAST:
2651       st->port = ct->port;
2652       st->destination = g_strdup (ct->destination);
2653       st->ttl = ct->ttl;
2654       break;
2655     case GST_RTSP_LOWER_TRANS_TCP:
2656       st->interleaved = ct->interleaved;
2657       st->client_port = ct->client_port;
2658       st->server_port = ct->server_port;
2659     default:
2660       break;
2661   }
2662
2663   if ((gst_rtsp_media_get_transport_mode (media) &
2664           GST_RTSP_TRANSPORT_MODE_PLAY))
2665     gst_rtsp_stream_get_ssrc (ctx->stream, &st->ssrc);
2666
2667   return st;
2668 }
2669
2670 static void
2671 rtsp_ctrl_timeout_remove_unlocked (GstRTSPClientPrivate * priv)
2672 {
2673   if (priv->rtsp_ctrl_timeout != NULL) {
2674     GST_DEBUG ("rtsp control session removed timeout %p.",
2675         priv->rtsp_ctrl_timeout);
2676     g_source_destroy (priv->rtsp_ctrl_timeout);
2677     g_source_unref (priv->rtsp_ctrl_timeout);
2678     priv->rtsp_ctrl_timeout = NULL;
2679     priv->rtsp_ctrl_timeout_cnt = 0;
2680   }
2681 }
2682
2683 static void
2684 rtsp_ctrl_timeout_remove (GstRTSPClient * client)
2685 {
2686   g_mutex_lock (&client->priv->lock);
2687   rtsp_ctrl_timeout_remove_unlocked (client->priv);
2688   g_mutex_unlock (&client->priv->lock);
2689 }
2690
2691 static void
2692 rtsp_ctrl_timeout_destroy_notify (gpointer user_data)
2693 {
2694   GWeakRef *client_weak_ref = (GWeakRef *) user_data;
2695
2696   g_weak_ref_clear (client_weak_ref);
2697   g_free (client_weak_ref);
2698 }
2699
2700 static gboolean
2701 rtsp_ctrl_timeout_cb (gpointer user_data)
2702 {
2703   gboolean res = G_SOURCE_CONTINUE;
2704   GstRTSPClientPrivate *priv;
2705   GWeakRef *client_weak_ref = (GWeakRef *) user_data;
2706   GstRTSPClient *client = (GstRTSPClient *) g_weak_ref_get (client_weak_ref);
2707
2708   if (client == NULL) {
2709     return G_SOURCE_REMOVE;
2710   }
2711
2712   priv = client->priv;
2713   g_mutex_lock (&priv->lock);
2714   priv->rtsp_ctrl_timeout_cnt += RTSP_CTRL_CB_INTERVAL;
2715
2716   if ((priv->rtsp_ctrl_timeout_cnt > RTSP_CTRL_TIMEOUT_VALUE)
2717       || (priv->had_session
2718           && priv->rtsp_ctrl_timeout_cnt > priv->post_session_timeout)) {
2719     GST_DEBUG ("rtsp control session timeout %p expired, closing client.",
2720         priv->rtsp_ctrl_timeout);
2721     rtsp_ctrl_timeout_remove_unlocked (client->priv);
2722
2723     res = G_SOURCE_REMOVE;
2724   }
2725
2726   g_mutex_unlock (&priv->lock);
2727
2728   if (res == G_SOURCE_REMOVE) {
2729     gst_rtsp_client_close (client);
2730   }
2731
2732   g_object_unref (client);
2733
2734   return res;
2735 }
2736
2737 static gchar *
2738 stream_make_keymgmt (GstRTSPClient * client, const gchar * location,
2739     GstRTSPStream * stream)
2740 {
2741   gchar *base64, *result = NULL;
2742   GstMIKEYMessage *mikey_msg;
2743   GstCaps *srtcpparams;
2744   GstElement *rtcp_encoder;
2745   gint srtcp_cipher, srtp_cipher;
2746   gint srtcp_auth, srtp_auth;
2747   GstBuffer *key;
2748   GType ciphertype, authtype;
2749   GEnumClass *cipher_enum, *auth_enum;
2750   GEnumValue *srtcp_cipher_value, *srtp_cipher_value, *srtcp_auth_value,
2751       *srtp_auth_value;
2752
2753   rtcp_encoder = gst_rtsp_stream_get_srtp_encoder (stream);
2754
2755   if (!rtcp_encoder)
2756     goto done;
2757
2758   ciphertype = g_type_from_name ("GstSrtpCipherType");
2759   authtype = g_type_from_name ("GstSrtpAuthType");
2760
2761   cipher_enum = g_type_class_ref (ciphertype);
2762   auth_enum = g_type_class_ref (authtype);
2763
2764   /* We need to bring the encoder to READY so that it generates its key */
2765   gst_element_set_state (rtcp_encoder, GST_STATE_READY);
2766
2767   g_object_get (rtcp_encoder, "rtcp-cipher", &srtcp_cipher, "rtcp-auth",
2768       &srtcp_auth, "rtp-cipher", &srtp_cipher, "rtp-auth", &srtp_auth, "key",
2769       &key, NULL);
2770   g_object_unref (rtcp_encoder);
2771
2772   srtcp_cipher_value = g_enum_get_value (cipher_enum, srtcp_cipher);
2773   srtp_cipher_value = g_enum_get_value (cipher_enum, srtp_cipher);
2774   srtcp_auth_value = g_enum_get_value (auth_enum, srtcp_auth);
2775   srtp_auth_value = g_enum_get_value (auth_enum, srtp_auth);
2776
2777   g_type_class_unref (cipher_enum);
2778   g_type_class_unref (auth_enum);
2779
2780   srtcpparams = gst_caps_new_simple ("application/x-srtcp",
2781       "srtcp-cipher", G_TYPE_STRING, srtcp_cipher_value->value_nick,
2782       "srtcp-auth", G_TYPE_STRING, srtcp_auth_value->value_nick,
2783       "srtp-cipher", G_TYPE_STRING, srtp_cipher_value->value_nick,
2784       "srtp-auth", G_TYPE_STRING, srtp_auth_value->value_nick,
2785       "srtp-key", GST_TYPE_BUFFER, key, NULL);
2786
2787   mikey_msg = gst_mikey_message_new_from_caps (srtcpparams);
2788   if (mikey_msg) {
2789     guint send_ssrc;
2790
2791     gst_rtsp_stream_get_ssrc (stream, &send_ssrc);
2792     gst_mikey_message_add_cs_srtp (mikey_msg, 0, send_ssrc, 0);
2793
2794     base64 = gst_mikey_message_base64_encode (mikey_msg);
2795     gst_mikey_message_unref (mikey_msg);
2796
2797     if (base64) {
2798       result = gst_sdp_make_keymgmt (location, base64);
2799       g_free (base64);
2800     }
2801   }
2802
2803 done:
2804   return result;
2805 }
2806
2807 static gboolean
2808 handle_setup_request (GstRTSPClient * client, GstRTSPContext * ctx)
2809 {
2810   GstRTSPClientPrivate *priv = client->priv;
2811   GstRTSPResult res;
2812   GstRTSPUrl *uri;
2813   gchar *transport, *keymgmt;
2814   GstRTSPTransport *ct, *st;
2815   GstRTSPStatusCode code;
2816   GstRTSPSession *session;
2817   GstRTSPStreamTransport *trans;
2818   gchar *trans_str;
2819   GstRTSPSessionMedia *sessmedia;
2820   GstRTSPMedia *media;
2821   GstRTSPStream *stream;
2822   GstRTSPState rtspstate;
2823   GstRTSPClientClass *klass;
2824   gchar *path, *control = NULL;
2825   gint matched;
2826   gboolean new_session = FALSE;
2827   GstRTSPStatusCode sig_result;
2828   gchar *pipelined_request_id = NULL, *accept_range = NULL;
2829
2830   if (!ctx->uri)
2831     goto no_uri;
2832
2833   uri = ctx->uri;
2834   klass = GST_RTSP_CLIENT_GET_CLASS (client);
2835   path = klass->make_path_from_uri (client, uri);
2836
2837   /* parse the transport */
2838   res =
2839       gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_TRANSPORT,
2840       &transport, 0);
2841   if (res != GST_RTSP_OK)
2842     goto no_transport;
2843
2844   /* Handle Pipelined-requests if using >= 2.0 */
2845   if (ctx->request->type_data.request.version >= GST_RTSP_VERSION_2_0)
2846     gst_rtsp_message_get_header (ctx->request,
2847         GST_RTSP_HDR_PIPELINED_REQUESTS, &pipelined_request_id, 0);
2848
2849   /* we create the session after parsing stuff so that we don't make
2850    * a session for malformed requests */
2851   if (priv->session_pool == NULL)
2852     goto no_pool;
2853
2854   session = ctx->session;
2855
2856   if (session) {
2857     g_object_ref (session);
2858     /* get a handle to the configuration of the media in the session, this can
2859      * return NULL if this is a new url to manage in this session. */
2860     sessmedia = gst_rtsp_session_get_media (session, path, &matched);
2861   } else {
2862     /* we need a new media configuration in this session */
2863     sessmedia = NULL;
2864   }
2865
2866   /* we have no session media, find one and manage it */
2867   if (sessmedia == NULL) {
2868     /* get a handle to the configuration of the media in the session */
2869     media = find_media (client, ctx, path, &matched);
2870     /* need to suspend the media, if the protocol has changed */
2871     if (media != NULL) {
2872       gst_rtsp_media_lock (media);
2873       gst_rtsp_media_suspend (media);
2874     }
2875   } else {
2876     if ((media = gst_rtsp_session_media_get_media (sessmedia))) {
2877       g_object_ref (media);
2878       gst_rtsp_media_lock (media);
2879     } else {
2880       goto media_not_found;
2881     }
2882   }
2883   /* no media, not found then */
2884   if (media == NULL)
2885     goto media_not_found_no_reply;
2886
2887   if (path[matched] == '\0') {
2888     if (gst_rtsp_media_n_streams (media) == 1) {
2889       stream = gst_rtsp_media_get_stream (media, 0);
2890     } else {
2891       goto control_not_found;
2892     }
2893   } else {
2894     /* path is what matched. */
2895     gchar *newpath = g_strndup (path, matched);
2896     /* control is remainder */
2897     if (matched == 1 && path[0] == '/')
2898       control = g_strdup (&path[1]);
2899     else
2900       control = g_strdup (&path[matched + 1]);
2901
2902     g_free (path);
2903     path = newpath;
2904
2905     /* find the stream now using the control part */
2906     stream = gst_rtsp_media_find_stream (media, control);
2907   }
2908
2909   if (stream == NULL)
2910     goto stream_not_found;
2911
2912   /* now we have a uri identifying a valid media and stream */
2913   ctx->stream = stream;
2914   ctx->media = media;
2915
2916   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_SETUP_REQUEST], 0,
2917       ctx, &sig_result);
2918   if (sig_result != GST_RTSP_STS_OK) {
2919     goto sig_failed;
2920   }
2921
2922   if (session == NULL) {
2923     /* create a session if this fails we probably reached our session limit or
2924      * something. */
2925     if (!(session = gst_rtsp_session_pool_create (priv->session_pool)))
2926       goto service_unavailable;
2927
2928     /* Pipelined requests should be cleared between sessions */
2929     g_hash_table_remove_all (priv->pipelined_requests);
2930
2931     /* make sure this client is closed when the session is closed */
2932     client_watch_session (client, session);
2933
2934     new_session = TRUE;
2935     /* signal new session */
2936     g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_NEW_SESSION], 0,
2937         session);
2938
2939     ctx->session = session;
2940   }
2941
2942   if (pipelined_request_id) {
2943     g_hash_table_insert (client->priv->pipelined_requests,
2944         g_strdup (pipelined_request_id),
2945         g_strdup (gst_rtsp_session_get_sessionid (session)));
2946   }
2947   /* Remember that we had at least one session in the past */
2948   priv->had_session = TRUE;
2949   rtsp_ctrl_timeout_remove (client);
2950
2951   if (!klass->configure_client_media (client, media, stream, ctx))
2952     goto configure_media_failed_no_reply;
2953
2954   gst_rtsp_transport_new (&ct);
2955
2956   /* parse and find a usable supported transport */
2957   if (!parse_transport (transport, stream, ct))
2958     goto unsupported_transports;
2959
2960   if ((ct->mode_play
2961           && !(gst_rtsp_media_get_transport_mode (media) &
2962               GST_RTSP_TRANSPORT_MODE_PLAY)) || (ct->mode_record
2963           && !(gst_rtsp_media_get_transport_mode (media) &
2964               GST_RTSP_TRANSPORT_MODE_RECORD)))
2965     goto unsupported_mode;
2966
2967   /* parse the keymgmt */
2968   if (gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_KEYMGMT,
2969           &keymgmt, 0) == GST_RTSP_OK) {
2970     if (!gst_rtsp_stream_handle_keymgmt (ctx->stream, keymgmt))
2971       goto keymgmt_error;
2972   }
2973
2974   if (gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_ACCEPT_RANGES,
2975           &accept_range, 0) == GST_RTSP_OK) {
2976     GEnumValue *runit = NULL;
2977     gint i;
2978     gchar **valid_ranges;
2979     GEnumClass *runit_class = g_type_class_ref (GST_TYPE_RTSP_RANGE_UNIT);
2980
2981     gst_rtsp_message_dump (ctx->request);
2982     valid_ranges = g_strsplit (accept_range, ",", -1);
2983
2984     for (i = 0; valid_ranges[i]; i++) {
2985       gchar *range = valid_ranges[i];
2986
2987       while (*range == ' ')
2988         range++;
2989
2990       runit = g_enum_get_value_by_nick (runit_class, range);
2991       if (runit)
2992         break;
2993     }
2994     g_strfreev (valid_ranges);
2995     g_type_class_unref (runit_class);
2996
2997     if (!runit)
2998       goto unsupported_range_unit;
2999   }
3000
3001   if (sessmedia == NULL) {
3002     /* manage the media in our session now, if not done already  */
3003     sessmedia =
3004         gst_rtsp_session_manage_media (session, path, g_object_ref (media));
3005     /* if we stil have no media, error */
3006     if (sessmedia == NULL)
3007       goto sessmedia_unavailable;
3008
3009     /* don't cache media anymore */
3010     clean_cached_media (client, FALSE);
3011   }
3012
3013   ctx->sessmedia = sessmedia;
3014
3015   /* update the client transport */
3016   if (!klass->configure_client_transport (client, ctx, ct))
3017     goto unsupported_client_transport;
3018
3019   /* set in the session media transport */
3020   trans = gst_rtsp_session_media_set_transport (sessmedia, stream, ct);
3021
3022   ctx->trans = trans;
3023
3024   /* configure the url used to set this transport, this we will use when
3025    * generating the response for the PLAY request */
3026   gst_rtsp_stream_transport_set_url (trans, uri);
3027   /* configure keepalive for this transport */
3028   gst_rtsp_stream_transport_set_keepalive (trans,
3029       (GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
3030
3031   if (ct->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
3032     /* our callbacks to send data on this TCP connection */
3033     gst_rtsp_stream_transport_set_callbacks (trans,
3034         (GstRTSPSendFunc) do_send_data,
3035         (GstRTSPSendFunc) do_send_data, client, NULL);
3036     gst_rtsp_stream_transport_set_list_callbacks (trans,
3037         (GstRTSPSendListFunc) do_send_data_list,
3038         (GstRTSPSendListFunc) do_send_data_list, client, NULL);
3039
3040     gst_rtsp_stream_transport_set_back_pressure_callback (trans,
3041         (GstRTSPBackPressureFunc) do_check_back_pressure, client, NULL);
3042
3043     g_hash_table_insert (priv->transports,
3044         GINT_TO_POINTER (ct->interleaved.min), trans);
3045     g_object_ref (trans);
3046     g_hash_table_insert (priv->transports,
3047         GINT_TO_POINTER (ct->interleaved.max), trans);
3048     g_object_ref (trans);
3049     add_data_seq (client, ct->interleaved.min);
3050     add_data_seq (client, ct->interleaved.max);
3051   }
3052
3053   /* create and serialize the server transport */
3054   st = make_server_transport (client, media, ctx, ct);
3055   trans_str = gst_rtsp_transport_as_text (st);
3056
3057   /* FIXME-WFD : Temporarily force to set profile string */
3058   trans_str = g_strjoinv ("RTP/AVP/UDP", g_strsplit (trans_str, "RTP/AVP", -1));
3059
3060   gst_rtsp_transport_free (st);
3061
3062   /* construct the response now */
3063   code = GST_RTSP_STS_OK;
3064   gst_rtsp_message_init_response (ctx->response, code,
3065       gst_rtsp_status_as_text (code), ctx->request);
3066
3067   gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_TRANSPORT,
3068       trans_str);
3069   g_free (trans_str);
3070
3071   if (pipelined_request_id)
3072     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PIPELINED_REQUESTS,
3073         pipelined_request_id);
3074
3075   if (ctx->request->type_data.request.version >= GST_RTSP_VERSION_2_0) {
3076     GstClockTimeDiff seekable = gst_rtsp_media_seekable (media);
3077     GString *media_properties = g_string_new (NULL);
3078
3079     if (seekable == -1)
3080       g_string_append (media_properties,
3081           "No-Seeking,Time-Progressing,Time-Duration=0.0");
3082     else if (seekable == 0)
3083       g_string_append (media_properties, "Beginning-Only");
3084     else if (seekable == G_MAXINT64)
3085       g_string_append (media_properties, "Random-Access");
3086     else
3087       g_string_append_printf (media_properties,
3088           "Random-Access=%f, Unlimited, Immutable",
3089           (gdouble) seekable / GST_SECOND);
3090
3091     gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_MEDIA_PROPERTIES,
3092         media_properties->str);
3093     g_string_free (media_properties, TRUE);
3094     /* TODO Check how Accept-Ranges should be filled */
3095     gst_rtsp_message_add_header (ctx->request, GST_RTSP_HDR_ACCEPT_RANGES,
3096         "npt, clock, smpte, clock");
3097   }
3098
3099   send_message (client, ctx, ctx->response, FALSE);
3100
3101   /* update the state */
3102   rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
3103   switch (rtspstate) {
3104     case GST_RTSP_STATE_PLAYING:
3105     case GST_RTSP_STATE_RECORDING:
3106     case GST_RTSP_STATE_READY:
3107       /* no state change */
3108       break;
3109     default:
3110       gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_READY);
3111       break;
3112   }
3113
3114   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_SETUP_REQUEST], 0, ctx);
3115
3116   gst_rtsp_media_unlock (media);
3117   g_object_unref (media);
3118   g_object_unref (session);
3119   g_free (path);
3120   g_free (control);
3121
3122   return TRUE;
3123
3124   /* ERRORS */
3125 no_uri:
3126   {
3127     GST_ERROR ("client %p: no uri", client);
3128     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3129     return FALSE;
3130   }
3131 no_transport:
3132   {
3133     GST_ERROR ("client %p: no transport", client);
3134     send_generic_error_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT,
3135         ctx);
3136     goto cleanup_path;
3137   }
3138 no_pool:
3139   {
3140     GST_ERROR ("client %p: no session pool configured", client);
3141     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
3142     goto cleanup_path;
3143   }
3144 media_not_found_no_reply:
3145   {
3146     GST_ERROR ("client %p: media '%s' not found", client, path);
3147     /* error reply is already sent */
3148     goto cleanup_session;
3149   }
3150 media_not_found:
3151   {
3152     GST_ERROR ("client %p: media '%s' not found", client, path);
3153     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3154     goto cleanup_session;
3155   }
3156 control_not_found:
3157   {
3158     GST_ERROR ("client %p: no control in path '%s'", client, path);
3159     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3160     gst_rtsp_media_unlock (media);
3161     g_object_unref (media);
3162     goto cleanup_session;
3163   }
3164 stream_not_found:
3165   {
3166     GST_ERROR ("client %p: stream '%s' not found", client,
3167         GST_STR_NULL (control));
3168     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3169     gst_rtsp_media_unlock (media);
3170     g_object_unref (media);
3171     goto cleanup_session;
3172   }
3173 sig_failed:
3174   {
3175     GST_ERROR ("client %p: pre signal returned error: %s", client,
3176         gst_rtsp_status_as_text (sig_result));
3177     send_generic_error_response (client, sig_result, ctx);
3178     gst_rtsp_media_unlock (media);
3179     g_object_unref (media);
3180     goto cleanup_path;
3181   }
3182 service_unavailable:
3183   {
3184     GST_ERROR ("client %p: can't create session", client);
3185     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
3186     gst_rtsp_media_unlock (media);
3187     g_object_unref (media);
3188     goto cleanup_session;
3189   }
3190 sessmedia_unavailable:
3191   {
3192     GST_ERROR ("client %p: can't create session media", client);
3193     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
3194     goto cleanup_transport;
3195   }
3196 configure_media_failed_no_reply:
3197   {
3198     GST_ERROR ("client %p: configure_media failed", client);
3199     gst_rtsp_media_unlock (media);
3200     g_object_unref (media);
3201     /* error reply is already sent */
3202     goto cleanup_session;
3203   }
3204 unsupported_transports:
3205   {
3206     GST_ERROR ("client %p: unsupported transports", client);
3207     send_generic_error_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT,
3208         ctx);
3209     goto cleanup_transport;
3210   }
3211 unsupported_client_transport:
3212   {
3213     GST_ERROR ("client %p: unsupported client transport", client);
3214     send_generic_error_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT,
3215         ctx);
3216     goto cleanup_transport;
3217   }
3218 unsupported_mode:
3219   {
3220     GST_ERROR ("client %p: unsupported mode (media play: %d, media record: %d, "
3221         "mode play: %d, mode record: %d)", client,
3222         ! !(gst_rtsp_media_get_transport_mode (media) &
3223             GST_RTSP_TRANSPORT_MODE_PLAY),
3224         ! !(gst_rtsp_media_get_transport_mode (media) &
3225             GST_RTSP_TRANSPORT_MODE_RECORD), ct->mode_play, ct->mode_record);
3226     send_generic_error_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT,
3227         ctx);
3228     goto cleanup_transport;
3229   }
3230 unsupported_range_unit:
3231   {
3232     GST_ERROR ("Client %p: does not support any range format we support",
3233         client);
3234     send_generic_error_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, ctx);
3235     goto cleanup_transport;
3236   }
3237 keymgmt_error:
3238   {
3239     GST_ERROR ("client %p: keymgmt error", client);
3240     send_generic_error_response (client, GST_RTSP_STS_KEY_MANAGEMENT_FAILURE,
3241         ctx);
3242     goto cleanup_transport;
3243   }
3244   {
3245   cleanup_transport:
3246     gst_rtsp_transport_free (ct);
3247     if (media) {
3248       gst_rtsp_media_unlock (media);
3249       g_object_unref (media);
3250     }
3251   cleanup_session:
3252     if (new_session)
3253       gst_rtsp_session_pool_remove (priv->session_pool, session);
3254     if (session)
3255       g_object_unref (session);
3256   cleanup_path:
3257     g_free (path);
3258     g_free (control);
3259     return FALSE;
3260   }
3261 }
3262
3263 static GstSDPMessage *
3264 create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
3265 {
3266   GstRTSPClientPrivate *priv = client->priv;
3267   GstSDPMessage *sdp;
3268   GstSDPInfo info;
3269   const gchar *proto;
3270   guint64 session_id_tmp;
3271   gchar session_id[21];
3272
3273   gst_sdp_message_new (&sdp);
3274
3275   /* some standard things first */
3276   gst_sdp_message_set_version (sdp, "0");
3277
3278   if (priv->is_ipv6)
3279     proto = "IP6";
3280   else
3281     proto = "IP4";
3282
3283   session_id_tmp = (((guint64) g_random_int ()) << 32) | g_random_int ();
3284   g_snprintf (session_id, sizeof (session_id), "%" G_GUINT64_FORMAT,
3285       session_id_tmp);
3286
3287   gst_sdp_message_set_origin (sdp, "-", session_id, "1", "IN", proto,
3288       priv->server_ip);
3289
3290   gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer");
3291   gst_sdp_message_set_information (sdp, "rtsp-server");
3292   gst_sdp_message_add_time (sdp, "0", "0", NULL);
3293   gst_sdp_message_add_attribute (sdp, "tool", "GStreamer");
3294   gst_sdp_message_add_attribute (sdp, "type", "broadcast");
3295   gst_sdp_message_add_attribute (sdp, "control", "*");
3296
3297   info.is_ipv6 = priv->is_ipv6;
3298   info.server_ip = priv->server_ip;
3299
3300   /* create an SDP for the media object */
3301   if (!gst_rtsp_media_setup_sdp (media, sdp, &info))
3302     goto no_sdp;
3303
3304   return sdp;
3305
3306   /* ERRORS */
3307 no_sdp:
3308   {
3309     GST_ERROR ("client %p: could not create SDP", client);
3310     gst_sdp_message_free (sdp);
3311     return NULL;
3312   }
3313 }
3314
3315 /* for the describe we must generate an SDP */
3316 static gboolean
3317 handle_describe_request (GstRTSPClient * client, GstRTSPContext * ctx)
3318 {
3319   GstRTSPClientPrivate *priv = client->priv;
3320   GstRTSPResult res;
3321   GstSDPMessage *sdp;
3322   guint i;
3323   gchar *path, *str;
3324   GstRTSPMedia *media;
3325   GstRTSPClientClass *klass;
3326   GstRTSPStatusCode sig_result;
3327
3328   klass = GST_RTSP_CLIENT_GET_CLASS (client);
3329
3330   if (!ctx->uri)
3331     goto no_uri;
3332
3333   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_DESCRIBE_REQUEST],
3334       0, ctx, &sig_result);
3335   if (sig_result != GST_RTSP_STS_OK) {
3336     goto sig_failed;
3337   }
3338
3339   /* check what kind of format is accepted, we don't really do anything with it
3340    * and always return SDP for now. */
3341   for (i = 0;; i++) {
3342     gchar *accept;
3343
3344     res =
3345         gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_ACCEPT,
3346         &accept, i);
3347     if (res == GST_RTSP_ENOTIMPL)
3348       break;
3349
3350     if (g_ascii_strcasecmp (accept, "application/sdp") == 0)
3351       break;
3352   }
3353
3354   if (!priv->mount_points)
3355     goto no_mount_points;
3356
3357   if (!(path = gst_rtsp_mount_points_make_path (priv->mount_points, ctx->uri)))
3358     goto no_path;
3359
3360   /* find the media object for the uri */
3361   if (!(media = find_media (client, ctx, path, NULL)))
3362     goto no_media;
3363
3364   gst_rtsp_media_lock (media);
3365
3366   if (!(gst_rtsp_media_get_transport_mode (media) &
3367           GST_RTSP_TRANSPORT_MODE_PLAY))
3368     goto unsupported_mode;
3369
3370   /* create an SDP for the media object on this client */
3371   if (!(sdp = klass->create_sdp (client, media)))
3372     goto no_sdp;
3373
3374   /* we suspend after the describe */
3375   gst_rtsp_media_suspend (media);
3376
3377   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
3378       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
3379
3380   gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_CONTENT_TYPE,
3381       "application/sdp");
3382
3383   /* content base for some clients that might screw up creating the setup uri */
3384   str = make_base_url (client, ctx->uri, path);
3385   g_free (path);
3386
3387   GST_INFO ("adding content-base: %s", str);
3388   gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_CONTENT_BASE, str);
3389
3390   /* add SDP to the response body */
3391   str = gst_sdp_message_as_text (sdp);
3392   gst_rtsp_message_take_body (ctx->response, (guint8 *) str, strlen (str));
3393   gst_sdp_message_free (sdp);
3394
3395   send_message (client, ctx, ctx->response, FALSE);
3396
3397   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_DESCRIBE_REQUEST],
3398       0, ctx);
3399
3400   gst_rtsp_media_unlock (media);
3401   g_object_unref (media);
3402
3403   return TRUE;
3404
3405   /* ERRORS */
3406 sig_failed:
3407   {
3408     GST_ERROR ("client %p: pre signal returned error: %s", client,
3409         gst_rtsp_status_as_text (sig_result));
3410     send_generic_error_response (client, sig_result, ctx);
3411     return FALSE;
3412   }
3413 no_uri:
3414   {
3415     GST_ERROR ("client %p: no uri", client);
3416     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3417     return FALSE;
3418   }
3419 no_mount_points:
3420   {
3421     GST_ERROR ("client %p: no mount points configured", client);
3422     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3423     return FALSE;
3424   }
3425 no_path:
3426   {
3427     GST_ERROR ("client %p: can't find path for url", client);
3428     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3429     return FALSE;
3430   }
3431 no_media:
3432   {
3433     GST_ERROR ("client %p: no media", client);
3434     g_free (path);
3435     /* error reply is already sent */
3436     return FALSE;
3437   }
3438 unsupported_mode:
3439   {
3440     GST_ERROR ("client %p: media does not support DESCRIBE", client);
3441     send_generic_error_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx);
3442     g_free (path);
3443     gst_rtsp_media_unlock (media);
3444     g_object_unref (media);
3445     return FALSE;
3446   }
3447 no_sdp:
3448   {
3449     GST_ERROR ("client %p: can't create SDP", client);
3450     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
3451     g_free (path);
3452     gst_rtsp_media_unlock (media);
3453     g_object_unref (media);
3454     return FALSE;
3455   }
3456 }
3457
3458 static gboolean
3459 handle_sdp (GstRTSPClient * client, GstRTSPContext * ctx, GstRTSPMedia * media,
3460     GstSDPMessage * sdp)
3461 {
3462   GstRTSPClientPrivate *priv = client->priv;
3463   GstRTSPThread *thread;
3464
3465   /* create an SDP for the media object */
3466   if (!gst_rtsp_media_handle_sdp (media, sdp))
3467     goto unhandled_sdp;
3468
3469   thread = gst_rtsp_thread_pool_get_thread (priv->thread_pool,
3470       GST_RTSP_THREAD_TYPE_MEDIA, ctx);
3471   if (thread == NULL)
3472     goto no_thread;
3473
3474   /* prepare the media */
3475   if (!gst_rtsp_media_prepare (media, thread))
3476     goto no_prepare;
3477
3478   return TRUE;
3479
3480   /* ERRORS */
3481 unhandled_sdp:
3482   {
3483     GST_ERROR ("client %p: could not handle SDP", client);
3484     return FALSE;
3485   }
3486 no_thread:
3487   {
3488     GST_ERROR ("client %p: can't create thread", client);
3489     return FALSE;
3490   }
3491 no_prepare:
3492   {
3493     GST_ERROR ("client %p: can't prepare media", client);
3494     return FALSE;
3495   }
3496 }
3497
3498 static gboolean
3499 handle_announce_request (GstRTSPClient * client, GstRTSPContext * ctx)
3500 {
3501   GstRTSPClientPrivate *priv = client->priv;
3502   GstRTSPClientClass *klass;
3503   GstSDPResult sres;
3504   GstSDPMessage *sdp;
3505   GstRTSPMedia *media;
3506   gchar *path, *cont = NULL;
3507   guint8 *data;
3508   guint size;
3509   GstRTSPStatusCode sig_result;
3510   guint i, n_streams;
3511
3512   klass = GST_RTSP_CLIENT_GET_CLASS (client);
3513
3514   if (!ctx->uri)
3515     goto no_uri;
3516
3517   if (!priv->mount_points)
3518     goto no_mount_points;
3519
3520   /* check if reply is SDP */
3521   gst_rtsp_message_get_header (ctx->request, GST_RTSP_HDR_CONTENT_TYPE, &cont,
3522       0);
3523   /* could not be set but since the request returned OK, we assume it
3524    * was SDP, else check it. */
3525   if (cont) {
3526     if (g_ascii_strcasecmp (cont, "application/sdp") != 0)
3527       goto wrong_content_type;
3528   }
3529
3530   /* get message body and parse as SDP */
3531   gst_rtsp_message_get_body (ctx->request, &data, &size);
3532   if (data == NULL || size == 0)
3533     goto no_message;
3534
3535   GST_DEBUG ("client %p: parse SDP...", client);
3536   gst_sdp_message_new (&sdp);
3537   sres = gst_sdp_message_parse_buffer (data, size, sdp);
3538   if (sres != GST_SDP_OK)
3539     goto sdp_parse_failed;
3540
3541   if (!(path = gst_rtsp_mount_points_make_path (priv->mount_points, ctx->uri)))
3542     goto no_path;
3543
3544   /* find the media object for the uri */
3545   if (!(media = find_media (client, ctx, path, NULL)))
3546     goto no_media;
3547
3548   ctx->media = media;
3549   gst_rtsp_media_lock (media);
3550
3551   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_ANNOUNCE_REQUEST],
3552       0, ctx, &sig_result);
3553   if (sig_result != GST_RTSP_STS_OK) {
3554     goto sig_failed;
3555   }
3556
3557   if (!(gst_rtsp_media_get_transport_mode (media) &
3558           GST_RTSP_TRANSPORT_MODE_RECORD))
3559     goto unsupported_mode;
3560
3561   /* Tell client subclass about the media */
3562   if (!klass->handle_sdp (client, ctx, media, sdp))
3563     goto unhandled_sdp;
3564
3565   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
3566       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
3567
3568   n_streams = gst_rtsp_media_n_streams (media);
3569   for (i = 0; i < n_streams; i++) {
3570     GstRTSPStream *stream = gst_rtsp_media_get_stream (media, i);
3571     gchar *uri, *location, *keymgmt;
3572
3573     uri = gst_rtsp_url_get_request_uri (ctx->uri);
3574     location = g_strdup_printf ("%s/stream=%d", uri, i);
3575     keymgmt = stream_make_keymgmt (client, location, stream);
3576
3577     if (keymgmt)
3578       gst_rtsp_message_take_header (ctx->response, GST_RTSP_HDR_KEYMGMT,
3579           keymgmt);
3580
3581     g_free (location);
3582     g_free (uri);
3583   }
3584
3585   /* we suspend after the announce */
3586   gst_rtsp_media_suspend (media);
3587
3588   send_message (client, ctx, ctx->response, FALSE);
3589
3590   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_ANNOUNCE_REQUEST],
3591       0, ctx);
3592
3593   gst_sdp_message_free (sdp);
3594   g_free (path);
3595   gst_rtsp_media_unlock (media);
3596   g_object_unref (media);
3597
3598   return TRUE;
3599
3600 no_uri:
3601   {
3602     GST_ERROR ("client %p: no uri", client);
3603     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3604     return FALSE;
3605   }
3606 no_mount_points:
3607   {
3608     GST_ERROR ("client %p: no mount points configured", client);
3609     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3610     return FALSE;
3611   }
3612 no_path:
3613   {
3614     GST_ERROR ("client %p: can't find path for url", client);
3615     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3616     gst_sdp_message_free (sdp);
3617     return FALSE;
3618   }
3619 wrong_content_type:
3620   {
3621     GST_ERROR ("client %p: unknown content type", client);
3622     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3623     return FALSE;
3624   }
3625 no_message:
3626   {
3627     GST_ERROR ("client %p: can't find SDP message", client);
3628     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3629     return FALSE;
3630   }
3631 sdp_parse_failed:
3632   {
3633     GST_ERROR ("client %p: failed to parse SDP message", client);
3634     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3635     gst_sdp_message_free (sdp);
3636     return FALSE;
3637   }
3638 no_media:
3639   {
3640     GST_ERROR ("client %p: no media", client);
3641     g_free (path);
3642     /* error reply is already sent */
3643     gst_sdp_message_free (sdp);
3644     return FALSE;
3645   }
3646 sig_failed:
3647   {
3648     GST_ERROR ("client %p: pre signal returned error: %s", client,
3649         gst_rtsp_status_as_text (sig_result));
3650     send_generic_error_response (client, sig_result, ctx);
3651     gst_sdp_message_free (sdp);
3652     gst_rtsp_media_unlock (media);
3653     g_object_unref (media);
3654     return FALSE;
3655   }
3656 unsupported_mode:
3657   {
3658     GST_ERROR ("client %p: media does not support ANNOUNCE", client);
3659     send_generic_error_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx);
3660     g_free (path);
3661     gst_rtsp_media_unlock (media);
3662     g_object_unref (media);
3663     gst_sdp_message_free (sdp);
3664     return FALSE;
3665   }
3666 unhandled_sdp:
3667   {
3668     GST_ERROR ("client %p: can't handle SDP", client);
3669     send_generic_error_response (client, GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE,
3670         ctx);
3671     g_free (path);
3672     gst_rtsp_media_unlock (media);
3673     g_object_unref (media);
3674     gst_sdp_message_free (sdp);
3675     return FALSE;
3676   }
3677 }
3678
3679 static gboolean
3680 handle_record_request (GstRTSPClient * client, GstRTSPContext * ctx)
3681 {
3682   GstRTSPSession *session;
3683   GstRTSPClientClass *klass;
3684   GstRTSPSessionMedia *sessmedia;
3685   GstRTSPMedia *media;
3686   GstRTSPUrl *uri;
3687   GstRTSPState rtspstate;
3688   gchar *path;
3689   gint matched;
3690   GstRTSPStatusCode sig_result;
3691   GPtrArray *transports;
3692
3693   if (!(session = ctx->session))
3694     goto no_session;
3695
3696   if (!(uri = ctx->uri))
3697     goto no_uri;
3698
3699   klass = GST_RTSP_CLIENT_GET_CLASS (client);
3700   path = klass->make_path_from_uri (client, uri);
3701
3702   /* get a handle to the configuration of the media in the session */
3703   sessmedia = gst_rtsp_session_get_media (session, path, &matched);
3704   if (!sessmedia)
3705     goto not_found;
3706
3707   if (path[matched] != '\0')
3708     goto no_aggregate;
3709
3710   g_free (path);
3711
3712   ctx->sessmedia = sessmedia;
3713   ctx->media = media = gst_rtsp_session_media_get_media (sessmedia);
3714
3715   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_RECORD_REQUEST], 0,
3716       ctx, &sig_result);
3717   if (sig_result != GST_RTSP_STS_OK) {
3718     goto sig_failed;
3719   }
3720
3721   if (!(gst_rtsp_media_get_transport_mode (media) &
3722           GST_RTSP_TRANSPORT_MODE_RECORD))
3723     goto unsupported_mode;
3724
3725   /* the session state must be playing or ready */
3726   rtspstate = gst_rtsp_session_media_get_rtsp_state (sessmedia);
3727   if (rtspstate != GST_RTSP_STATE_PLAYING && rtspstate != GST_RTSP_STATE_READY)
3728     goto invalid_state;
3729
3730   /* update the pipeline */
3731   transports = gst_rtsp_session_media_get_transports (sessmedia);
3732   if (!gst_rtsp_media_complete_pipeline (media, transports)) {
3733     g_ptr_array_unref (transports);
3734     goto pipeline_error;
3735   }
3736   g_ptr_array_unref (transports);
3737
3738   /* in record we first unsuspend, media could be suspended from SDP or PAUSED */
3739   if (!gst_rtsp_media_unsuspend (media))
3740     goto unsuspend_failed;
3741
3742   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
3743       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
3744
3745   send_message (client, ctx, ctx->response, FALSE);
3746
3747   /* start playing after sending the response */
3748   gst_rtsp_session_media_set_state (sessmedia, GST_STATE_PLAYING);
3749
3750   gst_rtsp_session_media_set_rtsp_state (sessmedia, GST_RTSP_STATE_PLAYING);
3751
3752   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_RECORD_REQUEST], 0,
3753       ctx);
3754
3755   return TRUE;
3756
3757   /* ERRORS */
3758 no_session:
3759   {
3760     GST_ERROR ("client %p: no session", client);
3761     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
3762     return FALSE;
3763   }
3764 no_uri:
3765   {
3766     GST_ERROR ("client %p: no uri supplied", client);
3767     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
3768     return FALSE;
3769   }
3770 not_found:
3771   {
3772     GST_ERROR ("client %p: media not found", client);
3773     send_generic_error_response (client, GST_RTSP_STS_NOT_FOUND, ctx);
3774     return FALSE;
3775   }
3776 no_aggregate:
3777   {
3778     GST_ERROR ("client %p: no aggregate path %s", client, path);
3779     send_generic_error_response (client,
3780         GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, ctx);
3781     g_free (path);
3782     return FALSE;
3783   }
3784 sig_failed:
3785   {
3786     GST_ERROR ("client %p: pre signal returned error: %s", client,
3787         gst_rtsp_status_as_text (sig_result));
3788     send_generic_error_response (client, sig_result, ctx);
3789     return FALSE;
3790   }
3791 unsupported_mode:
3792   {
3793     GST_ERROR ("client %p: media does not support RECORD", client);
3794     send_generic_error_response (client, GST_RTSP_STS_METHOD_NOT_ALLOWED, ctx);
3795     return FALSE;
3796   }
3797 invalid_state:
3798   {
3799     GST_ERROR ("client %p: not PLAYING or READY", client);
3800     send_generic_error_response (client,
3801         GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, ctx);
3802     return FALSE;
3803   }
3804 pipeline_error:
3805   {
3806     GST_ERROR ("client %p: failed to configure the pipeline", client);
3807     send_generic_error_response (client,
3808         GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, ctx);
3809     return FALSE;
3810   }
3811 unsuspend_failed:
3812   {
3813     GST_ERROR ("client %p: unsuspend failed", client);
3814     send_generic_error_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, ctx);
3815     return FALSE;
3816   }
3817 }
3818
3819 static gboolean
3820 default_handle_options_request (GstRTSPClient * client, GstRTSPContext * ctx,
3821     GstRTSPVersion version)
3822 {
3823   GstRTSPMethod options;
3824   gchar *str;
3825   GstRTSPStatusCode sig_result;
3826
3827   options = GST_RTSP_DESCRIBE |
3828       GST_RTSP_OPTIONS |
3829       GST_RTSP_PAUSE |
3830       GST_RTSP_PLAY |
3831       GST_RTSP_SETUP |
3832       GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
3833
3834   if (version < GST_RTSP_VERSION_2_0) {
3835     options |= GST_RTSP_RECORD;
3836     options |= GST_RTSP_ANNOUNCE;
3837   }
3838
3839   str = gst_rtsp_options_as_text (options);
3840
3841   gst_rtsp_message_init_response (ctx->response, GST_RTSP_STS_OK,
3842       gst_rtsp_status_as_text (GST_RTSP_STS_OK), ctx->request);
3843
3844   gst_rtsp_message_add_header (ctx->response, GST_RTSP_HDR_PUBLIC, str);
3845   g_free (str);
3846
3847   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_PRE_OPTIONS_REQUEST], 0,
3848       ctx, &sig_result);
3849   if (sig_result != GST_RTSP_STS_OK) {
3850     goto sig_failed;
3851   }
3852
3853   send_message (client, ctx, ctx->response, FALSE);
3854
3855   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_OPTIONS_REQUEST],
3856       0, ctx);
3857
3858   return TRUE;
3859
3860 /* ERRORS */
3861 sig_failed:
3862   {
3863     GST_ERROR ("client %p: pre signal returned error: %s", client,
3864         gst_rtsp_status_as_text (sig_result));
3865     send_generic_error_response (client, sig_result, ctx);
3866     gst_rtsp_message_free (ctx->response);
3867     return FALSE;
3868   }
3869 }
3870
3871 /* remove duplicate and trailing '/' */
3872 static void
3873 sanitize_uri (GstRTSPUrl * uri)
3874 {
3875   gint i, len;
3876   gchar *s, *d;
3877   gboolean have_slash, prev_slash;
3878
3879   s = d = uri->abspath;
3880   len = strlen (uri->abspath);
3881
3882   prev_slash = FALSE;
3883
3884   for (i = 0; i < len; i++) {
3885     have_slash = s[i] == '/';
3886     *d = s[i];
3887     if (!have_slash || !prev_slash)
3888       d++;
3889     prev_slash = have_slash;
3890   }
3891   len = d - uri->abspath;
3892   /* don't remove the first slash if that's the only thing left */
3893   if (len > 1 && *(d - 1) == '/')
3894     d--;
3895   *d = '\0';
3896 }
3897
3898 /* is called when the session is removed from its session pool. */
3899 static void
3900 client_session_removed (GstRTSPSessionPool * pool, GstRTSPSession * session,
3901     GstRTSPClient * client)
3902 {
3903   GstRTSPClientPrivate *priv = client->priv;
3904   GSource *timer_src;
3905
3906   GST_INFO ("client %p: session %p removed", client, session);
3907
3908   g_mutex_lock (&priv->lock);
3909   client_unwatch_session (client, session, NULL);
3910
3911   if (!priv->sessions && priv->rtsp_ctrl_timeout == NULL) {
3912     if (priv->post_session_timeout > 0) {
3913       GWeakRef *client_weak_ref = g_new (GWeakRef, 1);
3914       timer_src = g_timeout_source_new_seconds (RTSP_CTRL_CB_INTERVAL);
3915
3916       g_weak_ref_init (client_weak_ref, client);
3917       g_source_set_callback (timer_src, rtsp_ctrl_timeout_cb, client_weak_ref,
3918           rtsp_ctrl_timeout_destroy_notify);
3919       priv->rtsp_ctrl_timeout_cnt = 0;
3920       g_source_attach (timer_src, priv->watch_context);
3921       priv->rtsp_ctrl_timeout = timer_src;
3922       GST_DEBUG ("rtsp control setting up connection timeout %p.",
3923           priv->rtsp_ctrl_timeout);
3924       g_mutex_unlock (&priv->lock);
3925     } else if (priv->post_session_timeout == 0) {
3926       g_mutex_unlock (&priv->lock);
3927       gst_rtsp_client_close (client);
3928     } else {
3929       g_mutex_unlock (&priv->lock);
3930     }
3931   } else {
3932     g_mutex_unlock (&priv->lock);
3933   }
3934 }
3935
3936 /* Check for Require headers. Returns TRUE if there are no Require headers,
3937  * otherwise lets the application decide which headers are supported.
3938  * By default all headers are unsupported.
3939  * If there are unsupported options, FALSE will be returned together with
3940  * a newly-allocated string of (comma-separated) unsupported options in
3941  * the unsupported_reqs variable.
3942  *
3943  * There may be multiple Require headers, but we must send one single
3944  * Unsupported header with all the unsupported options as response. If
3945  * an incoming Require header contained a comma-separated list of options
3946  * GstRtspConnection will already have split that list up into multiple
3947  * headers.
3948  */
3949 static gboolean
3950 check_request_requirements (GstRTSPContext * ctx, gchar ** unsupported_reqs)
3951 {
3952   GstRTSPResult res;
3953   GPtrArray *arr = NULL;
3954   GstRTSPMessage *msg = ctx->request;
3955   gchar *reqs = NULL;
3956   gint i;
3957   gchar *sig_result = NULL;
3958   gboolean result = TRUE;
3959
3960   i = 0;
3961   do {
3962     res = gst_rtsp_message_get_header (msg, GST_RTSP_HDR_REQUIRE, &reqs, i++);
3963
3964     if (res == GST_RTSP_ENOTIMPL)
3965       break;
3966
3967     if (arr == NULL)
3968       arr = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
3969
3970     g_ptr_array_add (arr, g_strdup (reqs));
3971   }
3972   while (TRUE);
3973
3974   /* if we don't have any Require headers at all, all is fine */
3975   if (i == 1)
3976     return TRUE;
3977
3978   /* otherwise we've now processed at all the Require headers */
3979   g_ptr_array_add (arr, NULL);
3980
3981   g_signal_emit (ctx->client,
3982       gst_rtsp_client_signals[SIGNAL_CHECK_REQUIREMENTS], 0, ctx,
3983       (gchar **) arr->pdata, &sig_result);
3984
3985   if (sig_result == NULL) {
3986     /* no supported options, just report all of the required ones as
3987      * unsupported */
3988     *unsupported_reqs = g_strjoinv (", ", (gchar **) arr->pdata);
3989     result = FALSE;
3990     goto done;
3991   }
3992
3993   if (strlen (sig_result) == 0)
3994     g_free (sig_result);
3995   else {
3996     *unsupported_reqs = sig_result;
3997     result = FALSE;
3998   }
3999
4000 done:
4001   g_ptr_array_unref (arr);
4002   return result;
4003 }
4004
4005 static void
4006 handle_request (GstRTSPClient * client, GstRTSPMessage * request)
4007 {
4008   GstRTSPClientPrivate *priv = client->priv;
4009   GstRTSPMethod method;
4010   const gchar *uristr;
4011   GstRTSPUrl *uri = NULL;
4012   GstRTSPVersion version;
4013   GstRTSPResult res;
4014   GstRTSPSession *session = NULL;
4015   GstRTSPContext sctx = { NULL }, *ctx;
4016   GstRTSPMessage response = { 0 };
4017   gchar *unsupported_reqs = NULL;
4018   gchar *sessid = NULL, *pipelined_request_id = NULL;
4019   GstRTSPClientClass *klass;
4020
4021   klass = GST_RTSP_CLIENT_GET_CLASS (client);
4022   if (!(ctx = gst_rtsp_context_get_current ())) {
4023     ctx = &sctx;
4024     ctx->auth = priv->auth;
4025     gst_rtsp_context_push_current (ctx);
4026   }
4027
4028   ctx->conn = priv->connection;
4029   ctx->client = client;
4030   ctx->request = request;
4031   ctx->response = &response;
4032
4033   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
4034     gst_rtsp_message_dump (request);
4035   }
4036
4037   gst_rtsp_message_parse_request (request, &method, &uristr, &version);
4038
4039   GST_INFO ("client %p: received a request %s %s %s", client,
4040       gst_rtsp_method_as_text (method), uristr,
4041       gst_rtsp_version_as_text (version));
4042
4043   /* we can only handle 1.0 requests */
4044   if (version != GST_RTSP_VERSION_1_0 && version != GST_RTSP_VERSION_2_0)
4045     goto not_supported;
4046
4047   ctx->method = method;
4048
4049   /* we always try to parse the url first */
4050   if (strcmp (uristr, "*") == 0) {
4051     /* special case where we have * as uri, keep uri = NULL */
4052   } else if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) {
4053     /* check if the uristr is an absolute path <=> scheme and host information
4054      * is missing */
4055     gchar *scheme;
4056
4057     scheme = g_uri_parse_scheme (uristr);
4058     if (scheme == NULL && g_str_has_prefix (uristr, "/")) {
4059       gchar *absolute_uristr = NULL;
4060
4061       GST_WARNING_OBJECT (client, "request doesn't contain absolute url");
4062       if (priv->server_ip == NULL) {
4063         GST_WARNING_OBJECT (client, "host information missing");
4064         goto bad_request;
4065       }
4066
4067       absolute_uristr =
4068           g_strdup_printf ("rtsp://%s%s", priv->server_ip, uristr);
4069
4070       GST_DEBUG_OBJECT (client, "absolute url: %s", absolute_uristr);
4071       if (gst_rtsp_url_parse (absolute_uristr, &uri) != GST_RTSP_OK) {
4072         g_free (absolute_uristr);
4073         goto bad_request;
4074       }
4075       g_free (absolute_uristr);
4076     } else {
4077       g_free (scheme);
4078       goto bad_request;
4079     }
4080   }
4081
4082   /* get the session if there is any */
4083   res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_PIPELINED_REQUESTS,
4084       &pipelined_request_id, 0);
4085   if (res == GST_RTSP_OK) {
4086     sessid = g_hash_table_lookup (client->priv->pipelined_requests,
4087         pipelined_request_id);
4088
4089     if (!sessid)
4090       res = GST_RTSP_ERROR;
4091   }
4092
4093   if (res != GST_RTSP_OK)
4094     res =
4095         gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0);
4096
4097   if (res == GST_RTSP_OK) {
4098     if (priv->session_pool == NULL)
4099       goto no_pool;
4100
4101     /* we had a session in the request, find it again */
4102     if (!(session = gst_rtsp_session_pool_find (priv->session_pool, sessid)))
4103       goto session_not_found;
4104
4105     /* we add the session to the client list of watched sessions. When a session
4106      * disappears because it times out, we will be notified. If all sessions are
4107      * gone, we will close the connection */
4108     client_watch_session (client, session);
4109   }
4110
4111   /* sanitize the uri */
4112   if (uri)
4113     sanitize_uri (uri);
4114   ctx->uri = uri;
4115   ctx->session = session;
4116
4117   if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_URL))
4118     goto not_authorized;
4119
4120   /* handle any 'Require' headers */
4121   if (!check_request_requirements (ctx, &unsupported_reqs))
4122     goto unsupported_requirement;
4123
4124   /* now see what is asked and dispatch to a dedicated handler */
4125   switch (method) {
4126     case GST_RTSP_OPTIONS:
4127       priv->version = version;
4128       klass->handle_options_request (client, ctx, version);
4129       break;
4130     case GST_RTSP_DESCRIBE:
4131       handle_describe_request (client, ctx);
4132       break;
4133     case GST_RTSP_SETUP:
4134       handle_setup_request (client, ctx);
4135       break;
4136     case GST_RTSP_PLAY:
4137       klass->handle_play_request (client, ctx);
4138       break;
4139     case GST_RTSP_PAUSE:
4140       handle_pause_request (client, ctx);
4141       break;
4142     case GST_RTSP_TEARDOWN:
4143       handle_teardown_request (client, ctx);
4144       break;
4145     case GST_RTSP_SET_PARAMETER:
4146       klass->handle_set_param_request (client, ctx);
4147       break;
4148     case GST_RTSP_GET_PARAMETER:
4149       klass->handle_get_param_request (client, ctx);
4150       break;
4151     case GST_RTSP_ANNOUNCE:
4152       if (version >= GST_RTSP_VERSION_2_0)
4153         goto invalid_command_for_version;
4154       handle_announce_request (client, ctx);
4155       break;
4156     case GST_RTSP_RECORD:
4157       if (version >= GST_RTSP_VERSION_2_0)
4158         goto invalid_command_for_version;
4159       handle_record_request (client, ctx);
4160       break;
4161     case GST_RTSP_REDIRECT:
4162       goto not_implemented;
4163     case GST_RTSP_INVALID:
4164     default:
4165       goto bad_request;
4166   }
4167
4168 done:
4169   if (ctx == &sctx)
4170     gst_rtsp_context_pop_current (ctx);
4171   if (session)
4172     g_object_unref (session);
4173   if (uri)
4174     gst_rtsp_url_free (uri);
4175   return;
4176
4177   /* ERRORS */
4178 not_supported:
4179   {
4180     GST_ERROR ("client %p: version %d not supported", client, version);
4181     send_generic_error_response (client,
4182         GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED, ctx);
4183     goto done;
4184   }
4185 invalid_command_for_version:
4186   {
4187     GST_ERROR ("client %p: invalid command for version", client);
4188     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
4189     goto done;
4190   }
4191 bad_request:
4192   {
4193     GST_ERROR ("client %p: bad request", client);
4194     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
4195     goto done;
4196   }
4197 no_pool:
4198   {
4199     GST_ERROR ("client %p: no pool configured", client);
4200     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
4201     goto done;
4202   }
4203 session_not_found:
4204   {
4205     GST_ERROR ("client %p: session not found", client);
4206     send_generic_error_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, ctx);
4207     goto done;
4208   }
4209 not_authorized:
4210   {
4211     GST_ERROR ("client %p: not allowed", client);
4212     /* error reply is already sent */
4213     goto done;
4214   }
4215 unsupported_requirement:
4216   {
4217     GST_ERROR ("client %p: Required option is not supported (%s)", client,
4218         unsupported_reqs);
4219     send_option_not_supported_response (client, ctx, unsupported_reqs);
4220     g_free (unsupported_reqs);
4221     goto done;
4222   }
4223 not_implemented:
4224   {
4225     GST_ERROR ("client %p: method %d not implemented", client, method);
4226     send_generic_error_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, ctx);
4227     goto done;
4228   }
4229 }
4230
4231
4232 static void
4233 handle_response (GstRTSPClient * client, GstRTSPMessage * response)
4234 {
4235   GstRTSPClientPrivate *priv = client->priv;
4236   GstRTSPResult res;
4237   GstRTSPSession *session = NULL;
4238   GstRTSPContext sctx = { NULL }, *ctx;
4239   gchar *sessid;
4240
4241   if (!(ctx = gst_rtsp_context_get_current ())) {
4242     ctx = &sctx;
4243     ctx->auth = priv->auth;
4244     gst_rtsp_context_push_current (ctx);
4245   }
4246
4247   ctx->conn = priv->connection;
4248   ctx->client = client;
4249   ctx->request = NULL;
4250   ctx->uri = NULL;
4251   ctx->method = GST_RTSP_INVALID;
4252   ctx->response = response;
4253
4254   if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
4255     gst_rtsp_message_dump (response);
4256   }
4257
4258   GST_INFO ("client %p: received a response", client);
4259
4260   /* get the session if there is any */
4261   res =
4262       gst_rtsp_message_get_header (response, GST_RTSP_HDR_SESSION, &sessid, 0);
4263   if (res == GST_RTSP_OK) {
4264     if (priv->session_pool == NULL)
4265       goto no_pool;
4266
4267     /* we had a session in the request, find it again */
4268     if (!(session = gst_rtsp_session_pool_find (priv->session_pool, sessid)))
4269       goto session_not_found;
4270
4271     /* we add the session to the client list of watched sessions. When a session
4272      * disappears because it times out, we will be notified. If all sessions are
4273      * gone, we will close the connection */
4274     client_watch_session (client, session);
4275   }
4276
4277   ctx->session = session;
4278
4279   g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_HANDLE_RESPONSE],
4280       0, ctx);
4281
4282 done:
4283   if (ctx == &sctx)
4284     gst_rtsp_context_pop_current (ctx);
4285   if (session)
4286     g_object_unref (session);
4287   return;
4288
4289 no_pool:
4290   {
4291     GST_ERROR ("client %p: no pool configured", client);
4292     goto done;
4293   }
4294 session_not_found:
4295   {
4296     GST_ERROR ("client %p: session not found", client);
4297     goto done;
4298   }
4299 }
4300
4301 static void
4302 handle_data (GstRTSPClient * client, GstRTSPMessage * message)
4303 {
4304   GstRTSPClientPrivate *priv = client->priv;
4305   GstRTSPResult res;
4306   guint8 channel;
4307   guint8 *data;
4308   guint size;
4309   GstBuffer *buffer;
4310   GstRTSPStreamTransport *trans;
4311
4312   /* find the stream for this message */
4313   res = gst_rtsp_message_parse_data (message, &channel);
4314   if (res != GST_RTSP_OK)
4315     return;
4316
4317   gst_rtsp_message_get_body (message, &data, &size);
4318   if (size < 2)
4319     goto invalid_length;
4320
4321   gst_rtsp_message_steal_body (message, &data, &size);
4322
4323   /* Strip trailing \0 (which GstRTSPConnection adds) */
4324   --size;
4325
4326   buffer = gst_buffer_new_wrapped (data, size);
4327
4328   trans =
4329       g_hash_table_lookup (priv->transports, GINT_TO_POINTER ((gint) channel));
4330   if (trans) {
4331     GSocketAddress *addr;
4332
4333     /* Only create the socket address once for the transport, we don't really
4334      * want to do that for every single packet.
4335      *
4336      * The netaddress meta is later used by the RTP stack to know where
4337      * packets came from and allows us to match it again to a stream transport
4338      *
4339      * In theory we could use the remote socket address of the RTSP connection
4340      * here, but this would fail with a custom configure_client_transport()
4341      * implementation.
4342      */
4343     if (!(addr =
4344             g_object_get_data (G_OBJECT (trans), "rtsp-client.remote-addr"))) {
4345       const GstRTSPTransport *tr;
4346       GInetAddress *iaddr;
4347
4348       tr = gst_rtsp_stream_transport_get_transport (trans);
4349       iaddr = g_inet_address_new_from_string (tr->destination);
4350       if (iaddr) {
4351         addr = g_inet_socket_address_new (iaddr, tr->client_port.min);
4352         g_object_unref (iaddr);
4353         g_object_set_data_full (G_OBJECT (trans), "rtsp-client.remote-addr",
4354             addr, (GDestroyNotify) g_object_unref);
4355       }
4356     }
4357
4358     if (addr) {
4359       gst_buffer_add_net_address_meta (buffer, addr);
4360     }
4361
4362     /* dispatch to the stream based on the channel number */
4363     GST_LOG_OBJECT (client, "%u bytes of data on channel %u", size, channel);
4364     gst_rtsp_stream_transport_recv_data (trans, channel, buffer);
4365   } else {
4366     GST_DEBUG_OBJECT (client, "received %u bytes of data for "
4367         "unknown channel %u", size, channel);
4368     gst_buffer_unref (buffer);
4369   }
4370
4371   return;
4372
4373 /* ERRORS */
4374 invalid_length:
4375   {
4376     GST_DEBUG ("client %p: Short message received, ignoring", client);
4377     return;
4378   }
4379 }
4380
4381 /**
4382  * gst_rtsp_client_set_session_pool:
4383  * @client: a #GstRTSPClient
4384  * @pool: (transfer none) (nullable): a #GstRTSPSessionPool
4385  *
4386  * Set @pool as the sessionpool for @client which it will use to find
4387  * or allocate sessions. the sessionpool is usually inherited from the server
4388  * that created the client but can be overridden later.
4389  */
4390 void
4391 gst_rtsp_client_set_session_pool (GstRTSPClient * client,
4392     GstRTSPSessionPool * pool)
4393 {
4394   GstRTSPSessionPool *old;
4395   GstRTSPClientPrivate *priv;
4396
4397   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4398
4399   priv = client->priv;
4400
4401   if (pool)
4402     g_object_ref (pool);
4403
4404   g_mutex_lock (&priv->lock);
4405   old = priv->session_pool;
4406   priv->session_pool = pool;
4407
4408   if (priv->session_removed_id) {
4409     g_signal_handler_disconnect (old, priv->session_removed_id);
4410     priv->session_removed_id = 0;
4411   }
4412   g_mutex_unlock (&priv->lock);
4413
4414   /* FIXME, should remove all sessions from the old pool for this client */
4415   if (old)
4416     g_object_unref (old);
4417 }
4418
4419 /**
4420  * gst_rtsp_client_get_session_pool:
4421  * @client: a #GstRTSPClient
4422  *
4423  * Get the #GstRTSPSessionPool object that @client uses to manage its sessions.
4424  *
4425  * Returns: (transfer full) (nullable): a #GstRTSPSessionPool, unref after usage.
4426  */
4427 GstRTSPSessionPool *
4428 gst_rtsp_client_get_session_pool (GstRTSPClient * client)
4429 {
4430   GstRTSPClientPrivate *priv;
4431   GstRTSPSessionPool *result;
4432
4433   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
4434
4435   priv = client->priv;
4436
4437   g_mutex_lock (&priv->lock);
4438   if ((result = priv->session_pool))
4439     g_object_ref (result);
4440   g_mutex_unlock (&priv->lock);
4441
4442   return result;
4443 }
4444
4445 /**
4446  * gst_rtsp_client_set_mount_points:
4447  * @client: a #GstRTSPClient
4448  * @mounts: (transfer none) (nullable): a #GstRTSPMountPoints
4449  *
4450  * Set @mounts as the mount points for @client which it will use to map urls
4451  * to media streams. These mount points are usually inherited from the server that
4452  * created the client but can be overriden later.
4453  */
4454 void
4455 gst_rtsp_client_set_mount_points (GstRTSPClient * client,
4456     GstRTSPMountPoints * mounts)
4457 {
4458   GstRTSPClientPrivate *priv;
4459   GstRTSPMountPoints *old;
4460
4461   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4462
4463   priv = client->priv;
4464
4465   if (mounts)
4466     g_object_ref (mounts);
4467
4468   g_mutex_lock (&priv->lock);
4469   old = priv->mount_points;
4470   priv->mount_points = mounts;
4471   g_mutex_unlock (&priv->lock);
4472
4473   if (old)
4474     g_object_unref (old);
4475 }
4476
4477 /**
4478  * gst_rtsp_client_get_mount_points:
4479  * @client: a #GstRTSPClient
4480  *
4481  * Get the #GstRTSPMountPoints object that @client uses to manage its sessions.
4482  *
4483  * Returns: (transfer full) (nullable): a #GstRTSPMountPoints, unref after usage.
4484  */
4485 GstRTSPMountPoints *
4486 gst_rtsp_client_get_mount_points (GstRTSPClient * client)
4487 {
4488   GstRTSPClientPrivate *priv;
4489   GstRTSPMountPoints *result;
4490
4491   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
4492
4493   priv = client->priv;
4494
4495   g_mutex_lock (&priv->lock);
4496   if ((result = priv->mount_points))
4497     g_object_ref (result);
4498   g_mutex_unlock (&priv->lock);
4499
4500   return result;
4501 }
4502
4503 /**
4504  * gst_rtsp_client_set_content_length_limit:
4505  * @client: a #GstRTSPClient
4506  * @limit: Content-Length limit
4507  *
4508  * Configure @client to use the specified Content-Length limit.
4509  *
4510  * Define an appropriate request size limit and reject requests exceeding the
4511  * limit with response status 413 Request Entity Too Large
4512  *
4513  * Since: 1.18
4514  */
4515 void
4516 gst_rtsp_client_set_content_length_limit (GstRTSPClient * client, guint limit)
4517 {
4518   GstRTSPClientPrivate *priv;
4519
4520   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4521
4522   priv = client->priv;
4523   g_mutex_lock (&priv->lock);
4524   priv->content_length_limit = limit;
4525   g_mutex_unlock (&priv->lock);
4526 }
4527
4528 /**
4529  * gst_rtsp_client_get_content_length_limit:
4530  * @client: a #GstRTSPClient
4531  *
4532  * Get the Content-Length limit of @client.
4533  *
4534  * Returns: the Content-Length limit.
4535  *
4536  * Since: 1.18
4537  */
4538 guint
4539 gst_rtsp_client_get_content_length_limit (GstRTSPClient * client)
4540 {
4541   GstRTSPClientPrivate *priv;
4542   glong content_length_limit;
4543
4544   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), -1);
4545   priv = client->priv;
4546
4547   g_mutex_lock (&priv->lock);
4548   content_length_limit = priv->content_length_limit;
4549   g_mutex_unlock (&priv->lock);
4550
4551   return content_length_limit;
4552 }
4553
4554 /**
4555  * gst_rtsp_client_set_auth:
4556  * @client: a #GstRTSPClient
4557  * @auth: (transfer none) (nullable): a #GstRTSPAuth
4558  *
4559  * configure @auth to be used as the authentication manager of @client.
4560  */
4561 void
4562 gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
4563 {
4564   GstRTSPClientPrivate *priv;
4565   GstRTSPAuth *old;
4566
4567   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4568
4569   priv = client->priv;
4570
4571   if (auth)
4572     g_object_ref (auth);
4573
4574   g_mutex_lock (&priv->lock);
4575   old = priv->auth;
4576   priv->auth = auth;
4577   g_mutex_unlock (&priv->lock);
4578
4579   if (old)
4580     g_object_unref (old);
4581 }
4582
4583
4584 /**
4585  * gst_rtsp_client_get_auth:
4586  * @client: a #GstRTSPClient
4587  *
4588  * Get the #GstRTSPAuth used as the authentication manager of @client.
4589  *
4590  * Returns: (transfer full) (nullable): the #GstRTSPAuth of @client.
4591  * g_object_unref() after usage.
4592  */
4593 GstRTSPAuth *
4594 gst_rtsp_client_get_auth (GstRTSPClient * client)
4595 {
4596   GstRTSPClientPrivate *priv;
4597   GstRTSPAuth *result;
4598
4599   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
4600
4601   priv = client->priv;
4602
4603   g_mutex_lock (&priv->lock);
4604   if ((result = priv->auth))
4605     g_object_ref (result);
4606   g_mutex_unlock (&priv->lock);
4607
4608   return result;
4609 }
4610
4611 /**
4612  * gst_rtsp_client_set_thread_pool:
4613  * @client: a #GstRTSPClient
4614  * @pool: (transfer none) (nullable): a #GstRTSPThreadPool
4615  *
4616  * configure @pool to be used as the thread pool of @client.
4617  */
4618 void
4619 gst_rtsp_client_set_thread_pool (GstRTSPClient * client,
4620     GstRTSPThreadPool * pool)
4621 {
4622   GstRTSPClientPrivate *priv;
4623   GstRTSPThreadPool *old;
4624
4625   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4626
4627   priv = client->priv;
4628
4629   if (pool)
4630     g_object_ref (pool);
4631
4632   g_mutex_lock (&priv->lock);
4633   old = priv->thread_pool;
4634   priv->thread_pool = pool;
4635   g_mutex_unlock (&priv->lock);
4636
4637   if (old)
4638     g_object_unref (old);
4639 }
4640
4641 /**
4642  * gst_rtsp_client_get_thread_pool:
4643  * @client: a #GstRTSPClient
4644  *
4645  * Get the #GstRTSPThreadPool used as the thread pool of @client.
4646  *
4647  * Returns: (transfer full) (nullable): the #GstRTSPThreadPool of @client. g_object_unref() after
4648  * usage.
4649  */
4650 GstRTSPThreadPool *
4651 gst_rtsp_client_get_thread_pool (GstRTSPClient * client)
4652 {
4653   GstRTSPClientPrivate *priv;
4654   GstRTSPThreadPool *result;
4655
4656   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
4657
4658   priv = client->priv;
4659
4660   g_mutex_lock (&priv->lock);
4661   if ((result = priv->thread_pool))
4662     g_object_ref (result);
4663   g_mutex_unlock (&priv->lock);
4664
4665   return result;
4666 }
4667
4668 /**
4669  * gst_rtsp_client_set_connection:
4670  * @client: a #GstRTSPClient
4671  * @conn: (transfer full): a #GstRTSPConnection
4672  *
4673  * Set the #GstRTSPConnection of @client. This function takes ownership of
4674  * @conn.
4675  *
4676  * Returns: %TRUE on success.
4677  */
4678 gboolean
4679 gst_rtsp_client_set_connection (GstRTSPClient * client,
4680     GstRTSPConnection * conn)
4681 {
4682   GstRTSPClientPrivate *priv;
4683   GSocket *read_socket;
4684   GSocketAddress *address;
4685   GstRTSPUrl *url;
4686   GError *error = NULL;
4687
4688   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), FALSE);
4689   g_return_val_if_fail (conn != NULL, FALSE);
4690
4691   priv = client->priv;
4692
4693   gst_rtsp_connection_set_content_length_limit (conn,
4694       priv->content_length_limit);
4695   read_socket = gst_rtsp_connection_get_read_socket (conn);
4696
4697   if (!(address = g_socket_get_local_address (read_socket, &error)))
4698     goto no_address;
4699
4700   g_free (priv->server_ip);
4701   /* keep the original ip that the client connected to */
4702   if (G_IS_INET_SOCKET_ADDRESS (address)) {
4703     GInetAddress *iaddr;
4704
4705     iaddr = g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (address));
4706
4707     /* socket might be ipv6 but adress still ipv4 */
4708     priv->is_ipv6 = g_inet_address_get_family (iaddr) == G_SOCKET_FAMILY_IPV6;
4709     priv->server_ip = g_inet_address_to_string (iaddr);
4710     g_object_unref (address);
4711   } else {
4712     priv->is_ipv6 = g_socket_get_family (read_socket) == G_SOCKET_FAMILY_IPV6;
4713     priv->server_ip = g_strdup ("unknown");
4714     g_object_unref (address);
4715   }
4716
4717   GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
4718       priv->server_ip, priv->is_ipv6);
4719
4720   url = gst_rtsp_connection_get_url (conn);
4721   GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
4722
4723   priv->connection = conn;
4724
4725   return TRUE;
4726
4727   /* ERRORS */
4728 no_address:
4729   {
4730     GST_ERROR ("could not get local address %s", error->message);
4731     g_error_free (error);
4732     return FALSE;
4733   }
4734 }
4735
4736 /**
4737  * gst_rtsp_client_get_connection:
4738  * @client: a #GstRTSPClient
4739  *
4740  * Get the #GstRTSPConnection of @client.
4741  *
4742  * Returns: (transfer none) (nullable): the #GstRTSPConnection of @client.
4743  * The connection object returned remains valid until the client is freed.
4744  */
4745 GstRTSPConnection *
4746 gst_rtsp_client_get_connection (GstRTSPClient * client)
4747 {
4748   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
4749
4750   return client->priv->connection;
4751 }
4752
4753 /**
4754  * gst_rtsp_client_set_send_func:
4755  * @client: a #GstRTSPClient
4756  * @func: (scope notified): a #GstRTSPClientSendFunc
4757  * @user_data: (closure): user data passed to @func
4758  * @notify: (allow-none): called when @user_data is no longer in use
4759  *
4760  * Set @func as the callback that will be called when a new message needs to be
4761  * sent to the client. @user_data is passed to @func and @notify is called when
4762  * @user_data is no longer in use.
4763  *
4764  * By default, the client will send the messages on the #GstRTSPConnection that
4765  * was configured with gst_rtsp_client_attach() was called.
4766  *
4767  * It is only allowed to set either a `send_func` or a `send_messages_func`
4768  * but not both at the same time.
4769  */
4770 void
4771 gst_rtsp_client_set_send_func (GstRTSPClient * client,
4772     GstRTSPClientSendFunc func, gpointer user_data, GDestroyNotify notify)
4773 {
4774   GstRTSPClientPrivate *priv;
4775   GDestroyNotify old_notify;
4776   gpointer old_data;
4777
4778   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4779
4780   priv = client->priv;
4781
4782   g_mutex_lock (&priv->send_lock);
4783   g_assert (func == NULL || priv->send_messages_func == NULL);
4784   priv->send_func = func;
4785   old_notify = priv->send_notify;
4786   old_data = priv->send_data;
4787   priv->send_notify = notify;
4788   priv->send_data = user_data;
4789   g_mutex_unlock (&priv->send_lock);
4790
4791   if (old_notify)
4792     old_notify (old_data);
4793 }
4794
4795 /**
4796  * gst_rtsp_client_set_send_messages_func:
4797  * @client: a #GstRTSPClient
4798  * @func: (scope notified): a #GstRTSPClientSendMessagesFunc
4799  * @user_data: (closure): user data passed to @func
4800  * @notify: (allow-none): called when @user_data is no longer in use
4801  *
4802  * Set @func as the callback that will be called when new messages needs to be
4803  * sent to the client. @user_data is passed to @func and @notify is called when
4804  * @user_data is no longer in use.
4805  *
4806  * By default, the client will send the messages on the #GstRTSPConnection that
4807  * was configured with gst_rtsp_client_attach() was called.
4808  *
4809  * It is only allowed to set either a `send_func` or a `send_messages_func`
4810  * but not both at the same time.
4811  *
4812  * Since: 1.16
4813  */
4814 void
4815 gst_rtsp_client_set_send_messages_func (GstRTSPClient * client,
4816     GstRTSPClientSendMessagesFunc func, gpointer user_data,
4817     GDestroyNotify notify)
4818 {
4819   GstRTSPClientPrivate *priv;
4820   GDestroyNotify old_notify;
4821   gpointer old_data;
4822
4823   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
4824
4825   priv = client->priv;
4826
4827   g_mutex_lock (&priv->send_lock);
4828   g_assert (func == NULL || priv->send_func == NULL);
4829   priv->send_messages_func = func;
4830   old_notify = priv->send_messages_notify;
4831   old_data = priv->send_messages_data;
4832   priv->send_messages_notify = notify;
4833   priv->send_messages_data = user_data;
4834   g_mutex_unlock (&priv->send_lock);
4835
4836   if (old_notify)
4837     old_notify (old_data);
4838 }
4839
4840 /**
4841  * gst_rtsp_client_handle_message:
4842  * @client: a #GstRTSPClient
4843  * @message: (transfer none): an #GstRTSPMessage
4844  *
4845  * Let the client handle @message.
4846  *
4847  * Returns: a #GstRTSPResult.
4848  */
4849 GstRTSPResult
4850 gst_rtsp_client_handle_message (GstRTSPClient * client,
4851     GstRTSPMessage * message)
4852 {
4853   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), GST_RTSP_EINVAL);
4854   g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
4855
4856   switch (message->type) {
4857     case GST_RTSP_MESSAGE_REQUEST:
4858       handle_request (client, message);
4859       break;
4860     case GST_RTSP_MESSAGE_RESPONSE:
4861       handle_response (client, message);
4862       break;
4863     case GST_RTSP_MESSAGE_DATA:
4864       handle_data (client, message);
4865       break;
4866     default:
4867       break;
4868   }
4869   return GST_RTSP_OK;
4870 }
4871
4872 /**
4873  * gst_rtsp_client_send_message:
4874  * @client: a #GstRTSPClient
4875  * @session: (allow-none) (transfer none): a #GstRTSPSession to send
4876  *   the message to or %NULL
4877  * @message: (transfer none): The #GstRTSPMessage to send
4878  *
4879  * Send a message message to the remote end. @message must be a
4880  * #GST_RTSP_MESSAGE_REQUEST or a #GST_RTSP_MESSAGE_RESPONSE.
4881  */
4882 GstRTSPResult
4883 gst_rtsp_client_send_message (GstRTSPClient * client, GstRTSPSession * session,
4884     GstRTSPMessage * message)
4885 {
4886   GstRTSPContext sctx = { NULL }
4887   , *ctx;
4888   GstRTSPClientPrivate *priv;
4889
4890   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), GST_RTSP_EINVAL);
4891   g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL);
4892   g_return_val_if_fail (message->type == GST_RTSP_MESSAGE_REQUEST ||
4893       message->type == GST_RTSP_MESSAGE_RESPONSE, GST_RTSP_EINVAL);
4894
4895   priv = client->priv;
4896
4897   if (!(ctx = gst_rtsp_context_get_current ())) {
4898     ctx = &sctx;
4899     ctx->auth = priv->auth;
4900     gst_rtsp_context_push_current (ctx);
4901   }
4902
4903   ctx->conn = priv->connection;
4904   ctx->client = client;
4905   ctx->session = session;
4906
4907   send_message (client, ctx, message, FALSE);
4908
4909   if (ctx == &sctx)
4910     gst_rtsp_context_pop_current (ctx);
4911
4912   return GST_RTSP_OK;
4913 }
4914
4915 /**
4916  * gst_rtsp_client_get_stream_transport:
4917  *
4918  * This is useful when providing a send function through
4919  * gst_rtsp_client_set_send_func() when doing RTSP over TCP:
4920  * the send function must call gst_rtsp_stream_transport_message_sent ()
4921  * on the appropriate transport when data has been received for streaming
4922  * to continue.
4923  *
4924  * Returns: (transfer none) (nullable): the #GstRTSPStreamTransport associated with @channel.
4925  *
4926  * Since: 1.18
4927  */
4928 GstRTSPStreamTransport *
4929 gst_rtsp_client_get_stream_transport (GstRTSPClient * self, guint8 channel)
4930 {
4931   return g_hash_table_lookup (self->priv->transports,
4932       GINT_TO_POINTER ((gint) channel));
4933 }
4934
4935 static gboolean
4936 do_send_messages (GstRTSPClient * client, GstRTSPMessage * messages,
4937     guint n_messages, gboolean close, gpointer user_data)
4938 {
4939   GstRTSPClientPrivate *priv = client->priv;
4940   guint id = 0;
4941   GstRTSPResult ret;
4942   guint i;
4943
4944   /* send the message */
4945   if (close)
4946     GST_INFO ("client %p: sending close message", client);
4947
4948   ret = gst_rtsp_watch_send_messages (priv->watch, messages, n_messages, &id);
4949   if (ret != GST_RTSP_OK)
4950     goto error;
4951
4952   for (i = 0; i < n_messages; i++) {
4953     if (gst_rtsp_message_get_type (&messages[i]) == GST_RTSP_MESSAGE_DATA) {
4954       guint8 channel = 0;
4955       GstRTSPResult r;
4956
4957       /* We assume that all data messages in the list are for the
4958        * same channel */
4959       r = gst_rtsp_message_parse_data (&messages[i], &channel);
4960       if (r != GST_RTSP_OK) {
4961         ret = r;
4962         goto error;
4963       }
4964
4965       /* check if the message has been queued for transmission in watch */
4966       if (id) {
4967         /* store the seq number so we can wait until it has been sent */
4968         GST_DEBUG_OBJECT (client, "wait for message %d, channel %d", id,
4969             channel);
4970         set_data_seq (client, channel, id);
4971       } else {
4972         GstRTSPStreamTransport *trans;
4973
4974         trans =
4975             g_hash_table_lookup (priv->transports,
4976             GINT_TO_POINTER ((gint) channel));
4977         if (trans) {
4978           GST_DEBUG_OBJECT (client, "emit 'message-sent' signal");
4979           g_mutex_unlock (&priv->send_lock);
4980           gst_rtsp_stream_transport_message_sent (trans);
4981           g_mutex_lock (&priv->send_lock);
4982         }
4983       }
4984       break;
4985     }
4986   }
4987
4988   return ret == GST_RTSP_OK;
4989
4990   /* ERRORS */
4991 error:
4992   {
4993     GST_DEBUG_OBJECT (client, "got error %d", ret);
4994     return FALSE;
4995   }
4996 }
4997
4998 static GstRTSPResult
4999 message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
5000     gpointer user_data)
5001 {
5002   return gst_rtsp_client_handle_message (GST_RTSP_CLIENT (user_data), message);
5003 }
5004
5005 static GstRTSPResult
5006 message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
5007 {
5008   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5009   GstRTSPClientPrivate *priv = client->priv;
5010   GstRTSPStreamTransport *trans = NULL;
5011   guint8 channel = 0;
5012
5013   g_mutex_lock (&priv->send_lock);
5014
5015   if (get_data_channel (client, cseq, &channel)) {
5016     trans = g_hash_table_lookup (priv->transports, GINT_TO_POINTER (channel));
5017     set_data_seq (client, channel, 0);
5018   }
5019   g_mutex_unlock (&priv->send_lock);
5020
5021   if (trans) {
5022     GST_DEBUG_OBJECT (client, "emit 'message-sent' signal");
5023     gst_rtsp_stream_transport_message_sent (trans);
5024   }
5025
5026   return GST_RTSP_OK;
5027 }
5028
5029 static GstRTSPResult
5030 closed (GstRTSPWatch * watch, gpointer user_data)
5031 {
5032   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5033   GstRTSPClientPrivate *priv = client->priv;
5034   const gchar *tunnelid;
5035
5036   GST_INFO ("client %p: connection closed", client);
5037
5038   if ((tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection))) {
5039     g_mutex_lock (&tunnels_lock);
5040     /* remove from tunnelids */
5041     g_hash_table_remove (tunnels, tunnelid);
5042     g_mutex_unlock (&tunnels_lock);
5043   }
5044
5045   gst_rtsp_watch_set_flushing (watch, TRUE);
5046   g_mutex_lock (&priv->watch_lock);
5047   gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
5048   gst_rtsp_client_set_send_messages_func (client, NULL, NULL, NULL);
5049   g_mutex_unlock (&priv->watch_lock);
5050
5051   return GST_RTSP_OK;
5052 }
5053
5054 static GstRTSPResult
5055 error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data)
5056 {
5057   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5058   gchar *str;
5059
5060   str = gst_rtsp_strresult (result);
5061   GST_INFO ("client %p: received an error %s", client, str);
5062   g_free (str);
5063
5064   return GST_RTSP_OK;
5065 }
5066
5067 static GstRTSPResult
5068 error_full (GstRTSPWatch * watch, GstRTSPResult result,
5069     GstRTSPMessage * message, guint id, gpointer user_data)
5070 {
5071   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5072   gchar *str;
5073   GstRTSPContext sctx = { NULL }, *ctx;
5074   GstRTSPClientPrivate *priv;
5075   GstRTSPMessage response = { 0 };
5076   priv = client->priv;
5077
5078   if (!(ctx = gst_rtsp_context_get_current ())) {
5079     ctx = &sctx;
5080     ctx->auth = priv->auth;
5081     gst_rtsp_context_push_current (ctx);
5082   }
5083
5084   ctx->conn = priv->connection;
5085   ctx->client = client;
5086   ctx->request = message;
5087   ctx->method = GST_RTSP_INVALID;
5088   ctx->response = &response;
5089
5090   /* only return error response if it is a request */
5091   if (!message || message->type != GST_RTSP_MESSAGE_REQUEST)
5092     goto done;
5093
5094   if (result == GST_RTSP_ENOMEM) {
5095     send_generic_error_response (client, GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE,
5096         ctx);
5097     goto done;
5098   }
5099   if (result == GST_RTSP_EPARSE) {
5100     send_generic_error_response (client, GST_RTSP_STS_BAD_REQUEST, ctx);
5101     goto done;
5102   }
5103
5104 done:
5105   if (ctx == &sctx)
5106     gst_rtsp_context_pop_current (ctx);
5107   str = gst_rtsp_strresult (result);
5108   GST_INFO
5109       ("client %p: error when handling message %p with id %d: %s",
5110       client, message, id, str);
5111   g_free (str);
5112
5113   return GST_RTSP_OK;
5114 }
5115
5116 static gboolean
5117 remember_tunnel (GstRTSPClient * client)
5118 {
5119   GstRTSPClientPrivate *priv = client->priv;
5120   const gchar *tunnelid;
5121
5122   /* store client in the pending tunnels */
5123   tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection);
5124   if (tunnelid == NULL)
5125     goto no_tunnelid;
5126
5127   GST_INFO ("client %p: inserting tunnel session %s", client, tunnelid);
5128
5129   /* we can't have two clients connecting with the same tunnelid */
5130   g_mutex_lock (&tunnels_lock);
5131   if (g_hash_table_lookup (tunnels, tunnelid))
5132     goto tunnel_existed;
5133
5134   g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
5135   g_mutex_unlock (&tunnels_lock);
5136
5137   return TRUE;
5138
5139   /* ERRORS */
5140 no_tunnelid:
5141   {
5142     GST_ERROR ("client %p: no tunnelid provided", client);
5143     return FALSE;
5144   }
5145 tunnel_existed:
5146   {
5147     g_mutex_unlock (&tunnels_lock);
5148     GST_ERROR ("client %p: tunnel session %s already existed", client,
5149         tunnelid);
5150     return FALSE;
5151   }
5152 }
5153
5154 static GstRTSPResult
5155 tunnel_lost (GstRTSPWatch * watch, gpointer user_data)
5156 {
5157   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5158   GstRTSPClientPrivate *priv = client->priv;
5159
5160   GST_WARNING ("client %p: tunnel lost (connection %p)", client,
5161       priv->connection);
5162
5163   /* ignore error, it'll only be a problem when the client does a POST again */
5164   remember_tunnel (client);
5165
5166   return GST_RTSP_OK;
5167 }
5168
5169 static GstRTSPStatusCode
5170 handle_tunnel (GstRTSPClient * client)
5171 {
5172   GstRTSPClientPrivate *priv = client->priv;
5173   GstRTSPClient *oclient;
5174   GstRTSPClientPrivate *opriv;
5175   const gchar *tunnelid;
5176
5177   tunnelid = gst_rtsp_connection_get_tunnelid (priv->connection);
5178   if (tunnelid == NULL)
5179     goto no_tunnelid;
5180
5181   /* check for previous tunnel */
5182   g_mutex_lock (&tunnels_lock);
5183   oclient = g_hash_table_lookup (tunnels, tunnelid);
5184
5185   if (oclient == NULL) {
5186     /* no previous tunnel, remember tunnel */
5187     g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
5188     g_mutex_unlock (&tunnels_lock);
5189
5190     GST_INFO ("client %p: no previous tunnel found, remembering tunnel (%p)",
5191         client, priv->connection);
5192   } else {
5193     /* merge both tunnels into the first client */
5194     /* remove the old client from the table. ref before because removing it will
5195      * remove the ref to it. */
5196     g_object_ref (oclient);
5197     g_hash_table_remove (tunnels, tunnelid);
5198     g_mutex_unlock (&tunnels_lock);
5199
5200     opriv = oclient->priv;
5201
5202     g_mutex_lock (&opriv->watch_lock);
5203     if (opriv->watch == NULL)
5204       goto tunnel_closed;
5205     if (opriv->tstate == priv->tstate)
5206       goto tunnel_duplicate_id;
5207
5208     GST_INFO ("client %p: found previous tunnel %p (old %p, new %p)", client,
5209         oclient, opriv->connection, priv->connection);
5210
5211     gst_rtsp_connection_do_tunnel (opriv->connection, priv->connection);
5212     gst_rtsp_watch_reset (priv->watch);
5213     gst_rtsp_watch_reset (opriv->watch);
5214     g_mutex_unlock (&opriv->watch_lock);
5215     g_object_unref (oclient);
5216
5217     /* the old client owns the tunnel now, the new one will be freed */
5218     g_source_destroy ((GSource *) priv->watch);
5219     priv->watch = NULL;
5220     gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
5221     gst_rtsp_client_set_send_messages_func (client, NULL, NULL, NULL);
5222     rtsp_ctrl_timeout_remove (client);
5223   }
5224
5225   return GST_RTSP_STS_OK;
5226
5227   /* ERRORS */
5228 no_tunnelid:
5229   {
5230     GST_ERROR ("client %p: no tunnelid provided", client);
5231     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
5232   }
5233 tunnel_closed:
5234   {
5235     GST_ERROR ("client %p: tunnel session %s was closed", client, tunnelid);
5236     g_mutex_unlock (&opriv->watch_lock);
5237     g_object_unref (oclient);
5238     return GST_RTSP_STS_SERVICE_UNAVAILABLE;
5239   }
5240 tunnel_duplicate_id:
5241   {
5242     GST_ERROR ("client %p: tunnel session %s was duplicate", client, tunnelid);
5243     g_mutex_unlock (&opriv->watch_lock);
5244     g_object_unref (oclient);
5245     return GST_RTSP_STS_BAD_REQUEST;
5246   }
5247 }
5248
5249 static GstRTSPStatusCode
5250 tunnel_get (GstRTSPWatch * watch, gpointer user_data)
5251 {
5252   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5253
5254   GST_INFO ("client %p: tunnel get (connection %p)", client,
5255       client->priv->connection);
5256
5257   g_mutex_lock (&client->priv->lock);
5258   client->priv->tstate = TUNNEL_STATE_GET;
5259   g_mutex_unlock (&client->priv->lock);
5260
5261   return handle_tunnel (client);
5262 }
5263
5264 static GstRTSPResult
5265 tunnel_post (GstRTSPWatch * watch, gpointer user_data)
5266 {
5267   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5268
5269   GST_INFO ("client %p: tunnel post (connection %p)", client,
5270       client->priv->connection);
5271
5272   g_mutex_lock (&client->priv->lock);
5273   client->priv->tstate = TUNNEL_STATE_POST;
5274   g_mutex_unlock (&client->priv->lock);
5275
5276   if (handle_tunnel (client) != GST_RTSP_STS_OK)
5277     return GST_RTSP_ERROR;
5278
5279   return GST_RTSP_OK;
5280 }
5281
5282 static GstRTSPResult
5283 tunnel_http_response (GstRTSPWatch * watch, GstRTSPMessage * request,
5284     GstRTSPMessage * response, gpointer user_data)
5285 {
5286   GstRTSPClientClass *klass;
5287
5288   GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
5289   klass = GST_RTSP_CLIENT_GET_CLASS (client);
5290
5291   if (klass->tunnel_http_response) {
5292     klass->tunnel_http_response (client, request, response);
5293   }
5294
5295   return GST_RTSP_OK;
5296 }
5297
5298 static GstRTSPWatchFuncs watch_funcs = {
5299   message_received,
5300   message_sent,
5301   closed,
5302   error,
5303   tunnel_get,
5304   tunnel_post,
5305   error_full,
5306   tunnel_lost,
5307   tunnel_http_response
5308 };
5309
5310 static void
5311 client_watch_notify (GstRTSPClient * client)
5312 {
5313   GstRTSPClientPrivate *priv = client->priv;
5314   gboolean closed = TRUE;
5315
5316   GST_INFO ("client %p: watch destroyed", client);
5317   priv->watch = NULL;
5318   /* remove all sessions if the media says so and so drop the extra client ref */
5319   gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
5320   gst_rtsp_client_set_send_messages_func (client, NULL, NULL, NULL);
5321   rtsp_ctrl_timeout_remove (client);
5322   gst_rtsp_client_session_filter (client, cleanup_session, &closed);
5323
5324   if (closed)
5325     g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
5326   g_object_unref (client);
5327 }
5328
5329 /**
5330  * gst_rtsp_client_attach:
5331  * @client: a #GstRTSPClient
5332  * @context: (allow-none): a #GMainContext
5333  *
5334  * Attaches @client to @context. When the mainloop for @context is run, the
5335  * client will be dispatched. When @context is %NULL, the default context will be
5336  * used).
5337  *
5338  * This function should be called when the client properties and urls are fully
5339  * configured and the client is ready to start.
5340  *
5341  * Returns: the ID (greater than 0) for the source within the GMainContext.
5342  */
5343 guint
5344 gst_rtsp_client_attach (GstRTSPClient * client, GMainContext * context)
5345 {
5346   GstRTSPClientPrivate *priv;
5347   GSource *timer_src;
5348   guint res;
5349   GWeakRef *client_weak_ref = g_new (GWeakRef, 1);
5350
5351   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), 0);
5352   priv = client->priv;
5353   g_return_val_if_fail (priv->connection != NULL, 0);
5354   g_return_val_if_fail (priv->watch == NULL, 0);
5355   g_return_val_if_fail (priv->watch_context == NULL, 0);
5356
5357   /* make sure noone will free the context before the watch is destroyed */
5358   priv->watch_context = g_main_context_ref (context);
5359
5360   /* create watch for the connection and attach */
5361   priv->watch = gst_rtsp_watch_new (priv->connection, &watch_funcs,
5362       g_object_ref (client), (GDestroyNotify) client_watch_notify);
5363   gst_rtsp_client_set_send_func (client, NULL, NULL, NULL);
5364   gst_rtsp_client_set_send_messages_func (client, do_send_messages, priv->watch,
5365       (GDestroyNotify) gst_rtsp_watch_unref);
5366
5367   gst_rtsp_watch_set_send_backlog (priv->watch, 0, WATCH_BACKLOG_SIZE);
5368
5369   /* take the lock before attaching the client watch, so that the client thread
5370    * can not access the control channel timer until it's properly in place */
5371   g_mutex_lock (&priv->lock);
5372
5373   GST_INFO ("client %p: attaching to context %p", client, context);
5374   res = gst_rtsp_watch_attach (priv->watch, context);
5375
5376   /* Setting up a timeout for the RTSP control channel until a session
5377    * is up where it is handling timeouts. */
5378
5379   /* remove old timeout if any */
5380   rtsp_ctrl_timeout_remove_unlocked (client->priv);
5381
5382   timer_src = g_timeout_source_new_seconds (RTSP_CTRL_CB_INTERVAL);
5383   g_weak_ref_init (client_weak_ref, client);
5384   g_source_set_callback (timer_src, rtsp_ctrl_timeout_cb, client_weak_ref,
5385       rtsp_ctrl_timeout_destroy_notify);
5386   g_source_attach (timer_src, priv->watch_context);
5387   priv->rtsp_ctrl_timeout = timer_src;
5388   GST_DEBUG ("rtsp control setting up session timeout %p.",
5389       priv->rtsp_ctrl_timeout);
5390
5391   g_mutex_unlock (&priv->lock);
5392
5393   return res;
5394 }
5395
5396 /**
5397  * gst_rtsp_client_session_filter:
5398  * @client: a #GstRTSPClient
5399  * @func: (scope call) (allow-none): a callback
5400  * @user_data: user data passed to @func
5401  *
5402  * Call @func for each session managed by @client. The result value of @func
5403  * determines what happens to the session. @func will be called with @client
5404  * locked so no further actions on @client can be performed from @func.
5405  *
5406  * If @func returns #GST_RTSP_FILTER_REMOVE, the session will be removed from
5407  * @client.
5408  *
5409  * If @func returns #GST_RTSP_FILTER_KEEP, the session will remain in @client.
5410  *
5411  * If @func returns #GST_RTSP_FILTER_REF, the session will remain in @client but
5412  * will also be added with an additional ref to the result #GList of this
5413  * function..
5414  *
5415  * When @func is %NULL, #GST_RTSP_FILTER_REF will be assumed for each session.
5416  *
5417  * Returns: (element-type GstRTSPSession) (transfer full): a #GList with all
5418  * sessions for which @func returned #GST_RTSP_FILTER_REF. After usage, each
5419  * element in the #GList should be unreffed before the list is freed.
5420  */
5421 GList *
5422 gst_rtsp_client_session_filter (GstRTSPClient * client,
5423     GstRTSPClientSessionFilterFunc func, gpointer user_data)
5424 {
5425   GstRTSPClientPrivate *priv;
5426   GList *result, *walk, *next;
5427   GHashTable *visited;
5428   guint cookie;
5429
5430   g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
5431
5432   priv = client->priv;
5433
5434   result = NULL;
5435   if (func)
5436     visited = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
5437
5438   g_mutex_lock (&priv->lock);
5439 restart:
5440   cookie = priv->sessions_cookie;
5441   for (walk = priv->sessions; walk; walk = next) {
5442     GstRTSPSession *sess = walk->data;
5443     GstRTSPFilterResult res;
5444     gboolean changed;
5445
5446     next = g_list_next (walk);
5447
5448     if (func) {
5449       /* only visit each session once */
5450       if (g_hash_table_contains (visited, sess))
5451         continue;
5452
5453       g_hash_table_add (visited, g_object_ref (sess));
5454       g_mutex_unlock (&priv->lock);
5455
5456       res = func (client, sess, user_data);
5457
5458       g_mutex_lock (&priv->lock);
5459     } else
5460       res = GST_RTSP_FILTER_REF;
5461
5462     changed = (cookie != priv->sessions_cookie);
5463
5464     switch (res) {
5465       case GST_RTSP_FILTER_REMOVE:
5466         /* stop watching the session and pretend it went away, if the list was
5467          * changed, we can't use the current list position, try to see if we
5468          * still have the session */
5469         client_unwatch_session (client, sess, changed ? NULL : walk);
5470         cookie = priv->sessions_cookie;
5471         break;
5472       case GST_RTSP_FILTER_REF:
5473         result = g_list_prepend (result, g_object_ref (sess));
5474         break;
5475       case GST_RTSP_FILTER_KEEP:
5476       default:
5477         break;
5478     }
5479     if (changed)
5480       goto restart;
5481   }
5482   g_mutex_unlock (&priv->lock);
5483
5484   if (func)
5485     g_hash_table_unref (visited);
5486
5487   return result;
5488 }
5489
5490 /**
5491  * gst_rtsp_client_set_watch_flushing:
5492  * @client: a #GstRTSPClient
5493  * @val: a boolean value
5494  *
5495  * sets watch flushing to @val on watch to accet/ignore new messages.
5496  */
5497 void
5498 gst_rtsp_client_set_watch_flushing (GstRTSPClient * client, gboolean val)
5499 {
5500   GstRTSPClientPrivate *priv = NULL;
5501   g_return_if_fail (GST_IS_RTSP_CLIENT (client));
5502
5503   priv = gst_rtsp_client_get_instance_private (client);
5504
5505   /* make sure we unblock/block the backlog and accept/don't accept new messages on the watch */
5506   if (priv->watch != NULL) {
5507     GST_INFO ("Set watch flushing as %d", val);
5508     gst_rtsp_watch_set_flushing (priv->watch, val);
5509   }
5510 }