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 unlink_session_streams (client, session,
125 (GstRTSPSessionMedia *) medias->data);
130 client_cleanup_sessions (GstRTSPClient * client)
134 /* remove weak-ref from sessions */
135 for (sessions = client->sessions; sessions; sessions = g_list_next (sessions)) {
136 GstRTSPSession *session = (GstRTSPSession *) sessions->data;
137 g_object_weak_unref (G_OBJECT (session),
138 (GWeakNotify) client_session_finalized, client);
139 client_unlink_session (client, session);
141 g_list_free (client->sessions);
142 client->sessions = NULL;
145 /* A client is finalized when the connection is broken */
147 gst_rtsp_client_finalize (GObject * obj)
149 GstRTSPClient *client = GST_RTSP_CLIENT (obj);
151 GST_INFO ("finalize client %p", client);
153 client_cleanup_sessions (client);
155 gst_rtsp_connection_free (client->connection);
156 if (client->session_pool)
157 g_object_unref (client->session_pool);
158 if (client->media_mapping)
159 g_object_unref (client->media_mapping);
161 g_object_unref (client->auth);
164 gst_rtsp_url_free (client->uri);
166 g_object_unref (client->media);
168 g_free (client->server_ip);
170 G_OBJECT_CLASS (gst_rtsp_client_parent_class)->finalize (obj);
174 gst_rtsp_client_get_property (GObject * object, guint propid,
175 GValue * value, GParamSpec * pspec)
177 GstRTSPClient *client = GST_RTSP_CLIENT (object);
180 case PROP_SESSION_POOL:
181 g_value_take_object (value, gst_rtsp_client_get_session_pool (client));
183 case PROP_MEDIA_MAPPING:
184 g_value_take_object (value, gst_rtsp_client_get_media_mapping (client));
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
192 gst_rtsp_client_set_property (GObject * object, guint propid,
193 const GValue * value, GParamSpec * pspec)
195 GstRTSPClient *client = GST_RTSP_CLIENT (object);
198 case PROP_SESSION_POOL:
199 gst_rtsp_client_set_session_pool (client, g_value_get_object (value));
201 case PROP_MEDIA_MAPPING:
202 gst_rtsp_client_set_media_mapping (client, g_value_get_object (value));
205 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
210 * gst_rtsp_client_new:
212 * Create a new #GstRTSPClient instance.
214 * Returns: a new #GstRTSPClient
217 gst_rtsp_client_new (void)
219 GstRTSPClient *result;
221 result = g_object_new (GST_TYPE_RTSP_CLIENT, NULL);
227 send_response (GstRTSPClient * client, GstRTSPSession * session,
228 GstRTSPMessage * response)
230 gst_rtsp_message_add_header (response, GST_RTSP_HDR_SERVER,
231 "GStreamer RTSP server");
233 /* remove any previous header */
234 gst_rtsp_message_remove_header (response, GST_RTSP_HDR_SESSION, -1);
236 /* add the new session header for new session ids */
240 if (session->timeout != 60)
242 g_strdup_printf ("%s; timeout=%d", session->sessionid,
245 str = g_strdup (session->sessionid);
247 gst_rtsp_message_take_header (response, GST_RTSP_HDR_SESSION, str);
250 if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
251 gst_rtsp_message_dump (response);
254 gst_rtsp_watch_send_message (client->watch, response, NULL);
255 gst_rtsp_message_unset (response);
259 send_generic_response (GstRTSPClient * client, GstRTSPStatusCode code,
260 GstRTSPClientState * state)
262 GstRTSPMessage response = { 0 };
264 gst_rtsp_message_init_response (&response, code,
265 gst_rtsp_status_as_text (code), state->request);
267 send_response (client, NULL, &response);
271 handle_unauthorized_request (GstRTSPClient * client, GstRTSPAuth * auth,
272 GstRTSPClientState * state)
274 GstRTSPMessage response = { 0 };
276 gst_rtsp_message_init_response (&response, GST_RTSP_STS_UNAUTHORIZED,
277 gst_rtsp_status_as_text (GST_RTSP_STS_UNAUTHORIZED), state->request);
279 state->response = &response;
282 /* and let the authentication manager setup the auth tokens */
283 gst_rtsp_auth_setup_auth (auth, client, 0, state);
286 send_response (client, state->session, &response);
291 compare_uri (const GstRTSPUrl * uri1, const GstRTSPUrl * uri2)
293 if (uri1 == NULL || uri2 == NULL)
296 if (strcmp (uri1->abspath, uri2->abspath))
302 /* this function is called to initially find the media for the DESCRIBE request
303 * but is cached for when the same client (without breaking the connection) is
304 * doing a setup for the exact same url. */
305 static GstRTSPMedia *
306 find_media (GstRTSPClient * client, GstRTSPClientState * state)
308 GstRTSPMediaFactory *factory;
312 if (!compare_uri (client->uri, state->uri)) {
313 /* remove any previously cached values before we try to construct a new
316 gst_rtsp_url_free (client->uri);
319 g_object_unref (client->media);
320 client->media = NULL;
322 if (!client->media_mapping)
325 /* find the factory for the uri first */
327 gst_rtsp_media_mapping_find_factory (client->media_mapping,
331 state->factory = factory;
333 /* check if we have access to the factory */
334 if ((auth = gst_rtsp_media_factory_get_auth (factory))) {
335 if (!gst_rtsp_auth_check (auth, client, 0, state))
338 g_object_unref (auth);
341 /* prepare the media and add it to the pipeline */
342 if (!(media = gst_rtsp_media_factory_construct (factory, state->uri)))
345 g_object_unref (factory);
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);
398 g_object_unref (factory);
404 do_send_data (GstBuffer * buffer, guint8 channel, GstRTSPClient * client)
406 GstRTSPMessage message = { 0 };
410 gst_rtsp_message_init_data (&message, channel);
412 data = GST_BUFFER_DATA (buffer);
413 size = GST_BUFFER_SIZE (buffer);
414 gst_rtsp_message_take_body (&message, data, size);
416 /* FIXME, client->watch could have been finalized here, we need to keep an
417 * extra refcount to the watch. */
418 gst_rtsp_watch_send_message (client->watch, &message, NULL);
420 gst_rtsp_message_steal_body (&message, &data, &size);
421 gst_rtsp_message_unset (&message);
427 do_send_data_list (GstBufferList * blist, guint8 channel,
428 GstRTSPClient * client)
430 GstBufferListIterator *it;
432 it = gst_buffer_list_iterate (blist);
433 while (gst_buffer_list_iterator_next_group (it)) {
434 GstBuffer *group = gst_buffer_list_iterator_merge_group (it);
439 do_send_data (group, channel, client);
441 gst_buffer_list_iterator_free (it);
447 link_stream (GstRTSPClient * client, GstRTSPSession * session,
448 GstRTSPSessionStream * stream)
450 GST_DEBUG ("client %p: linking stream %p", client, stream);
451 gst_rtsp_session_stream_set_callbacks (stream, (GstRTSPSendFunc) do_send_data,
452 (GstRTSPSendFunc) do_send_data, (GstRTSPSendListFunc) do_send_data_list,
453 (GstRTSPSendListFunc) do_send_data_list, client, NULL);
454 client->streams = g_list_prepend (client->streams, stream);
455 /* make sure our session can't expire */
456 gst_rtsp_session_prevent_expire (session);
460 unlink_stream (GstRTSPClient * client, GstRTSPSession * session,
461 GstRTSPSessionStream * stream)
463 GST_DEBUG ("client %p: unlinking stream %p", client, stream);
464 gst_rtsp_session_stream_set_callbacks (stream, NULL, NULL, NULL, NULL, NULL,
466 client->streams = g_list_remove (client->streams, stream);
467 /* our session can now expire */
468 gst_rtsp_session_allow_expire (session);
472 unlink_session_streams (GstRTSPClient * client, GstRTSPSession * session,
473 GstRTSPSessionMedia * media)
477 n_streams = gst_rtsp_media_n_streams (media->media);
478 for (i = 0; i < n_streams; i++) {
479 GstRTSPSessionStream *sstream;
480 GstRTSPTransport *tr;
482 /* get the stream as configured in the session */
483 sstream = gst_rtsp_session_media_get_stream (media, i);
484 /* get the transport, if there is no transport configured, skip this stream */
485 if (!(tr = sstream->trans.transport))
488 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
489 /* for TCP, unlink the stream from the TCP connection of the client */
490 unlink_stream (client, session, sstream);
496 close_connection (GstRTSPClient * client)
498 const gchar *tunnelid;
500 GST_DEBUG ("client %p: closing connection", client);
502 if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
503 g_mutex_lock (tunnels_lock);
504 /* remove from tunnelids */
505 g_hash_table_remove (tunnels, tunnelid);
506 g_mutex_unlock (tunnels_lock);
509 gst_rtsp_connection_close (client->connection);
510 if (client->watchid) {
511 g_source_destroy ((GSource *) client->watch);
513 client->watch = NULL;
518 handle_teardown_request (GstRTSPClient * client, GstRTSPClientState * state)
520 GstRTSPSession *session;
521 GstRTSPSessionMedia *media;
522 GstRTSPMessage response = { 0 };
523 GstRTSPStatusCode code;
528 session = state->session;
530 /* get a handle to the configuration of the media in the session */
531 media = gst_rtsp_session_get_media (session, state->uri);
535 state->sessmedia = media;
537 /* unlink the all TCP callbacks */
538 unlink_session_streams (client, session, media);
540 /* remove the session from the watched sessions */
541 g_object_weak_unref (G_OBJECT (session),
542 (GWeakNotify) client_session_finalized, client);
543 client->sessions = g_list_remove (client->sessions, session);
545 gst_rtsp_session_media_set_state (media, GST_STATE_NULL);
547 /* unmanage the media in the session, returns false if all media session
549 if (!gst_rtsp_session_release_media (session, media)) {
550 /* remove the session */
551 gst_rtsp_session_pool_remove (client->session_pool, session);
553 /* construct the response now */
554 code = GST_RTSP_STS_OK;
555 gst_rtsp_message_init_response (&response, code,
556 gst_rtsp_status_as_text (code), state->request);
558 gst_rtsp_message_add_header (&response, GST_RTSP_HDR_CONNECTION, "close");
560 send_response (client, session, &response);
562 close_connection (client);
569 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
574 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
580 handle_get_param_request (GstRTSPClient * client, GstRTSPClientState * state)
586 res = gst_rtsp_message_get_body (state->request, &data, &size);
587 if (res != GST_RTSP_OK)
591 /* no body, keep-alive request */
592 send_generic_response (client, GST_RTSP_STS_OK, state);
594 /* there is a body */
595 GstRTSPMessage response = { 0 };
597 state->response = &response;
599 /* there is a body, handle the params */
600 res = gst_rtsp_params_get (client, state);
601 if (res != GST_RTSP_OK)
604 send_response (client, state->session, &response);
611 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
617 handle_set_param_request (GstRTSPClient * client, GstRTSPClientState * state)
623 res = gst_rtsp_message_get_body (state->request, &data, &size);
624 if (res != GST_RTSP_OK)
628 /* no body, keep-alive request */
629 send_generic_response (client, GST_RTSP_STS_OK, state);
631 GstRTSPMessage response = { 0 };
633 state->response = &response;
635 /* there is a body, handle the params */
636 res = gst_rtsp_params_set (client, state);
637 if (res != GST_RTSP_OK)
640 send_response (client, state->session, &response);
647 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
653 handle_pause_request (GstRTSPClient * client, GstRTSPClientState * state)
655 GstRTSPSession *session;
656 GstRTSPSessionMedia *media;
657 GstRTSPMessage response = { 0 };
658 GstRTSPStatusCode code;
660 if (!(session = state->session))
663 /* get a handle to the configuration of the media in the session */
664 media = gst_rtsp_session_get_media (session, state->uri);
668 state->sessmedia = media;
670 /* the session state must be playing or recording */
671 if (media->state != GST_RTSP_STATE_PLAYING &&
672 media->state != GST_RTSP_STATE_RECORDING)
675 /* unlink the all TCP callbacks */
676 unlink_session_streams (client, session, media);
678 /* then pause sending */
679 gst_rtsp_session_media_set_state (media, GST_STATE_PAUSED);
681 /* construct the response now */
682 code = GST_RTSP_STS_OK;
683 gst_rtsp_message_init_response (&response, code,
684 gst_rtsp_status_as_text (code), state->request);
686 send_response (client, session, &response);
688 /* the state is now READY */
689 media->state = GST_RTSP_STATE_READY;
696 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
701 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
706 send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
713 handle_play_request (GstRTSPClient * client, GstRTSPClientState * state)
715 GstRTSPSession *session;
716 GstRTSPSessionMedia *media;
717 GstRTSPMessage response = { 0 };
718 GstRTSPStatusCode code;
720 guint n_streams, i, infocount;
721 guint timestamp, seqnum;
723 GstRTSPTimeRange *range;
726 if (!(session = state->session))
729 /* get a handle to the configuration of the media in the session */
730 media = gst_rtsp_session_get_media (session, state->uri);
734 state->sessmedia = media;
736 /* the session state must be playing or ready */
737 if (media->state != GST_RTSP_STATE_PLAYING &&
738 media->state != GST_RTSP_STATE_READY)
741 /* parse the range header if we have one */
743 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_RANGE, &str, 0);
744 if (res == GST_RTSP_OK) {
745 if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
746 /* we have a range, seek to the position */
747 gst_rtsp_media_seek (media->media, range);
748 gst_rtsp_range_free (range);
752 /* grab RTPInfo from the payloaders now */
753 rtpinfo = g_string_new ("");
755 n_streams = gst_rtsp_media_n_streams (media->media);
756 for (i = 0, infocount = 0; i < n_streams; i++) {
757 GstRTSPSessionStream *sstream;
758 GstRTSPMediaStream *stream;
759 GstRTSPTransport *tr;
760 GObjectClass *payobjclass;
763 /* get the stream as configured in the session */
764 sstream = gst_rtsp_session_media_get_stream (media, i);
765 /* get the transport, if there is no transport configured, skip this stream */
766 if (!(tr = sstream->trans.transport)) {
767 GST_INFO ("stream %d is not configured", i);
771 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
772 /* for TCP, link the stream to the TCP connection of the client */
773 link_stream (client, session, sstream);
776 stream = sstream->media_stream;
778 payobjclass = G_OBJECT_GET_CLASS (stream->payloader);
780 if (g_object_class_find_property (payobjclass, "seqnum") &&
781 g_object_class_find_property (payobjclass, "timestamp")) {
784 payobj = G_OBJECT (stream->payloader);
786 /* only add RTP-Info for streams with seqnum and timestamp */
787 g_object_get (payobj, "seqnum", &seqnum, "timestamp", ×tamp, NULL);
790 g_string_append (rtpinfo, ", ");
792 uristr = gst_rtsp_url_get_request_uri (state->uri);
793 g_string_append_printf (rtpinfo, "url=%s/stream=%d;seq=%u;rtptime=%u",
794 uristr, i, seqnum, timestamp);
799 GST_WARNING ("RTP-Info cannot be determined for stream %d", i);
803 /* construct the response now */
804 code = GST_RTSP_STS_OK;
805 gst_rtsp_message_init_response (&response, code,
806 gst_rtsp_status_as_text (code), state->request);
808 /* add the RTP-Info header */
810 str = g_string_free (rtpinfo, FALSE);
811 gst_rtsp_message_take_header (&response, GST_RTSP_HDR_RTP_INFO, str);
813 g_string_free (rtpinfo, TRUE);
817 str = gst_rtsp_media_get_range_string (media->media, TRUE);
818 gst_rtsp_message_take_header (&response, GST_RTSP_HDR_RANGE, str);
820 send_response (client, session, &response);
822 /* start playing after sending the request */
823 gst_rtsp_session_media_set_state (media, GST_STATE_PLAYING);
825 media->state = GST_RTSP_STATE_PLAYING;
832 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, state);
837 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
842 send_generic_response (client, GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
849 do_keepalive (GstRTSPSession * session)
851 GST_INFO ("keep session %p alive", session);
852 gst_rtsp_session_touch (session);
856 handle_setup_request (GstRTSPClient * client, GstRTSPClientState * state)
862 gboolean have_transport;
863 GstRTSPTransport *ct, *st;
865 GstRTSPLowerTrans supported;
866 GstRTSPMessage response = { 0 };
867 GstRTSPStatusCode code;
868 GstRTSPSession *session;
869 GstRTSPSessionStream *stream;
870 gchar *trans_str, *pos;
872 GstRTSPSessionMedia *media;
877 /* the uri contains the stream number we added in the SDP config, which is
878 * always /stream=%d so we need to strip that off
879 * parse the stream we need to configure, look for the stream in the abspath
880 * first and then in the query. */
881 if (uri->abspath == NULL || !(pos = strstr (uri->abspath, "/stream="))) {
882 if (uri->query == NULL || !(pos = strstr (uri->query, "/stream=")))
886 /* we can mofify the parse uri in place */
889 pos += strlen ("/stream=");
890 if (sscanf (pos, "%u", &streamid) != 1)
893 /* parse the transport */
895 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_TRANSPORT,
897 if (res != GST_RTSP_OK)
900 transports = g_strsplit (transport, ",", 0);
901 gst_rtsp_transport_new (&ct);
903 /* init transports */
904 have_transport = FALSE;
905 gst_rtsp_transport_init (ct);
907 /* our supported transports */
908 supported = GST_RTSP_LOWER_TRANS_UDP |
909 GST_RTSP_LOWER_TRANS_UDP_MCAST | GST_RTSP_LOWER_TRANS_TCP;
911 /* loop through the transports, try to parse */
912 for (i = 0; transports[i]; i++) {
913 res = gst_rtsp_transport_parse (transports[i], ct);
914 if (res != GST_RTSP_OK) {
915 /* no valid transport, search some more */
916 GST_WARNING ("could not parse transport %s", transports[i]);
920 /* we have a transport, see if it's RTP/AVP */
921 if (ct->trans != GST_RTSP_TRANS_RTP || ct->profile != GST_RTSP_PROFILE_AVP) {
922 GST_WARNING ("invalid transport %s", transports[i]);
926 if (!(ct->lower_transport & supported)) {
927 GST_WARNING ("unsupported transport %s", transports[i]);
931 /* we have a valid transport */
932 GST_INFO ("found valid transport %s", transports[i]);
933 have_transport = TRUE;
937 gst_rtsp_transport_init (ct);
939 g_strfreev (transports);
941 /* we have not found anything usable, error out */
943 goto unsupported_transports;
945 if (client->session_pool == NULL)
948 /* we have a valid transport now, set the destination of the client. */
949 g_free (ct->destination);
950 if (ct->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) {
951 ct->destination = g_strdup (MCAST_ADDRESS);
953 url = gst_rtsp_connection_get_url (client->connection);
954 ct->destination = g_strdup (url->host);
957 session = state->session;
960 g_object_ref (session);
961 /* get a handle to the configuration of the media in the session, this can
962 * return NULL if this is a new url to manage in this session. */
963 media = gst_rtsp_session_get_media (session, uri);
965 /* create a session if this fails we probably reached our session limit or
967 if (!(session = gst_rtsp_session_pool_create (client->session_pool)))
968 goto service_unavailable;
970 state->session = session;
972 /* we need a new media configuration in this session */
976 /* we have no media, find one and manage it */
980 /* get a handle to the configuration of the media in the session */
981 if ((m = find_media (client, state))) {
982 /* manage the media in our session now */
983 media = gst_rtsp_session_manage_media (session, uri, m);
987 /* if we stil have no media, error */
991 state->sessmedia = media;
993 /* fix the transports */
994 if (ct->lower_transport & GST_RTSP_LOWER_TRANS_TCP) {
995 /* check if the client selected channels for TCP */
996 if (ct->interleaved.min == -1 || ct->interleaved.max == -1) {
997 gst_rtsp_session_media_alloc_channels (media, &ct->interleaved);
1001 /* get a handle to the stream in the media */
1002 if (!(stream = gst_rtsp_session_media_get_stream (media, streamid)))
1005 st = gst_rtsp_session_stream_set_transport (stream, ct);
1007 /* configure keepalive for this transport */
1008 gst_rtsp_session_stream_set_keepalive (stream,
1009 (GstRTSPKeepAliveFunc) do_keepalive, session, NULL);
1011 /* serialize the server transport */
1012 trans_str = gst_rtsp_transport_as_text (st);
1013 gst_rtsp_transport_free (st);
1015 /* construct the response now */
1016 code = GST_RTSP_STS_OK;
1017 gst_rtsp_message_init_response (&response, code,
1018 gst_rtsp_status_as_text (code), state->request);
1020 gst_rtsp_message_add_header (&response, GST_RTSP_HDR_TRANSPORT, trans_str);
1023 send_response (client, session, &response);
1025 /* update the state */
1026 switch (media->state) {
1027 case GST_RTSP_STATE_PLAYING:
1028 case GST_RTSP_STATE_RECORDING:
1029 case GST_RTSP_STATE_READY:
1030 /* no state change */
1033 media->state = GST_RTSP_STATE_READY;
1036 g_object_unref (session);
1043 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, state);
1048 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1049 g_object_unref (session);
1054 send_generic_response (client, GST_RTSP_STS_NOT_FOUND, state);
1055 g_object_unref (media);
1056 g_object_unref (session);
1061 send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1064 unsupported_transports:
1066 send_generic_response (client, GST_RTSP_STS_UNSUPPORTED_TRANSPORT, state);
1067 gst_rtsp_transport_free (ct);
1072 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1075 service_unavailable:
1077 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1082 static GstSDPMessage *
1083 create_sdp (GstRTSPClient * client, GstRTSPMedia * media)
1089 gst_sdp_message_new (&sdp);
1091 /* some standard things first */
1092 gst_sdp_message_set_version (sdp, "0");
1094 if (client->is_ipv6)
1099 gst_sdp_message_set_origin (sdp, "-", "1188340656180883", "1", "IN", proto,
1102 gst_sdp_message_set_session_name (sdp, "Session streamed with GStreamer");
1103 gst_sdp_message_set_information (sdp, "rtsp-server");
1104 gst_sdp_message_add_time (sdp, "0", "0", NULL);
1105 gst_sdp_message_add_attribute (sdp, "tool", "GStreamer");
1106 gst_sdp_message_add_attribute (sdp, "type", "broadcast");
1107 gst_sdp_message_add_attribute (sdp, "control", "*");
1109 info.server_proto = proto;
1110 if (media->protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST)
1111 info.server_ip = MCAST_ADDRESS;
1113 info.server_ip = client->server_ip;
1115 /* create an SDP for the media object */
1116 if (!gst_rtsp_sdp_from_media (sdp, &info, media))
1124 gst_sdp_message_free (sdp);
1129 /* for the describe we must generate an SDP */
1131 handle_describe_request (GstRTSPClient * client, GstRTSPClientState * state)
1133 GstRTSPMessage response = { 0 };
1137 gchar *str, *content_base;
1138 GstRTSPMedia *media;
1140 /* check what kind of format is accepted, we don't really do anything with it
1141 * and always return SDP for now. */
1146 gst_rtsp_message_get_header (state->request, GST_RTSP_HDR_ACCEPT,
1148 if (res == GST_RTSP_ENOTIMPL)
1151 if (g_ascii_strcasecmp (accept, "application/sdp") == 0)
1155 /* find the media object for the uri */
1156 if (!(media = find_media (client, state)))
1159 /* create an SDP for the media object on this client */
1160 if (!(sdp = create_sdp (client, media)))
1163 g_object_unref (media);
1165 gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK,
1166 gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1168 gst_rtsp_message_add_header (&response, GST_RTSP_HDR_CONTENT_TYPE,
1171 /* content base for some clients that might screw up creating the setup uri */
1172 str = gst_rtsp_url_get_request_uri (state->uri);
1173 str_len = strlen (str);
1175 /* check for trailing '/' and append one */
1176 if (str[str_len - 1] != '/') {
1177 content_base = g_malloc (str_len + 2);
1178 memcpy (content_base, str, str_len);
1179 content_base[str_len] = '/';
1180 content_base[str_len + 1] = '\0';
1186 GST_INFO ("adding content-base: %s", content_base);
1188 gst_rtsp_message_add_header (&response, GST_RTSP_HDR_CONTENT_BASE,
1190 g_free (content_base);
1192 /* add SDP to the response body */
1193 str = gst_sdp_message_as_text (sdp);
1194 gst_rtsp_message_take_body (&response, (guint8 *) str, strlen (str));
1195 gst_sdp_message_free (sdp);
1197 send_response (client, state->session, &response);
1204 /* error reply is already sent */
1209 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, state);
1210 g_object_unref (media);
1216 handle_options_request (GstRTSPClient * client, GstRTSPClientState * state)
1218 GstRTSPMessage response = { 0 };
1219 GstRTSPMethod options;
1222 options = GST_RTSP_DESCRIBE |
1227 GST_RTSP_GET_PARAMETER | GST_RTSP_SET_PARAMETER | GST_RTSP_TEARDOWN;
1229 str = gst_rtsp_options_as_text (options);
1231 gst_rtsp_message_init_response (&response, GST_RTSP_STS_OK,
1232 gst_rtsp_status_as_text (GST_RTSP_STS_OK), state->request);
1234 gst_rtsp_message_add_header (&response, GST_RTSP_HDR_PUBLIC, str);
1237 send_response (client, state->session, &response);
1242 /* remove duplicate and trailing '/' */
1244 sanitize_uri (GstRTSPUrl * uri)
1248 gboolean have_slash, prev_slash;
1250 s = d = uri->abspath;
1251 len = strlen (uri->abspath);
1255 for (i = 0; i < len; i++) {
1256 have_slash = s[i] == '/';
1258 if (!have_slash || !prev_slash)
1260 prev_slash = have_slash;
1262 len = d - uri->abspath;
1263 /* don't remove the first slash if that's the only thing left */
1264 if (len > 1 && *(d - 1) == '/')
1270 client_session_finalized (GstRTSPClient * client, GstRTSPSession * session)
1272 GST_INFO ("client %p: session %p finished", client, session);
1274 /* unlink all media managed in this session */
1275 client_unlink_session (client, session);
1277 /* remove the session */
1278 if (!(client->sessions = g_list_remove (client->sessions, session))) {
1279 GST_INFO ("client %p: all sessions finalized, close the connection",
1281 close_connection (client);
1286 client_watch_session (GstRTSPClient * client, GstRTSPSession * session)
1290 for (walk = client->sessions; walk; walk = g_list_next (walk)) {
1291 GstRTSPSession *msession = (GstRTSPSession *) walk->data;
1293 /* we already know about this session */
1294 if (msession == session)
1298 GST_INFO ("watching session %p", session);
1300 g_object_weak_ref (G_OBJECT (session), (GWeakNotify) client_session_finalized,
1302 client->sessions = g_list_prepend (client->sessions, session);
1306 handle_request (GstRTSPClient * client, GstRTSPMessage * request)
1308 GstRTSPMethod method;
1309 const gchar *uristr;
1311 GstRTSPVersion version;
1313 GstRTSPSession *session;
1314 GstRTSPClientState state = { NULL };
1317 state.request = request;
1319 if (gst_debug_category_get_threshold (rtsp_client_debug) >= GST_LEVEL_LOG) {
1320 gst_rtsp_message_dump (request);
1323 GST_INFO ("client %p: received a request", client);
1325 gst_rtsp_message_parse_request (request, &method, &uristr, &version);
1327 if (version != GST_RTSP_VERSION_1_0) {
1328 /* we can only handle 1.0 requests */
1329 send_generic_response (client, GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED,
1333 state.method = method;
1335 /* we always try to parse the url first */
1336 if (gst_rtsp_url_parse (uristr, &uri) != GST_RTSP_OK) {
1337 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1341 /* sanitize the uri */
1345 /* get the session if there is any */
1346 res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &sessid, 0);
1347 if (res == GST_RTSP_OK) {
1348 if (client->session_pool == NULL)
1351 /* we had a session in the request, find it again */
1352 if (!(session = gst_rtsp_session_pool_find (client->session_pool, sessid)))
1353 goto session_not_found;
1355 /* we add the session to the client list of watched sessions. When a session
1356 * disappears because it times out, we will be notified. If all sessions are
1357 * gone, we will close the connection */
1358 client_watch_session (client, session);
1362 state.session = session;
1365 if (!gst_rtsp_auth_check (client->auth, client, &state))
1366 goto not_authorized;
1369 /* now see what is asked and dispatch to a dedicated handler */
1371 case GST_RTSP_OPTIONS:
1372 handle_options_request (client, &state);
1374 case GST_RTSP_DESCRIBE:
1375 handle_describe_request (client, &state);
1377 case GST_RTSP_SETUP:
1378 handle_setup_request (client, &state);
1381 handle_play_request (client, &state);
1383 case GST_RTSP_PAUSE:
1384 handle_pause_request (client, &state);
1386 case GST_RTSP_TEARDOWN:
1387 handle_teardown_request (client, &state);
1389 case GST_RTSP_SET_PARAMETER:
1390 handle_set_param_request (client, &state);
1392 case GST_RTSP_GET_PARAMETER:
1393 handle_get_param_request (client, &state);
1395 case GST_RTSP_ANNOUNCE:
1396 case GST_RTSP_RECORD:
1397 case GST_RTSP_REDIRECT:
1398 send_generic_response (client, GST_RTSP_STS_NOT_IMPLEMENTED, &state);
1400 case GST_RTSP_INVALID:
1402 send_generic_response (client, GST_RTSP_STS_BAD_REQUEST, &state);
1406 g_object_unref (session);
1408 gst_rtsp_url_free (uri);
1414 send_generic_response (client, GST_RTSP_STS_SERVICE_UNAVAILABLE, &state);
1419 send_generic_response (client, GST_RTSP_STS_SESSION_NOT_FOUND, &state);
1424 handle_unauthorized_request (client, client->auth, &state);
1430 handle_data (GstRTSPClient * client, GstRTSPMessage * message)
1440 /* find the stream for this message */
1441 res = gst_rtsp_message_parse_data (message, &channel);
1442 if (res != GST_RTSP_OK)
1445 gst_rtsp_message_steal_body (message, &data, &size);
1447 buffer = gst_buffer_new ();
1448 GST_BUFFER_DATA (buffer) = data;
1449 GST_BUFFER_MALLOCDATA (buffer) = data;
1450 GST_BUFFER_SIZE (buffer) = size;
1453 for (walk = client->streams; walk; walk = g_list_next (walk)) {
1454 GstRTSPSessionStream *stream = (GstRTSPSessionStream *) walk->data;
1455 GstRTSPMediaStream *mstream;
1456 GstRTSPTransport *tr;
1458 /* get the transport, if there is no transport configured, skip this stream */
1459 if (!(tr = stream->trans.transport))
1462 /* we also need a media stream */
1463 if (!(mstream = stream->media_stream))
1466 /* check for TCP transport */
1467 if (tr->lower_transport == GST_RTSP_LOWER_TRANS_TCP) {
1468 /* dispatch to the stream based on the channel number */
1469 if (tr->interleaved.min == channel) {
1470 gst_rtsp_media_stream_rtp (mstream, buffer);
1473 } else if (tr->interleaved.max == channel) {
1474 gst_rtsp_media_stream_rtcp (mstream, buffer);
1481 gst_buffer_unref (buffer);
1485 * gst_rtsp_client_set_session_pool:
1486 * @client: a #GstRTSPClient
1487 * @pool: a #GstRTSPSessionPool
1489 * Set @pool as the sessionpool for @client which it will use to find
1490 * or allocate sessions. the sessionpool is usually inherited from the server
1491 * that created the client but can be overridden later.
1494 gst_rtsp_client_set_session_pool (GstRTSPClient * client,
1495 GstRTSPSessionPool * pool)
1497 GstRTSPSessionPool *old;
1499 old = client->session_pool;
1502 g_object_ref (pool);
1503 client->session_pool = pool;
1505 g_object_unref (old);
1510 * gst_rtsp_client_get_session_pool:
1511 * @client: a #GstRTSPClient
1513 * Get the #GstRTSPSessionPool object that @client uses to manage its sessions.
1515 * Returns: a #GstRTSPSessionPool, unref after usage.
1517 GstRTSPSessionPool *
1518 gst_rtsp_client_get_session_pool (GstRTSPClient * client)
1520 GstRTSPSessionPool *result;
1522 if ((result = client->session_pool))
1523 g_object_ref (result);
1529 * gst_rtsp_client_set_server:
1530 * @client: a #GstRTSPClient
1531 * @server: a #GstRTSPServer
1533 * Set @server as the server that created @client.
1536 gst_rtsp_client_set_server (GstRTSPClient * client, GstRTSPServer * server)
1540 old = client->server;
1541 if (old != server) {
1543 g_object_ref (server);
1544 client->server = server;
1546 g_object_unref (old);
1551 * gst_rtsp_client_get_server:
1552 * @client: a #GstRTSPClient
1554 * Get the #GstRTSPServer object that @client was created from.
1556 * Returns: a #GstRTSPServer, unref after usage.
1559 gst_rtsp_client_get_server (GstRTSPClient * client)
1561 GstRTSPServer *result;
1563 if ((result = client->server))
1564 g_object_ref (result);
1570 * gst_rtsp_client_set_media_mapping:
1571 * @client: a #GstRTSPClient
1572 * @mapping: a #GstRTSPMediaMapping
1574 * Set @mapping as the media mapping for @client which it will use to map urls
1575 * to media streams. These mapping is usually inherited from the server that
1576 * created the client but can be overriden later.
1579 gst_rtsp_client_set_media_mapping (GstRTSPClient * client,
1580 GstRTSPMediaMapping * mapping)
1582 GstRTSPMediaMapping *old;
1584 old = client->media_mapping;
1586 if (old != mapping) {
1588 g_object_ref (mapping);
1589 client->media_mapping = mapping;
1591 g_object_unref (old);
1596 * gst_rtsp_client_get_media_mapping:
1597 * @client: a #GstRTSPClient
1599 * Get the #GstRTSPMediaMapping object that @client uses to manage its sessions.
1601 * Returns: a #GstRTSPMediaMapping, unref after usage.
1603 GstRTSPMediaMapping *
1604 gst_rtsp_client_get_media_mapping (GstRTSPClient * client)
1606 GstRTSPMediaMapping *result;
1608 if ((result = client->media_mapping))
1609 g_object_ref (result);
1615 * gst_rtsp_client_set_auth:
1616 * @client: a #GstRTSPClient
1617 * @auth: a #GstRTSPAuth
1619 * configure @auth to be used as the authentication manager of @client.
1622 gst_rtsp_client_set_auth (GstRTSPClient * client, GstRTSPAuth * auth)
1626 g_return_if_fail (GST_IS_RTSP_CLIENT (client));
1632 g_object_ref (auth);
1633 client->auth = auth;
1635 g_object_unref (old);
1641 * gst_rtsp_client_get_auth:
1642 * @client: a #GstRTSPClient
1644 * Get the #GstRTSPAuth used as the authentication manager of @client.
1646 * Returns: the #GstRTSPAuth of @client. g_object_unref() after
1650 gst_rtsp_client_get_auth (GstRTSPClient * client)
1652 GstRTSPAuth *result;
1654 g_return_val_if_fail (GST_IS_RTSP_CLIENT (client), NULL);
1656 if ((result = client->auth))
1657 g_object_ref (result);
1662 static GstRTSPResult
1663 message_received (GstRTSPWatch * watch, GstRTSPMessage * message,
1666 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1668 switch (message->type) {
1669 case GST_RTSP_MESSAGE_REQUEST:
1670 handle_request (client, message);
1672 case GST_RTSP_MESSAGE_RESPONSE:
1674 case GST_RTSP_MESSAGE_DATA:
1675 handle_data (client, message);
1683 static GstRTSPResult
1684 message_sent (GstRTSPWatch * watch, guint cseq, gpointer user_data)
1686 GstRTSPClient *client;
1688 client = GST_RTSP_CLIENT (user_data);
1690 /* GST_INFO ("client %p: sent a message with cseq %d", client, cseq); */
1695 static GstRTSPResult
1696 closed (GstRTSPWatch * watch, gpointer user_data)
1698 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1699 const gchar *tunnelid;
1701 GST_INFO ("client %p: connection closed", client);
1703 if ((tunnelid = gst_rtsp_connection_get_tunnelid (client->connection))) {
1704 g_mutex_lock (tunnels_lock);
1705 /* remove from tunnelids */
1706 g_hash_table_remove (tunnels, tunnelid);
1707 g_mutex_unlock (tunnels_lock);
1713 static GstRTSPResult
1714 error (GstRTSPWatch * watch, GstRTSPResult result, gpointer user_data)
1716 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1719 str = gst_rtsp_strresult (result);
1720 GST_INFO ("client %p: received an error %s", client, str);
1726 static GstRTSPResult
1727 error_full (GstRTSPWatch * watch, GstRTSPResult result,
1728 GstRTSPMessage * message, guint id, gpointer user_data)
1730 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1733 str = gst_rtsp_strresult (result);
1735 ("client %p: received an error %s when handling message %p with id %d",
1736 client, str, message, id);
1743 remember_tunnel (GstRTSPClient * client)
1745 const gchar *tunnelid;
1747 /* store client in the pending tunnels */
1748 tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
1749 if (tunnelid == NULL)
1752 GST_INFO ("client %p: inserting tunnel session %s", client, tunnelid);
1754 /* we can't have two clients connecting with the same tunnelid */
1755 g_mutex_lock (tunnels_lock);
1756 if (g_hash_table_lookup (tunnels, tunnelid))
1757 goto tunnel_existed;
1759 g_hash_table_insert (tunnels, g_strdup (tunnelid), g_object_ref (client));
1760 g_mutex_unlock (tunnels_lock);
1767 GST_ERROR ("client %p: no tunnelid provided", client);
1772 g_mutex_unlock (tunnels_lock);
1773 GST_ERROR ("client %p: tunnel session %s already existed", client,
1779 static GstRTSPStatusCode
1780 tunnel_start (GstRTSPWatch * watch, gpointer user_data)
1782 GstRTSPClient *client;
1784 client = GST_RTSP_CLIENT (user_data);
1786 GST_INFO ("client %p: tunnel start (connection %p)", client,
1787 client->connection);
1789 if (!remember_tunnel (client))
1792 return GST_RTSP_STS_OK;
1797 GST_ERROR ("client %p: error starting tunnel", client);
1798 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1802 static GstRTSPResult
1803 tunnel_lost (GstRTSPWatch * watch, gpointer user_data)
1805 GstRTSPClient *client;
1807 client = GST_RTSP_CLIENT (user_data);
1809 GST_INFO ("client %p: tunnel lost (connection %p)", client,
1810 client->connection);
1812 /* ignore error, it'll only be a problem when the client does a POST again */
1813 remember_tunnel (client);
1818 static GstRTSPResult
1819 tunnel_complete (GstRTSPWatch * watch, gpointer user_data)
1821 const gchar *tunnelid;
1822 GstRTSPClient *client = GST_RTSP_CLIENT (user_data);
1823 GstRTSPClient *oclient;
1825 GST_INFO ("client %p: tunnel complete", client);
1827 /* find previous tunnel */
1828 tunnelid = gst_rtsp_connection_get_tunnelid (client->connection);
1829 if (tunnelid == NULL)
1832 g_mutex_lock (tunnels_lock);
1833 if (!(oclient = g_hash_table_lookup (tunnels, tunnelid)))
1836 /* remove the old client from the table. ref before because removing it will
1837 * remove the ref to it. */
1838 g_object_ref (oclient);
1839 g_hash_table_remove (tunnels, tunnelid);
1841 if (oclient->watch == NULL)
1843 g_mutex_unlock (tunnels_lock);
1845 GST_INFO ("client %p: found tunnel %p (old %p, new %p)", client, oclient,
1846 oclient->connection, client->connection);
1848 /* merge the tunnels into the first client */
1849 gst_rtsp_connection_do_tunnel (oclient->connection, client->connection);
1850 gst_rtsp_watch_reset (oclient->watch);
1851 g_object_unref (oclient);
1853 /* we don't need this watch anymore */
1854 g_source_destroy ((GSource *) client->watch);
1855 client->watchid = 0;
1856 client->watch = NULL;
1863 GST_INFO ("client %p: no tunnelid provided", client);
1864 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1868 g_mutex_unlock (tunnels_lock);
1869 GST_INFO ("client %p: tunnel session %s not found", client, tunnelid);
1870 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1874 g_mutex_unlock (tunnels_lock);
1875 GST_INFO ("client %p: tunnel session %s was closed", client, tunnelid);
1876 g_object_unref (oclient);
1877 return GST_RTSP_STS_SERVICE_UNAVAILABLE;
1881 static GstRTSPWatchFuncs watch_funcs = {
1893 client_watch_notify (GstRTSPClient * client)
1895 GST_INFO ("client %p: watch destroyed", client);
1896 client->watchid = 0;
1897 client->watch = NULL;
1898 g_signal_emit (client, gst_rtsp_client_signals[SIGNAL_CLOSED], 0, NULL);
1899 g_object_unref (client);
1903 * gst_rtsp_client_attach:
1904 * @client: a #GstRTSPClient
1905 * @channel: a #GIOChannel
1907 * Accept a new connection for @client on the socket in @channel.
1909 * This function should be called when the client properties and urls are fully
1910 * configured and the client is ready to start.
1912 * Returns: %TRUE if the client could be accepted.
1915 gst_rtsp_client_accept (GstRTSPClient * client, GIOChannel * channel)
1918 GstRTSPConnection *conn;
1921 GMainContext *context;
1923 struct sockaddr_storage addr;
1925 gchar ip[INET6_ADDRSTRLEN];
1927 /* a new client connected. */
1928 sock = g_io_channel_unix_get_fd (channel);
1930 GST_RTSP_CHECK (gst_rtsp_connection_accept (sock, &conn), accept_failed);
1932 fd = gst_rtsp_connection_get_readfd (conn);
1934 addrlen = sizeof (addr);
1935 if (getsockname (fd, (struct sockaddr *) &addr, &addrlen) < 0)
1936 goto getpeername_failed;
1938 client->is_ipv6 = addr.ss_family == AF_INET6;
1940 if (getnameinfo ((struct sockaddr *) &addr, addrlen, ip, sizeof (ip), NULL, 0,
1941 NI_NUMERICHOST) != 0)
1942 goto getnameinfo_failed;
1944 /* keep the original ip that the client connected to */
1945 g_free (client->server_ip);
1946 client->server_ip = g_strndup (ip, sizeof (ip));
1948 GST_INFO ("client %p connected to server ip %s, ipv6 = %d", client,
1949 client->server_ip, client->is_ipv6);
1951 url = gst_rtsp_connection_get_url (conn);
1952 GST_INFO ("added new client %p ip %s:%d", client, url->host, url->port);
1954 client->connection = conn;
1956 /* create watch for the connection and attach */
1957 client->watch = gst_rtsp_watch_new (client->connection, &watch_funcs,
1958 g_object_ref (client), (GDestroyNotify) client_watch_notify);
1960 /* find the context to add the watch */
1961 if ((source = g_main_current_source ()))
1962 context = g_source_get_context (source);
1966 GST_INFO ("attaching to context %p", context);
1968 client->watchid = gst_rtsp_watch_attach (client->watch, context);
1969 gst_rtsp_watch_unref (client->watch);
1976 gchar *str = gst_rtsp_strresult (res);
1978 GST_ERROR ("Could not accept client on server socket %d: %s", sock, str);
1984 GST_ERROR ("getpeername failed: %s", g_strerror (errno));
1989 GST_ERROR ("getnameinfo failed: %s", g_strerror (errno));