2 * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
26 #include <sys/types.h>
27 #include <netinet/in.h>
29 #include <sys/socket.h>
32 #include <arpa/inet.h>
33 #include <sys/ioctl.h>
35 #include "rtsp-client.h"
37 #include "rtsp-params.h"
39 /* temporary multicast address until it's configurable somewhere */
40 #define MCAST_ADDRESS "224.2.0.1"
42 static GMutex *tunnels_lock;
43 static GHashTable *tunnels;
59 GST_DEBUG_CATEGORY_STATIC (rtsp_client_debug);
60 #define GST_CAT_DEFAULT rtsp_client_debug
62 static guint gst_rtsp_client_signals[SIGNAL_LAST] = { 0 };
64 static void gst_rtsp_client_get_property (GObject * object, guint propid,
65 GValue * value, GParamSpec * pspec);
66 static void gst_rtsp_client_set_property (GObject * object, guint propid,
67 const GValue * value, GParamSpec * pspec);
68 static void gst_rtsp_client_finalize (GObject * obj);
70 static void client_session_finalized (GstRTSPClient * client,
71 GstRTSPSession * session);
72 static void unlink_session_streams (GstRTSPClient * client,
73 GstRTSPSession * session, GstRTSPSessionMedia * media);
75 G_DEFINE_TYPE (GstRTSPClient, gst_rtsp_client, G_TYPE_OBJECT);
78 gst_rtsp_client_class_init (GstRTSPClientClass * klass)
80 GObjectClass *gobject_class;
82 gobject_class = G_OBJECT_CLASS (klass);
84 gobject_class->get_property = gst_rtsp_client_get_property;
85 gobject_class->set_property = gst_rtsp_client_set_property;
86 gobject_class->finalize = gst_rtsp_client_finalize;
88 g_object_class_install_property (gobject_class, PROP_SESSION_POOL,
89 g_param_spec_object ("session-pool", "Session Pool",
90 "The session pool to use for client session",
91 GST_TYPE_RTSP_SESSION_POOL,
92 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
94 g_object_class_install_property (gobject_class, PROP_MEDIA_MAPPING,
95 g_param_spec_object ("media-mapping", "Media Mapping",
96 "The media mapping to use for client session",
97 GST_TYPE_RTSP_MEDIA_MAPPING,
98 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
100 gst_rtsp_client_signals[SIGNAL_CLOSED] =
101 g_signal_new ("closed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
102 G_STRUCT_OFFSET (GstRTSPClientClass, closed), NULL, NULL,
103 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
106 g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
107 tunnels_lock = g_mutex_new ();
109 GST_DEBUG_CATEGORY_INIT (rtsp_client_debug, "rtspclient", 0, "GstRTSPClient");
113 gst_rtsp_client_init (GstRTSPClient * client)
118 client_unlink_session (GstRTSPClient * client, GstRTSPSession * session)
122 /* unlink all media managed in this session */
123 for (medias = session->medias; medias; medias = g_list_next (medias)) {
124 GstRTSPSessionMedia *media = medias->data;
126 gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
127 unlink_session_streams (client, session, media);
128 /* unmanage the media in the session. */
129 gst_rtsp_session_release_media (session, media);
134 client_cleanup_sessions (GstRTSPClient * client)
138 /* remove weak-ref from sessions */
139 for (sessions = client->sessions; sessions; sessions = g_list_next (sessions)) {
140 GstRTSPSession *session = (GstRTSPSession *) sessions->data;
141 g_object_weak_unref (G_OBJECT (session),
142 (GWeakNotify) client_session_finalized, client);
143 client_unlink_session (client, session);
145 g_list_free (client->sessions);
146 client->sessions = NULL;
149 /* A client is finalized when the connection is broken */
151 gst_rtsp_client_finalize (GObject * obj)
153 GstRTSPClient *client = GST_RTSP_CLIENT (obj);
155 GST_INFO ("finalize client %p", client);
157 client_cleanup_sessions (client);
159 gst_rtsp_connection_free (client->connection);
160 if (client->session_pool)
161 g_object_unref (client->session_pool);
162 if (client->media_mapping)
163 g_object_unref (client->media_mapping);
165 g_object_unref (client->auth);
168 gst_rtsp_url_free (client->uri);
170 g_object_unref (client->media);
172 g_free (client->server_ip);
174 G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
178 gst_rtsp_client_get_property (GObject * object, guint propid,
179 GValue * value, GParamSpec * pspec)
181 GstRTSPClient *client = GST_RTSP_CLIENT (object);
184 case PROP_SESSION_POOL:
185 g_value_take_object (value, gst_rtsp_client_get_session_pool (client));
187 case PROP_MEDIA_MAPPING:
188 g_value_take_object (value, gst_rtsp_client_get_media_mapping (client));
191 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
196 gst_rtsp_client_set_property (GObject * object, guint propid,
197 const GValue * value, GParamSpec * pspec)
199 GstRTSPClient *client = GST_RTSP_CLIENT (object);
202 case PROP_SESSION_POOL:
203 gst_rtsp_client_set_session_pool (client, g_value_get_object (value));
205 case PROP_MEDIA_MAPPING:
206 gst_rtsp_client_set_media_mapping (client, g_value_get_object (value));
209 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
214 * gst_rtsp_client_new:
216 * Create a new #GstRTSPClient instance.
218 * Returns: a new #GstRTSPClient
221 gst_rtsp_client_new (void)
223 GstRTSPClient *result;
225 result = g_object_new (GST_TYPE_RTSP_CLIENT, NULL);
231 send_response (GstRTSPClient * client, GstRTSPSession * session,
232 GstRTSPMessage * response)
234 gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER,
235 "GStreamer RTSP server");
237 /* remove any previous header */
238 gst_rtsp_message_remove_header (response, GST_RTSP_HDR_SESSION, -1);
240 /* add the new session header for new session ids */
244 if (session->timeout != 60)
246 g_strdup_printf ("%s; timeout=%d", session->sessionid,
249 str = g_strdup (session->sessionid);
251 gst_rtsp_message_take_header (response, GST_RTSP_HDR_SESSION, str);
254 if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
255 gst_rtsp_message_dump (response);
258 gst_rtsp_watch_send_message (client->watch, response, NULL);
259 gst_rtsp_message_unset (response);
263 send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
264 GstRTSPClientState * state)
266 gst_rtsp_message_init_response (state->response, code,
267 gst_rtsp_status_as_text (code), state->request);
269 send_response (client, NULL, state->response);
273 handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
274 GstRTSPClientState * state)
276 gst_rtsp_message_init_response (state->response, GST_RTSP_STS_UNAUTHORIZED,
277 gst_rtsp_status_as_text (GST_RTSP_STS_UNAUTHORIZED), state->request);
280 /* and let the authentication manager setup the auth tokens */
281 gst_rtsp_auth_setup_auth (auth, client, 0, state);
284 send_response (client, state->session, state->response);
289 compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
291 if (uri1 == NULL || uri2 == NULL)
294 if (strcmp (uri1->abspath, uri2->abspath))
300 /* this function is called to initially find the media for the DESCRIBE request
301 * but is cached for when the same client (without breaking the connection) is
302 * doing a setup for the exact same url. */
303 static GstRTSPMedia *
304 find_media (GstRTSPClient * client, GstRTSPClientState * state)
306 GstRTSPMediaFactory *factory;
310 if (!compare_uri (client->uri, state->uri)) {
311 /* remove any previously cached values before we try to construct a new
314 gst_rtsp_url_free (client->uri);
317 g_object_unref (client->media);
318 client->media = NULL;
320 if (!client->media_mapping)
323 /* find the factory for the uri first */
325 gst_rtsp_media_mapping_find_factory (client->media_mapping,
329 state->factory = factory;
331 /* check if we have access to the factory */
332 if ((auth = gst_rtsp_media_factory_get_auth (factory))) {
333 if (!gst_rtsp_auth_check (auth, client, 0, state))
336 g_object_unref (auth);
339 /* prepare the media and add it to the pipeline */
340 if (!(media = gst_rtsp_media_factory_construct (factory, state->uri)))
343 g_object_unref (factory);
345 state->factory = NULL;
347 /* set ipv6 on the media before preparing */
348 media->is_ipv6 = client->is_ipv6;
349 state->media = media;
351 /* prepare the media */
352 if (!(gst_rtsp_media_prepare (media)))
355 /* now keep track of the uri and the media */
356 client->uri = gst_rtsp_url_copy (state->uri);
357 client->media = media;
359 /* we have seen this uri before, used cached media */
360 media = client->media;
361 state->media = media;
362 GST_INFO ("reusing cached media %p", media);
366 g_object_ref (media);
373 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
378 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
383 handle_unauthorized_request (client, auth, state);
384 g_object_unref (factory);
385 g_object_unref (auth);
390 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
391 g_object_unref (factory);
396 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
397 g_object_unref (media);
403 do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
405 GstRTSPMessage message = { 0 };
409 gst_rtsp_message_init_data (&message, channel);
411 data = GST_BUFFER_DATA (buffer);
412 size = GST_BUFFER_SIZE (buffer);
413 gst_rtsp_message_take_body (&message, data, size);
415 /* FIXME, client->watch could have been finalized here, we need to keep an
416 * extra refcount to the watch. */
417 gst_rtsp_watch_send_message (client->watch, &message, NULL);
419 gst_rtsp_message_steal_body (&message, &data, &size);
420 gst_rtsp_message_unset (&message);
426 do_send_data_list (GstBufferList * blist, guint8 channel,
427 GstRTSPClient * client)
429 GstBufferListIterator *it;
431 it = gst_buffer_list_iterate (blist);
432 while (gst_buffer_list_iterator_next_group (it)) {
433 GstBuffer *group = gst_buffer_list_iterator_merge_group (it);
438 do_send_data (group, channel, client);
440 gst_buffer_list_iterator_free (it);
446 link_stream (GstRTSPClient * client, GstRTSPSession * session,
447 GstRTSPSessionStream * stream)
449 GST_DEBUG ("client %p: linking stream %p", client, stream);
450 gst_rtsp_session_stream_set_callbacks (stream, (GstRTSPSendFunc) do_send_data,
451 (GstRTSPSendFunc) do_send_data, (GstRTSPSendListFunc) do_send_data_list,
452 (GstRTSPSendListFunc) do_send_data_list, client, NULL);
453 client->streams = g_list_prepend (client->streams, stream);
454 /* make sure our session can't expire */
455 gst_rtsp_session_prevent_expire (session);
459 unlink_stream (GstRTSPClient * client, GstRTSPSession * session,
460 GstRTSPSessionStream * stream)
462 GST_DEBUG ("client %p: unlinking stream %p", client, stream);
463 gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL, NULL,
465 client->streams = g_list_remove (client->streams, stream);
466 /* our session can now expire */
467 gst_rtsp_session_allow_expire (session);
471 unlink_session_streams (GstRTSPClient * client, GstRTSPSession * session,
472 GstRTSPSessionMedia * media)
476 n_streams = gst_rtsp_media_n_streams (media->media);
477 for (i = 0; i < n_streams; i++) {
478 GstRTSPSessionStream *sstream;
479 GstRTSPTransport *tr;
481 /* get the stream as configured in the session */
482 sstream = gst_rtsp_session_media_get_stream (media, i);
483 /* get the transport, if there is no transport configured, skip this stream */
484 if (!(tr = sstream->trans.transport))
487 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
488 /* for TCP, unlink the stream from the TCP connection of the client */
489 unlink_stream (client, session, sstream);
495 close_connection (GstRTSPClient * client)
497 const gchar *tunnelid;
499 GST_DEBUG ("client %p: closing connection", client);
501 if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
502 g_mutex_lock (tunnels_lock);
503 /* remove from tunnelids */
504 g_hash_table_remove (tunnels, tunnelid);
505 g_mutex_unlock (tunnels_lock);
508 gst_rtsp_connection_close (client->connection);
509 if (client->watchid) {
510 g_source_destroy ((GSource *) client->watch);
512 client->watch = NULL;
517 handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
519 GstRTSPSession *session;
520 GstRTSPSessionMedia *media;
521 GstRTSPStatusCode code;
526 session = state->session;
528 /* get a handle to the configuration of the media in the session */
529 media = gst_rtsp_session_get_media (session, state->uri);
533 state->sessmedia = media;
535 /* unlink the all TCP callbacks */
536 unlink_session_streams (client, session, media);
538 /* remove the session from the watched sessions */
539 g_object_weak_unref (G_OBJECT (session),
540 (GWeakNotify) client_session_finalized, client);
541 client->sessions = g_list_remove (client->sessions, session);
543 gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
545 /* unmanage the media in the session, returns false if all media session
547 if (!gst_rtsp_session_release_media (session, media)) {
548 /* remove the session */
549 gst_rtsp_session_pool_remove (client->session_pool, session);
551 /* construct the response now */
552 code = GST_RTSP_STS_OK;
553 gst_rtsp_message_init_response (state->response, code,
554 gst_rtsp_status_as_text (code), state->request);
556 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONNECTION,
559 send_response (client, session, state->response);
561 close_connection (client);
568 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
573 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
579 handle_get_param_request (GstRTSPClient * client, GstRTSPClientState * state)
585 res = gst_rtsp_message_get_body (state->request, &data, &size);
586 if (res != GST_RTSP_OK)
590 /* no body, keep-alive request */
591 send_generic_response (client, GST_RTSP_STS_OK, state);
593 /* there is a body, handle the params */
594 res = gst_rtsp_params_get (client, state);
595 if (res != GST_RTSP_OK)
598 send_response (client, state->session, state->response);
605 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
611 handle_set_param_request (GstRTSPClient * client, GstRTSPClientState * state)
617 res = gst_rtsp_message_get_body (state->request, &data, &size);
618 if (res != GST_RTSP_OK)
622 /* no body, keep-alive request */
623 send_generic_response (client, GST_RTSP_STS_OK, state);
625 /* there is a body, handle the params */
626 res = gst_rtsp_params_set (client, state);
627 if (res != GST_RTSP_OK)
630 send_response (client, state->session, state->response);
637 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
643 handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
645 GstRTSPSession *session;
646 GstRTSPSessionMedia *media;
647 GstRTSPStatusCode code;
649 if (!(session = state->session))
652 /* get a handle to the configuration of the media in the session */
653 media = gst_rtsp_session_get_media (session, state->uri);
657 state->sessmedia = media;
659 /* the session state must be playing or recording */
660 if (media->state != GST_RTSP_STATE_PLAYING &&
661 media->state != GST_RTSP_STATE_RECORDING)
664 /* unlink the all TCP callbacks */
665 unlink_session_streams (client, session, media);
667 /* then pause sending */
668 gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
670 /* construct the response now */
671 code = GST_RTSP_STS_OK;
672 gst_rtsp_message_init_response (state->response, code,
673 gst_rtsp_status_as_text (code), state->request);
675 send_response (client, session, state->response);
677 /* the state is now READY */
678 media->state = GST_RTSP_STATE_READY;
685 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
690 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
695 send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
702 handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
704 GstRTSPSession *session;
705 GstRTSPSessionMedia *media;
706 GstRTSPStatusCode code;
708 guint n_streams, i, infocount;
709 guint timestamp, seqnum;
711 GstRTSPTimeRange *range;
714 if (!(session = state->session))
717 /* get a handle to the configuration of the media in the session */
718 media = gst_rtsp_session_get_media (session, state->uri);
722 state->sessmedia = media;
724 /* the session state must be playing or ready */
725 if (media->state != GST_RTSP_STATE_PLAYING &&
726 media->state != GST_RTSP_STATE_READY)
729 /* parse the range header if we have one */
731 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_RANGE, &str, 0);
732 if (res == GST_RTSP_OK) {
733 if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
734 /* we have a range, seek to the position */
735 gst_rtsp_media_seek (media->media, range);
736 gst_rtsp_range_free (range);
740 /* grab RTPInfo from the payloaders now */
741 rtpinfo = g_string_new ("");
743 n_streams = gst_rtsp_media_n_streams (media->media);
744 for (i = 0, infocount = 0; i < n_streams; i++) {
745 GstRTSPSessionStream *sstream;
746 GstRTSPMediaStream *stream;
747 GstRTSPTransport *tr;
748 GObjectClass *payobjclass;
751 /* get the stream as configured in the session */
752 sstream = gst_rtsp_session_media_get_stream (media, i);
753 /* get the transport, if there is no transport configured, skip this stream */
754 if (!(tr = sstream->trans.transport)) {
755 GST_INFO ("stream %d is not configured", i);
759 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
760 /* for TCP, link the stream to the TCP connection of the client */
761 link_stream (client, session, sstream);
764 stream = sstream->media_stream;
766 payobjclass = G_OBJECT_GET_CLASS (stream->payloader);
768 if (g_object_class_find_property (payobjclass, "seqnum") &&
769 g_object_class_find_property (payobjclass, "timestamp")) {
772 payobj = G_OBJECT (stream->payloader);
774 /* only add RTP-Info for streams with seqnum and timestamp */
775 g_object_get (payobj, "seqnum", &seqnum, "timestamp", ×tamp, NULL);
778 g_string_append (rtpinfo, ", ");
780 uristr = gst_rtsp_url_get_request_uri (state->uri);
781 g_string_append_printf (rtpinfo, "url=%s/stream=%d;seq=%u;rtptime=%u",
782 uristr, i, seqnum, timestamp);
787 GST_WARNING ("RTP-Info cannot be determined for stream %d", i);
791 /* construct the response now */
792 code = GST_RTSP_STS_OK;
793 gst_rtsp_message_init_response (state->response, code,
794 gst_rtsp_status_as_text (code), state->request);
796 /* add the RTP-Info header */
798 str = g_string_free (rtpinfo, FALSE);
799 gst_rtsp_message_take_header (state->response, GST_RTSP_HDR_RTP_INFO, str);
801 g_string_free (rtpinfo, TRUE);
805 str = gst_rtsp_media_get_range_string (media->media, TRUE);
806 gst_rtsp_message_take_header (state->response, GST_RTSP_HDR_RANGE, str);
808 send_response (client, session, state->response);
810 /* start playing after sending the request */
811 gst_rtsp_session_media_set_state (media, GST_STATE_PLAYING);
813 media->state = GST_RTSP_STATE_PLAYING;
820 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
825 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
830 send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
837 do_keepalive (GstRTSPSession * session)
839 GST_INFO ("keep session %p alive", session);
840 gst_rtsp_session_touch (session);
844 handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
850 gboolean have_transport;
851 GstRTSPTransport *ct, *st;
853 GstRTSPLowerTrans supported;
854 GstRTSPStatusCode code;
855 GstRTSPSession *session;
856 GstRTSPSessionStream *stream;
857 gchar *trans_str, *pos;
859 GstRTSPSessionMedia *media;
863 /* the uri contains the stream number we added in the SDP config, which is
864 * always /stream=%d so we need to strip that off
865 * parse the stream we need to configure, look for the stream in the abspath
866 * first and then in the query. */
867 if (uri->abspath == NULL || !(pos = strstr (uri->abspath, "/stream="))) {
868 if (uri->query == NULL || !(pos = strstr (uri->query, "/stream=")))
872 /* we can mofify the parse uri in place */
875 pos += strlen ("/stream=");
876 if (sscanf (pos, "%u", &streamid) != 1)
879 /* parse the transport */
881 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_TRANSPORT,
883 if (res != GST_RTSP_OK)
886 transports = g_strsplit (transport, ",", 0);
887 gst_rtsp_transport_new (&ct);
889 /* init transports */
890 have_transport = FALSE;
891 gst_rtsp_transport_init (ct);
893 /* our supported transports */
894 supported = GST_RTSP_LOWER_TRANS_UDP |
895 GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP;
897 /* loop through the transports, try to parse */
898 for (i = 0; transports[i]; i++) {
899 res = gst_rtsp_transport_parse (transports[i], ct);
900 if (res != GST_RTSP_OK) {
901 /* no valid transport, search some more */
902 GST_WARNING ("could not parse transport %s", transports[i]);
906 /* we have a transport, see if it's RTP/AVP */
907 if (ct->trans != GST_RTSP_TRANS_RTP || ct->profile != GST_RTSP_PROFILE_AVP) {
908 GST_WARNING ("invalid transport %s", transports[i]);
912 if (!(ct->lower_transport & supported)) {
913 GST_WARNING ("unsupported transport %s", transports[i]);
917 /* we have a valid transport */
918 GST_INFO ("found valid transport %s", transports[i]);
919 have_transport = TRUE;
923 gst_rtsp_transport_init (ct);
925 g_strfreev (transports);
927 /* we have not found anything usable, error out */
929 goto unsupported_transports;
931 if (client->session_pool == NULL)
934 session = state->session;
937 g_object_ref (session);
938 /* get a handle to the configuration of the media in the session, this can
939 * return NULL if this is a new url to manage in this session. */
940 media = gst_rtsp_session_get_media (session, uri);
942 /* create a session if this fails we probably reached our session limit or
944 if (!(session = gst_rtsp_session_pool_create (client->session_pool)))
945 goto service_unavailable;
947 state->session = session;
949 /* we need a new media configuration in this session */
953 /* we have no media, find one and manage it */
957 /* get a handle to the configuration of the media in the session */
958 if ((m = find_media (client, state))) {
959 /* manage the media in our session now */
960 media = gst_rtsp_session_manage_media (session, uri, m);
964 /* if we stil have no media, error */
968 state->sessmedia = media;
970 /* we have a valid transport now, set the destination of the client. */
971 g_free (ct->destination);
972 if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
973 ct->destination = g_strdup (MCAST_ADDRESS);
977 url = gst_rtsp_connection_get_url (client->connection);
978 ct->destination = g_strdup (url->host);
980 if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) {
981 /* check if the client selected channels for TCP */
982 if (ct->interleaved.min == -1 || ct->interleaved.max == -1) {
983 gst_rtsp_session_media_alloc_channels (media, &ct->interleaved);
988 /* get a handle to the stream in the media */
989 if (!(stream = gst_rtsp_session_media_get_stream (media, streamid)))
992 st = gst_rtsp_session_stream_set_transport (stream, ct);
994 /* configure keepalive for this transport */
995 gst_rtsp_session_stream_set_keepalive (stream,
996 (GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
998 /* serialize the server transport */
999 trans_str = gst_rtsp_transport_as_text (st);
1000 gst_rtsp_transport_free (st);
1002 /* construct the response now */
1003 code = GST_RTSP_STS_OK;
1004 gst_rtsp_message_init_response (state->response, code,
1005 gst_rtsp_status_as_text (code), state->request);
1007 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_TRANSPORT,
1011 send_response (client, session, state->response);
1013 /* update the state */
1014 switch (media->state) {
1015 case GST_RTSP_STATE_PLAYING:
1016 case GST_RTSP_STATE_RECORDING:
1017 case GST_RTSP_STATE_READY:
1018 /* no state change */
1021 media->state = GST_RTSP_STATE_READY;
1024 g_object_unref (session);
1031 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
1036 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1037 g_object_unref (session);
1042 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1043 g_object_unref (media);
1044 g_object_unref (session);
1049 send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1052 unsupported_transports:
1054 send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1055 gst_rtsp_transport_free (ct);
1060 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1063 service_unavailable:
1065 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1070 static GstSDPMessage *
1071 create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
1077 gst_sdp_message_new (&sdp);
1079 /* some standard things first */
1080 gst_sdp_message_set_version (sdp, "0");
1082 if (client->is_ipv6)
1087 gst_sdp_message_set_origin (sdp, "-", "1188340656180883", "1", "IN", proto,
1090 gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer");
1091 gst_sdp_message_set_information (sdp, "rtsp-server");
1092 gst_sdp_message_add_time (sdp, "0", "0", NULL);
1093 gst_sdp_message_add_attribute (sdp, "tool", "GStreamer");
1094 gst_sdp_message_add_attribute (sdp, "type", "broadcast");
1095 gst_sdp_message_add_attribute (sdp, "control", "*");
1097 info.server_proto = proto;
1098 if (media->protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST)
1099 info.server_ip = g_strdup (MCAST_ADDRESS);
1101 info.server_ip = g_strdup (client->server_ip);
1103 /* create an SDP for the media object */
1104 if (!gst_rtsp_sdp_from_media (sdp, &info, media))
1107 g_free (info.server_ip);
1114 g_free (info.server_ip);
1115 gst_sdp_message_free (sdp);
1120 /* for the describe we must generate an SDP */
1122 handle_describe_request (GstRTSPClient * client, GstRTSPClientState * state)
1127 gchar *str, *content_base;
1128 GstRTSPMedia *media;
1130 /* check what kind of format is accepted, we don't really do anything with it
1131 * and always return SDP for now. */
1136 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_ACCEPT,
1138 if (res == GST_RTSP_ENOTIMPL)
1141 if (g_ascii_strcasecmp (accept, "application/sdp") == 0)
1145 /* find the media object for the uri */
1146 if (!(media = find_media (client, state)))
1149 /* create an SDP for the media object on this client */
1150 if (!(sdp = create_sdp (client, media)))
1153 g_object_unref (media);
1155 gst_rtsp_message_init_response (state->response, GST_RTSP_STS_OK,
1156 gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1158 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_TYPE,
1161 /* content base for some clients that might screw up creating the setup uri */
1162 str = gst_rtsp_url_get_request_uri (state->uri);
1163 str_len = strlen (str);
1165 /* check for trailing '/' and append one */
1166 if (str[str_len - 1] != '/') {
1167 content_base = g_malloc (str_len + 2);
1168 memcpy (content_base, str, str_len);
1169 content_base[str_len] = '/';
1170 content_base[str_len + 1] = '\0';
1176 GST_INFO ("adding content-base: %s", content_base);
1178 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_CONTENT_BASE,
1180 g_free (content_base);
1182 /* add SDP to the response body */
1183 str = gst_sdp_message_as_text (sdp);
1184 gst_rtsp_message_take_body (state->response, (guint8 *) str, strlen (str));
1185 gst_sdp_message_free (sdp);
1187 send_response (client, state->session, state->response);
1194 /* error reply is already sent */
1199 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1200 g_object_unref (media);
1206 handle_options_request (GstRTSPClient * client, GstRTSPClientState * state)
1208 GstRTSPMethod options;
1211 options = GST_RTSP_DESCRIBE |
1216 GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1218 str = gst_rtsp_options_as_text (options);
1220 gst_rtsp_message_init_response (state->response, GST_RTSP_STS_OK,
1221 gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1223 gst_rtsp_message_add_header (state->response, GST_RTSP_HDR_PUBLIC, str);
1226 send_response (client, state->session, state->response);
1231 /* remove duplicate and trailing '/' */
1233 sanitize_uri (GstRTSPUrl * uri)
1237 gboolean have_slash, prev_slash;
1239 s = d = uri->abspath;
1240 len = strlen (uri->abspath);
1244 for (i = 0; i < len; i++) {
1245 have_slash = s[i] == '/';
1247 if (!have_slash || !prev_slash)
1249 prev_slash = have_slash;
1251 len = d - uri->abspath;
1252 /* don't remove the first slash if that's the only thing left */
1253 if (len > 1 && *(d - 1) == '/')
1259 client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
1261 GST_INFO ("client %p: session %p finished", client, session);
1263 /* unlink all media managed in this session */
1264 client_unlink_session (client, session);
1266 /* remove the session */
1267 if (!(client->sessions = g_list_remove (client->sessions, session))) {
1268 GST_INFO ("client %p: all sessions finalized, close the connection",
1270 close_connection (client);
1275 client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
1279 for (walk = client->sessions; walk; walk = g_list_next (walk)) {
1280 GstRTSPSession *msession = (GstRTSPSession *) walk->data;
1282 /* we already know about this session */
1283 if (msession == session)
1287 GST_INFO ("watching session %p", session);
1289 g_object_weak_ref (G_OBJECT (session), (GWeakNotify) client_session_finalized,
1291 client->sessions = g_list_prepend (client->sessions, session);
1295 handle_request (GstRTSPClient * client, GstRTSPMessage * request)
1297 GstRTSPMethod method;
1298 const gchar *uristr;
1300 GstRTSPVersion version;
1302 GstRTSPSession *session;
1303 GstRTSPClientState state = { NULL };
1304 GstRTSPMessage response = { 0 };
1307 state.request = request;
1308 state.response = &response;
1310 if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
1311 gst_rtsp_message_dump (request);
1314 GST_INFO ("client %p: received a request", client);
1316 gst_rtsp_message_parse_request (request, &method, &uristr, &version);
1318 if (version != GST_RTSP_VERSION_1_0) {
1319 /* we can only handle 1.0 requests */
1320 send_generic_response (client, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED,
1324 state.method = method;
1326 /* we always try to parse the url first */
1327 if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) {
1328 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1332 /* sanitize the uri */
1336 /* get the session if there is any */
1337 res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0);
1338 if (res == GST_RTSP_OK) {
1339 if (client->session_pool == NULL)
1342 /* we had a session in the request, find it again */
1343 if (!(session = gst_rtsp_session_pool_find (client->session_pool, sessid)))
1344 goto session_not_found;
1346 /* we add the session to the client list of watched sessions. When a session
1347 * disappears because it times out, we will be notified. If all sessions are
1348 * gone, we will close the connection */
1349 client_watch_session (client, session);
1353 state.session = session;
1356 if (!gst_rtsp_auth_check (client->auth, client, &state))
1357 goto not_authorized;
1360 /* now see what is asked and dispatch to a dedicated handler */
1362 case GST_RTSP_OPTIONS:
1363 handle_options_request (client, &state);
1365 case GST_RTSP_DESCRIBE:
1366 handle_describe_request (client, &state);
1368 case GST_RTSP_SETUP:
1369 handle_setup_request (client, &state);
1372 handle_play_request (client, &state);
1374 case GST_RTSP_PAUSE:
1375 handle_pause_request (client, &state);
1377 case GST_RTSP_TEARDOWN:
1378 handle_teardown_request (client, &state);
1380 case GST_RTSP_SET_PARAMETER:
1381 handle_set_param_request (client, &state);
1383 case GST_RTSP_GET_PARAMETER:
1384 handle_get_param_request (client, &state);
1386 case GST_RTSP_ANNOUNCE:
1387 case GST_RTSP_RECORD:
1388 case GST_RTSP_REDIRECT:
1389 send_generic_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, &state);
1391 case GST_RTSP_INVALID:
1393 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1397 g_object_unref (session);
1399 gst_rtsp_url_free (uri);
1405 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, &state);
1410 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, &state);
1415 handle_unauthorized_request (client, client->auth, &state);
1421 handle_data (GstRTSPClient * client, GstRTSPMessage * message)
1431 /* find the stream for this message */
1432 res = gst_rtsp_message_parse_data (message, &channel);
1433 if (res != GST_RTSP_OK)
1436 gst_rtsp_message_steal_body (message, &data, &size);
1438 buffer = gst_buffer_new ();
1439 GST_BUFFER_DATA (buffer) = data;
1440 GST_BUFFER_MALLOCDATA (buffer) = data;
1441 GST_BUFFER_SIZE (buffer) = size;
1444 for (walk = client->streams; walk; walk = g_list_next (walk)) {
1445 GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
1446 GstRTSPMediaStream *mstream;
1447 GstRTSPTransport *tr;
1449 /* get the transport, if there is no transport configured, skip this stream */
1450 if (!(tr = stream->trans.transport))
1453 /* we also need a media stream */
1454 if (!(mstream = stream->media_stream))
1457 /* check for TCP transport */
1458 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
1459 /* dispatch to the stream based on the channel number */
1460 if (tr->interleaved.min == channel) {
1461 gst_rtsp_media_stream_rtp (mstream, buffer);
1464 } else if (tr->interleaved.max == channel) {
1465 gst_rtsp_media_stream_rtcp (mstream, buffer);
1472 gst_buffer_unref (buffer);
1476 * gst_rtsp_client_set_session_pool:
1477 * @client: a #GstRTSPClient
1478 * @pool: a #GstRTSPSessionPool
1480 * Set @pool as the sessionpool for @client which it will use to find
1481 * or allocate sessions. the sessionpool is usually inherited from the server
1482 * that created the client but can be overridden later.
1485 gst_rtsp_client_set_session_pool (GstRTSPClient * client,
1486 GstRTSPSessionPool * pool)
1488 GstRTSPSessionPool *old;
1490 old = client->session_pool;
1493 g_object_ref (pool);
1494 client->session_pool = pool;
1496 g_object_unref (old);
1501 * gst_rtsp_client_get_session_pool:
1502 * @client: a #GstRTSPClient
1504 * Get the #GstRTSPSessionPool object that @client uses to manage its sessions.
1506 * Returns: a #GstRTSPSessionPool, unref after usage.
1508 GstRTSPSessionPool *
1509 gst_rtsp_client_get_session_pool (GstRTSPClient * client)
1511 GstRTSPSessionPool *result;
1513 if ((result = client->session_pool))
1514 g_object_ref (result);
1520 * gst_rtsp_client_set_server:
1521 * @client: a #GstRTSPClient
1522 * @server: a #GstRTSPServer
1524 * Set @server as the server that created @client.
1527 gst_rtsp_client_set_server (GstRTSPClient * client, GstRTSPServer * server)
1531 old = client->server;
1532 if (old != server) {
1534 g_object_ref (server);
1535 client->server = server;
1537 g_object_unref (old);
1542 * gst_rtsp_client_get_server:
1543 * @client: a #GstRTSPClient
1545 * Get the #GstRTSPServer object that @client was created from.
1547 * Returns: a #GstRTSPServer, unref after usage.
1550 gst_rtsp_client_get_server (GstRTSPClient * client)
1552 GstRTSPServer *result;
1554 if ((result = client->server))
1555 g_object_ref (result);
1561 * gst_rtsp_client_set_media_mapping:
1562 * @client: a #GstRTSPClient
1563 * @mapping: a #GstRTSPMediaMapping
1565 * Set @mapping as the media mapping for @client which it will use to map urls
1566 * to media streams. These mapping is usually inherited from the server that
1567 * created the client but can be overriden later.
1570 gst_rtsp_client_set_media_mapping (GstRTSPClient * client,
1571 GstRTSPMediaMapping * mapping)
1573 GstRTSPMediaMapping *old;
1575 old = client->media_mapping;
1577 if (old != mapping) {
1579 g_object_ref (mapping);
1580 client->media_mapping = mapping;
1582 g_object_unref (old);
1587 * gst_rtsp_client_get_media_mapping:
1588 * @client: a #GstRTSPClient
1590 * Get the #GstRTSPMediaMapping object that @client uses to manage its sessions.
1592 * Returns: a #GstRTSPMediaMapping, unref after usage.
1594 GstRTSPMediaMapping *
1595 gst_rtsp_client_get_media_mapping (GstRTSPClient * client)
1597 GstRTSPMediaMapping *result;
1599 if ((result = client->media_mapping))
1600 g_object_ref (result);
1606 * gst_rtsp_client_set_auth:
1607 * @client: a #GstRTSPClient
1608 * @auth: a #GstRTSPAuth
1610 * configure @auth to be used as the authentication manager of @client.
1613 gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
1617 g_return_if_fail (GST_IS_RTSP_CLIENT (client));
1623 g_object_ref (auth);
1624 client->auth = auth;
1626 g_object_unref (old);
1632 * gst_rtsp_client_get_auth:
1633 * @client: a #GstRTSPClient
1635 * Get the #GstRTSPAuth used as the authentication manager of @client.
1637 * Returns: the #GstRTSPAuth of @client. g_object_unref() after
1641 gst_rtsp_client_get_auth (GstRTSPClient * client)
1643 GstRTSPAuth *result;
1645 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
1647 if ((result = client->auth))
1648 g_object_ref (result);
1653 static GstRTSPResult
1654 message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
1657 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1659 switch (message->type) {
1660 case GST_RTSP_MESSAGE_REQUEST:
1661 handle_request (client, message);
1663 case GST_RTSP_MESSAGE_RESPONSE:
1665 case GST_RTSP_MESSAGE_DATA:
1666 handle_data (client, message);
1674 static GstRTSPResult
1675 message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
1677 /* GstRTSPClient *client; */
1679 /* client = GST_RTSP_CLIENT (user_data); */
1681 /* GST_INFO ("client %p: sent a message with cseq %d", client, cseq); */
1686 static GstRTSPResult
1687 closed (GstRTSPWatch * watch, gpointer user_data)
1689 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1690 const gchar *tunnelid;
1692 GST_INFO ("client %p: connection closed", client);
1694 if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
1695 g_mutex_lock (tunnels_lock);
1696 /* remove from tunnelids */
1697 g_hash_table_remove (tunnels, tunnelid);
1698 g_mutex_unlock (tunnels_lock);
1704 static GstRTSPResult
1705 error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data)
1707 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1710 str = gst_rtsp_strresult (result);
1711 GST_INFO ("client %p: received an error %s", client, str);
1717 static GstRTSPResult
1718 error_full (GstRTSPWatch * watch, GstRTSPResult result,
1719 GstRTSPMessage * message, guint id, gpointer user_data)
1721 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1724 str = gst_rtsp_strresult (result);
1726 ("client %p: received an error %s when handling message %p with id %d",
1727 client, str, message, id);
1734 remember_tunnel (GstRTSPClient * client)
1736 const gchar *tunnelid;
1738 /* store client in the pending tunnels */
1739 tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
1740 if (tunnelid == NULL)
1743 GST_INFO ("client %p: inserting tunnel session %s", client, tunnelid);
1745 /* we can't have two clients connecting with the same tunnelid */
1746 g_mutex_lock (tunnels_lock);
1747 if (g_hash_table_lookup (tunnels, tunnelid))
1748 goto tunnel_existed;
1750 g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
1751 g_mutex_unlock (tunnels_lock);
1758 GST_ERROR ("client %p: no tunnelid provided", client);
1763 g_mutex_unlock (tunnels_lock);
1764 GST_ERROR ("client %p: tunnel session %s already existed", client,
1770 static GstRTSPStatusCode
1771 tunnel_start (GstRTSPWatch * watch, gpointer user_data)
1773 GstRTSPClient *client;
1775 client = GST_RTSP_CLIENT (user_data);
1777 GST_INFO ("client %p: tunnel start (connection %p)", client,
1778 client->connection);
1780 if (!remember_tunnel (client))
1783 return GST_RTSP_STS_OK;
1788 GST_ERROR ("client %p: error starting tunnel", client);
1789 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1793 static GstRTSPResult
1794 tunnel_lost (GstRTSPWatch * watch, gpointer user_data)
1796 GstRTSPClient *client;
1798 client = GST_RTSP_CLIENT (user_data);
1800 GST_INFO ("client %p: tunnel lost (connection %p)", client,
1801 client->connection);
1803 /* ignore error, it'll only be a problem when the client does a POST again */
1804 remember_tunnel (client);
1809 static GstRTSPResult
1810 tunnel_complete (GstRTSPWatch * watch, gpointer user_data)
1812 const gchar *tunnelid;
1813 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1814 GstRTSPClient *oclient;
1816 GST_INFO ("client %p: tunnel complete", client);
1818 /* find previous tunnel */
1819 tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
1820 if (tunnelid == NULL)
1823 g_mutex_lock (tunnels_lock);
1824 if (!(oclient = g_hash_table_lookup (tunnels, tunnelid)))
1827 /* remove the old client from the table. ref before because removing it will
1828 * remove the ref to it. */
1829 g_object_ref (oclient);
1830 g_hash_table_remove (tunnels, tunnelid);
1832 if (oclient->watch == NULL)
1834 g_mutex_unlock (tunnels_lock);
1836 GST_INFO ("client %p: found tunnel %p (old %p, new %p)", client, oclient,
1837 oclient->connection, client->connection);
1839 /* merge the tunnels into the first client */
1840 gst_rtsp_connection_do_tunnel (oclient->connection, client->connection);
1841 gst_rtsp_watch_reset (oclient->watch);
1842 g_object_unref (oclient);
1844 /* we don't need this watch anymore */
1845 g_source_destroy ((GSource *) client->watch);
1846 client->watchid = 0;
1847 client->watch = NULL;
1854 GST_INFO ("client %p: no tunnelid provided", client);
1855 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1859 g_mutex_unlock (tunnels_lock);
1860 GST_INFO ("client %p: tunnel session %s not found", client, tunnelid);
1861 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1865 g_mutex_unlock (tunnels_lock);
1866 GST_INFO ("client %p: tunnel session %s was closed", client, tunnelid);
1867 g_object_unref (oclient);
1868 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1872 static GstRTSPWatchFuncs watch_funcs = {
1884 client_watch_notify (GstRTSPClient * client)
1886 GST_INFO ("client %p: watch destroyed", client);
1887 client->watchid = 0;
1888 client->watch = NULL;
1889 g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
1890 g_object_unref (client);
1894 * gst_rtsp_client_attach:
1895 * @client: a #GstRTSPClient
1896 * @channel: a #GIOChannel
1898 * Accept a new connection for @client on the socket in @channel.
1900 * This function should be called when the client properties and urls are fully
1901 * configured and the client is ready to start.
1903 * Returns: %TRUE if the client could be accepted.
1906 gst_rtsp_client_accept (GstRTSPClient * client, GIOChannel * channel)
1909 GstRTSPConnection *conn;
1912 GMainContext *context;
1914 struct sockaddr_storage addr;
1916 gchar ip[INET6_ADDRSTRLEN];
1918 /* a new client connected. */
1919 sock = g_io_channel_unix_get_fd (channel);
1921 GST_RTSP_CHECK (gst_rtsp_connection_accept (sock, &conn), accept_failed);
1923 fd = gst_rtsp_connection_get_readfd (conn);
1925 addrlen = sizeof (addr);
1926 if (getsockname (fd, (struct sockaddr *) &addr, &addrlen) < 0)
1927 goto getpeername_failed;
1929 client->is_ipv6 = addr.ss_family == AF_INET6;
1931 if (getnameinfo ((struct sockaddr *) &addr, addrlen, ip, sizeof (ip), NULL, 0,
1932 NI_NUMERICHOST) != 0)
1933 goto getnameinfo_failed;
1935 /* keep the original ip that the client connected to */
1936 g_free (client->server_ip);
1937 client->server_ip = g_strndup (ip, sizeof (ip));
1939 GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
1940 client->server_ip, client->is_ipv6);
1942 url = gst_rtsp_connection_get_url (conn);
1943 GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
1945 client->connection = conn;
1947 /* create watch for the connection and attach */
1948 client->watch = gst_rtsp_watch_new (client->connection, &watch_funcs,
1949 g_object_ref (client), (GDestroyNotify) client_watch_notify);
1951 /* find the context to add the watch */
1952 if ((source = g_main_current_source ()))
1953 context = g_source_get_context (source);
1957 GST_INFO ("attaching to context %p", context);
1959 client->watchid = gst_rtsp_watch_attach (client->watch, context);
1960 gst_rtsp_watch_unref (client->watch);
1967 gchar *str = gst_rtsp_strresult (res);
1969 GST_ERROR ("Could not accept client on server socket %d: %s", sock, str);
1975 GST_ERROR ("getpeername failed: %s", g_strerror (errno));
1980 GST_ERROR ("getnameinfo failed: %s", g_strerror (errno));