Cleanup of sessions and more
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-session-pool.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "rtsp-session-pool.h"
21
22 #undef DEBUG
23
24 static void gst_rtsp_session_pool_finalize (GObject * object);
25
26 static gchar * create_session_id (GstRTSPSessionPool *pool);
27
28 G_DEFINE_TYPE (GstRTSPSessionPool, gst_rtsp_session_pool, G_TYPE_OBJECT);
29
30 static void
31 gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass)
32 {
33   GObjectClass *gobject_class;
34
35   gobject_class = G_OBJECT_CLASS (klass);
36
37   gobject_class->finalize = gst_rtsp_session_pool_finalize;
38
39   klass->create_session_id = create_session_id;
40 }
41
42 static void
43 gst_rtsp_session_pool_init (GstRTSPSessionPool * pool)
44 {
45   pool->lock = g_mutex_new ();
46   pool->sessions = g_hash_table_new_full (g_str_hash, g_str_equal,
47                   NULL, g_object_unref);
48 }
49
50 static void
51 gst_rtsp_session_pool_finalize (GObject * object)
52 {
53   GstRTSPSessionPool * pool = GST_RTSP_SESSION_POOL (object);
54
55   g_mutex_free (pool->lock);
56   g_hash_table_unref (pool->sessions);
57   
58   G_OBJECT_CLASS (gst_rtsp_session_pool_parent_class)->finalize (object);
59 }
60
61 /**
62  * gst_rtsp_session_pool_new:
63  *
64  * Create a new #GstRTSPSessionPool instance.
65  *
66  * Returns: A new #GstRTSPSessionPool. g_object_unref() after usage.
67  */
68 GstRTSPSessionPool *
69 gst_rtsp_session_pool_new (void)
70 {
71   GstRTSPSessionPool *result;
72
73   result = g_object_new (GST_TYPE_RTSP_SESSION_POOL, NULL);
74
75   return result;
76 }
77
78 /**
79  * gst_rtsp_session_pool_find:
80  * @pool: the pool to search
81  * @sessionid: the session id
82  *
83  * Find the session with @sessionid in @pool.
84  *
85  * Returns: the #GstRTSPSession with @sessionid or %NULL when the session did
86  * not exist. g_object_unref() after usage.
87  */
88 GstRTSPSession *
89 gst_rtsp_session_pool_find (GstRTSPSessionPool *pool, const gchar *sessionid)
90 {
91   GstRTSPSession *result;
92
93   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
94   g_return_val_if_fail (sessionid != NULL, NULL);
95
96   g_mutex_lock (pool->lock);
97   result = g_hash_table_lookup (pool->sessions, sessionid);
98   if (result)
99     g_object_ref (result);
100   g_mutex_unlock (pool->lock);
101
102   return result;
103 }
104
105 static gchar *
106 create_session_id (GstRTSPSessionPool *pool)
107 {
108   gchar id[16];
109   gint i;
110
111   for (i = 0; i < 16; i++) {
112     id[i] = g_random_int_range ('a', 'z');
113   }
114
115   return g_strndup (id, 16);
116 }
117
118 /**
119  * gst_rtsp_session_pool_create:
120  * @pool: a #GstRTSPSessionPool
121  *
122  * Create a new #GstRTSPSession object in @pool.
123  *
124  * Returns: a new #GstRTSPSession.
125  */
126 GstRTSPSession *
127 gst_rtsp_session_pool_create (GstRTSPSessionPool *pool)
128 {
129   GstRTSPSession *result = NULL;
130   GstRTSPSessionPoolClass *klass;
131   gchar *id = NULL;
132
133   g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL);
134
135   klass = GST_RTSP_SESSION_POOL_GET_CLASS (pool);
136
137   do {
138     /* start by creating a new random session id, we assume that this is random
139      * enough to not cause a collision, which we will check later  */
140     if (klass->create_session_id)
141       id = klass->create_session_id (pool);
142     else
143       goto no_function;
144
145     if (id == NULL)
146       goto no_session;
147
148     g_mutex_lock (pool->lock);
149     /* check if the sessionid existed */
150     result = g_hash_table_lookup (pool->sessions, id);
151     if (result) {
152       /* found, retry with a different session id*/
153       result = NULL;
154     }
155     else {
156       /* not found, create session and insert it in the pool */
157       result = gst_rtsp_session_new (id); 
158       /* take additional ref for the pool */
159       g_object_ref (result);
160       g_hash_table_insert (pool->sessions, result->sessionid, result);
161     }
162     g_mutex_unlock (pool->lock);
163
164     g_free (id);
165   } while (result == NULL);
166
167   return result;
168
169   /* ERRORS */
170 no_function:
171   {
172     g_warning ("no create_session_id vmethod in GstRTSPSessionPool %p", pool);
173     return NULL;
174   }
175 no_session:
176   {
177     g_warning ("can't create session id with GstRTSPSessionPool %p", pool);
178     return NULL;
179   }
180 }
181
182 /**
183  * gst_rtsp_session_pool_remove:
184  * @pool: a #GstRTSPSessionPool
185  * @sess: a #GstRTSPSession
186  *
187  * Remove @sess from @pool and Clean it up.
188  *
189  * Returns: a new #GstRTSPSession.
190  */
191 void
192 gst_rtsp_session_pool_remove (GstRTSPSessionPool *pool, GstRTSPSession *sess)
193 {
194   gboolean found;
195
196   g_return_if_fail (GST_IS_RTSP_SESSION_POOL (pool));
197   g_return_if_fail (GST_IS_RTSP_SESSION (sess));
198
199   g_mutex_lock (pool->lock);
200   found = g_hash_table_remove (pool->sessions, sess->sessionid);
201   g_mutex_unlock (pool->lock);
202 }
203