#include <gst/rtsp-server/rtsp-server.h>
/* define this if you want the resource to only be available when using
- * user/admin as the password */
+ * user/password as the password */
#undef WITH_AUTH
/* define this if you want the server to use TLS */
GstRTSPMediaFactory *factory;
#ifdef WITH_AUTH
GstRTSPAuth *auth;
+ GstRTSPToken *token;
+ GstStructure *s;
gchar *basic;
+ GstRTSPPermissions *permissions;
#endif
#ifdef WITH_TLS
GTlsCertificate *cert;
/* create a server instance */
server = gst_rtsp_server_new ();
+
+#ifdef WITH_AUTH
+ /* make a new authentication manager. it can be added to control access to all
+ * the factories on the server or on individual factories. */
+ auth = gst_rtsp_auth_new ();
#ifdef WITH_TLS
cert = g_tls_certificate_new_from_pem ("-----BEGIN CERTIFICATE-----"
"MIICJjCCAY+gAwIBAgIBBzANBgkqhkiG9w0BAQUFADCBhjETMBEGCgmSJomT8ixk"
"DwIga8PqH5Sf5sHedy2+CiK0V4MRfoU4c3zQ6kArI+bEgSkCIQCLA1vXBiE31B5s"
"bdHoYa1BXebfZVd+1Hd95IfEM5mbRwIgSkDuQwV55BBlvWph3U8wVIMIb4GStaH8"
"W535W8UBbEg=" "-----END PRIVATE KEY-----", -1, NULL);
- gst_rtsp_server_set_tls_certificate (server, cert);
+ gst_rtsp_auth_set_tls_certificate (auth, cert);
g_object_unref (cert);
#endif
- /* get the mount points for this server, every server has a default object
- * that be used to map uri mount points to media factories */
- mounts = gst_rtsp_server_get_mount_points (server);
-
-#ifdef WITH_AUTH
- /* make a new authentication manager. it can be added to control access to all
- * the factories on the server or on individual factories. */
- auth = gst_rtsp_auth_new ();
- basic = gst_rtsp_auth_make_basic ("user", "admin");
- gst_rtsp_auth_set_basic (auth, basic);
+ /* make user token */
+ token = gst_rtsp_token_new ();
+ s = gst_rtsp_token_writable_structure (token);
+ gst_structure_set (s, "media.factory.role", G_TYPE_STRING, "user", NULL);
+ basic = gst_rtsp_auth_make_basic ("user", "password");
+ gst_rtsp_auth_add_basic (auth, basic, token);
g_free (basic);
+ gst_rtsp_token_unref (token);
+
/* configure in the server */
gst_rtsp_server_set_auth (server, auth);
#endif
+ /* get the mount points for this server, every server has a default object
+ * that be used to map uri mount points to media factories */
+ mounts = gst_rtsp_server_get_mount_points (server);
+
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
"x264enc ! rtph264pay name=pay0 pt=96 "
"audiotestsrc ! audio/x-raw,rate=8000 ! "
"alawenc ! rtppcmapay name=pay1 pt=97 " ")");
+#ifdef WITH_AUTH
+ /* add permissions for the user media role */
+ permissions = gst_rtsp_permissions_new ();
+ gst_rtsp_permissions_add_role (permissions, "user",
+ gst_structure_new ("user",
+ "media.factory.access", G_TYPE_BOOLEAN, TRUE,
+ "media.factory.construct", G_TYPE_BOOLEAN, TRUE, NULL));
+ gst_rtsp_media_factory_set_permissions (factory, permissions);
+ gst_rtsp_permissions_unref (permissions);
+#endif
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
struct _GstRTSPAuthPrivate
{
GMutex lock;
+
+ /* the TLS certificate */
+ GTlsCertificate *certificate;
GHashTable *basic; /* protected by lock */
GstRTSPMethod methods;
};
GstRTSPAuthPrivate *priv = auth->priv;
GST_INFO ("finalize auth %p", auth);
+
+ if (priv->certificate)
+ g_object_unref (priv->certificate);
g_hash_table_unref (priv->basic);
g_mutex_clear (&priv->lock);
}
/**
+ * gst_rtsp_auth_set_tls_certificate:
+ * @auth: a #GstRTSPAuth
+ * @cert: (allow none): a #GTlsCertificate
+ *
+ * Set the TLS certificate for the auth. Client connections will only
+ * be accepted when TLS is negotiated.
+ */
+void
+gst_rtsp_auth_set_tls_certificate (GstRTSPAuth * auth, GTlsCertificate * cert)
+{
+ GstRTSPAuthPrivate *priv;
+ GTlsCertificate *old;
+
+ g_return_if_fail (GST_IS_RTSP_AUTH (auth));
+
+ priv = auth->priv;
+
+ if (cert)
+ g_object_ref (cert);
+
+ g_mutex_lock (&priv->lock);
+ old = priv->certificate;
+ priv->certificate = cert;
+ g_mutex_unlock (&priv->lock);
+
+ if (old)
+ g_object_unref (old);
+}
+
+/**
+ * gst_rtsp_auth_get_tls_certificate:
+ * @auth: a #GstRTSPAuth
+ *
+ * Get the #GTlsCertificate used for negotiating TLS @auth.
+ *
+ * Returns: (transfer full): the #GTlsCertificate of @auth. g_object_unref() after
+ * usage.
+ */
+GTlsCertificate *
+gst_rtsp_auth_get_tls_certificate (GstRTSPAuth * auth)
+{
+ GstRTSPAuthPrivate *priv;
+ GTlsCertificate *result;
+
+ g_return_val_if_fail (GST_IS_RTSP_AUTH (auth), NULL);
+
+ priv = auth->priv;
+
+ g_mutex_lock (&priv->lock);
+ if ((result = priv->certificate))
+ g_object_ref (result);
+ g_mutex_unlock (&priv->lock);
+
+ return result;
+}
+
+
+/**
* gst_rtsp_auth_add_basic:
* @auth: a #GstRTSPAuth
* @basic: the basic token
GstRTSPAuthPrivate *priv = auth->priv;
gboolean res = FALSE;
- if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
+ if (g_str_equal (check, GST_RTSP_AUTH_CHECK_CONNECT)) {
+ /* new connection */
+ if (priv->certificate) {
+ GTlsConnection *tls;
+
+ /* configure the connection */
+ tls = gst_rtsp_connection_get_tls (state->conn, NULL);
+ g_tls_connection_set_certificate (tls, priv->certificate);
+ }
+ res = TRUE;
+ } else if (g_str_equal (check, GST_RTSP_AUTH_CHECK_URL)) {
+ /* check url and methods */
if ((state->method & priv->methods) != 0)
res = ensure_authenticated (auth, state);
else
res = TRUE;
} else if (g_str_has_prefix (check, "auth.check.media.factory.")) {
+ /* check access to media factory */
const gchar *role;
GstRTSPPermissions *perms;
GstRTSPAuth * gst_rtsp_auth_new (void);
+void gst_rtsp_auth_set_tls_certificate (GstRTSPAuth *auth, GTlsCertificate *cert);
+GTlsCertificate * gst_rtsp_auth_get_tls_certificate (GstRTSPAuth *auth);
+
void gst_rtsp_auth_add_basic (GstRTSPAuth *auth, const gchar * basic,
GstRTSPToken *token);
void gst_rtsp_auth_remove_basic (GstRTSPAuth *auth, const gchar * basic);
/* checks */
/**
+ * GST_RTSP_AUTH_CHECK_CONNECT:
+ *
+ * Check a new connection
+ */
+#define GST_RTSP_AUTH_CHECK_CONNECT "auth.check.connect"
+/**
* GST_RTSP_AUTH_CHECK_URL:
*
* Check the URL and methods
* network (0.0.0.0) and port 8554.
*
* The server will require an SSL connection when a TLS certificate has been
- * set with gst_rtsp_server_set_tls_certificate().
+ * set in the auth object with gst_rtsp_auth_set_tls_certificate().
*
* To start the server, use gst_rtsp_server_attach() to attach it to a
* #GMainContext. For more control, gst_rtsp_server_create_source() and
/* resource manager */
GstRTSPThreadPool *thread_pool;
- /* the TLS certificate */
- GTlsCertificate *certificate;
-
/* the clients that are connected */
GList *clients;
};
static void gst_rtsp_server_finalize (GObject * object);
static GstRTSPClient *default_create_client (GstRTSPServer * server);
-static gboolean default_setup_connection (GstRTSPServer * server,
- GstRTSPClient * client, GstRTSPConnection * conn);
static void
gst_rtsp_server_class_init (GstRTSPServerClass * klass)
gst_rtsp_client_get_type ());
klass->create_client = default_create_client;
- klass->setup_connection = default_setup_connection;
GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer");
}
if (priv->auth)
g_object_unref (priv->auth);
- if (priv->certificate)
- g_object_unref (priv->certificate);
-
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_rtsp_server_parent_class)->finalize (object);
return res;
}
-/**
- * gst_rtsp_server_set_tls_certificate:
- * @server: a #GstRTSPServer
- * @cert: (allow none): a #GTlsCertificate
- *
- * Set the TLS certificate for the server. Client connections will only
- * be accepted when TLS is negotiated.
- */
-void
-gst_rtsp_server_set_tls_certificate (GstRTSPServer * server,
- GTlsCertificate * cert)
-{
- GstRTSPServerPrivate *priv;
- GTlsCertificate *old;
-
- g_return_if_fail (GST_IS_RTSP_SERVER (server));
-
- priv = server->priv;
-
- if (cert)
- g_object_ref (cert);
-
- GST_RTSP_SERVER_LOCK (server);
- old = priv->certificate;
- priv->certificate = cert;
- GST_RTSP_SERVER_UNLOCK (server);
-
- if (old)
- g_object_unref (old);
-}
-
-/**
- * gst_rtsp_server_get_tls_certificate:
- * @server: a #GstRTSPServer
- *
- * Get the #GTlsCertificate used for negotiating TLS @server.
- *
- * Returns: (transfer full): the #GTlsCertificate of @server. g_object_unref() after
- * usage.
- */
-GTlsCertificate *
-gst_rtsp_server_get_tls_certificate (GstRTSPServer * server)
-{
- GstRTSPServerPrivate *priv;
- GTlsCertificate *result;
-
- g_return_val_if_fail (GST_IS_RTSP_SERVER (server), NULL);
-
- priv = server->priv;
-
- GST_RTSP_SERVER_LOCK (server);
- if ((result = priv->certificate))
- g_object_ref (result);
- GST_RTSP_SERVER_UNLOCK (server);
-
- return result;
-}
-
static void
gst_rtsp_server_get_property (GObject * object, guint propid,
GValue * value, GParamSpec * pspec)
return client;
}
-static gboolean
-default_setup_connection (GstRTSPServer * server, GstRTSPClient * client,
- GstRTSPConnection * conn)
-{
- GstRTSPServerPrivate *priv = server->priv;
-
- GST_RTSP_SERVER_LOCK (server);
- if (priv->certificate) {
- GTlsConnection *tls;
-
- /* configure the connection */
- tls = gst_rtsp_connection_get_tls (conn, NULL);
- g_tls_connection_set_certificate (tls, priv->certificate);
- }
- GST_RTSP_SERVER_UNLOCK (server);
-
- return TRUE;
-}
-
/**
* gst_rtsp_server_transfer_connection:
* @server: a #GstRTSPServer
gst_rtsp_server_io_func (GSocket * socket, GIOCondition condition,
GstRTSPServer * server)
{
+ GstRTSPServerPrivate *priv = server->priv;
GstRTSPClient *client = NULL;
GstRTSPServerClass *klass;
GstRTSPResult res;
GstRTSPConnection *conn = NULL;
+ GstRTSPClientState state = { NULL };
if (condition & G_IO_IN) {
+ /* a new client connected. */
+ GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL),
+ accept_failed);
- klass = GST_RTSP_SERVER_GET_CLASS (server);
+ state.server = server;
+ state.conn = conn;
+ state.auth = priv->auth;
+ gst_rtsp_client_state_push_current (&state);
+
+ if (!gst_rtsp_auth_check (GST_RTSP_AUTH_CHECK_CONNECT))
+ goto connection_refused;
+ klass = GST_RTSP_SERVER_GET_CLASS (server);
/* a new client connected, create a client object to handle the client. */
if (klass->create_client)
client = klass->create_client (server);
if (client == NULL)
goto client_failed;
- /* a new client connected. */
- GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, NULL),
- accept_failed);
-
- if (klass->setup_connection)
- if (!klass->setup_connection (server, client, conn))
- goto setup_failed;
-
/* set connection on the client now */
gst_rtsp_client_set_connection (client, conn);
} else {
GST_WARNING_OBJECT (server, "received unknown event %08x", condition);
}
+exit:
+ gst_rtsp_client_state_pop_current (&state);
+
return G_SOURCE_CONTINUE;
/* ERRORS */
-client_failed:
- {
- GST_ERROR_OBJECT (server, "failed to create a client");
- return G_SOURCE_CONTINUE;
- }
accept_failed:
{
gchar *str = gst_rtsp_strresult (res);
GST_ERROR_OBJECT (server, "Could not accept client on socket %p: %s",
socket, str);
g_free (str);
- g_object_unref (client);
- return G_SOURCE_CONTINUE;
+ goto exit;
}
-setup_failed:
+connection_refused:
{
- GST_ERROR_OBJECT (server, "failed to setup client connection");
+ GST_ERROR_OBJECT (server, "connection refused");
+ gst_rtsp_connection_free (conn);
+ goto exit;
+ }
+client_failed:
+ {
+ GST_ERROR_OBJECT (server, "failed to create a client");
gst_rtsp_connection_free (conn);
- g_object_unref (client);
- return G_SOURCE_CONTINUE;
+ goto exit;
}
}
GObjectClass parent_class;
GstRTSPClient * (*create_client) (GstRTSPServer *server);
- gboolean (*setup_connection) (GstRTSPServer *server, GstRTSPClient *client,
- GstRTSPConnection *conn);
+
/* signals */
void (*client_connected) (GstRTSPServer *server, GstRTSPClient *client);
};