From 6d6ba1ee6145f96f21d2341deab4ac5f6f99b07a Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 12 Jan 2011 10:57:08 +0100 Subject: [PATCH] server: separate create and accept Create separate create and accept methods so that subclasses can create custom client object. Configure the server in the client object and prepare for keeping track of connected clients. --- gst/rtsp-server/rtsp-server.c | 61 +++++++++++++++++++++++++++++++++---------- gst/rtsp-server/rtsp-server.h | 43 +++++++++++++++++++----------- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c index d7a0d1c..b9ac26c 100644 --- a/gst/rtsp-server/rtsp-server.c +++ b/gst/rtsp-server/rtsp-server.c @@ -55,8 +55,9 @@ static void gst_rtsp_server_set_property (GObject * object, guint propid, const GValue * value, GParamSpec * pspec); static void gst_rtsp_server_finalize (GObject * object); -static GstRTSPClient *default_accept_client (GstRTSPServer * server, - GIOChannel * channel); +static GstRTSPClient *default_create_client (GstRTSPServer * server); +static gboolean default_accept_client (GstRTSPServer * server, + GstRTSPClient * client, GIOChannel * channel); static void gst_rtsp_server_class_init (GstRTSPServerClass * klass) @@ -127,6 +128,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass) GST_TYPE_RTSP_MEDIA_MAPPING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + klass->create_client = default_create_client; klass->accept_client = default_accept_client; GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer"); @@ -135,6 +137,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass) static void gst_rtsp_server_init (GstRTSPServer * server) { + server->lock = g_mutex_new (); server->address = g_strdup (DEFAULT_ADDRESS); server->service = g_strdup (DEFAULT_SERVICE); server->backlog = DEFAULT_BACKLOG; @@ -147,6 +150,7 @@ gst_rtsp_server_finalize (GObject * object) { GstRTSPServer *server = GST_RTSP_SERVER (object); + g_mutex_free (server->lock); g_free (server->address); g_free (server->service); @@ -616,10 +620,20 @@ close_error: } } -/* default method for creating a new client object in the server to accept and - * handle a client connection on this server */ +/* add the client to the active list of clients, takes ownership of + * the client */ +static void +manage_client (GstRTSPServer * server, GstRTSPClient * client) +{ + gst_rtsp_client_set_server (client, server); + + /* can unref the client now, when the request is finished, it will be + * unreffed async. */ + gst_object_unref (client); +} + static GstRTSPClient * -default_accept_client (GstRTSPServer * server, GIOChannel * channel) +default_create_client (GstRTSPServer * server) { GstRTSPClient *client; @@ -633,13 +647,22 @@ default_accept_client (GstRTSPServer * server, GIOChannel * channel) /* set authentication manager */ gst_rtsp_client_set_auth (client, server->auth); + return client; +} + +/* default method for creating a new client object in the server to accept and + * handle a client connection on this server */ +static gboolean +default_accept_client (GstRTSPServer * server, GstRTSPClient * client, + GIOChannel * channel) +{ /* accept connections for that client, this function returns after accepting * the connection and will run the remainder of the communication with the * client asyncronously. */ if (!gst_rtsp_client_accept (client, channel)) goto accept_failed; - return client; + return TRUE; /* ERRORS */ accept_failed: @@ -647,8 +670,7 @@ accept_failed: GST_ERROR_OBJECT (server, "Could not accept client on server socket %d: %s (%d)", server->server_sock.fd, g_strerror (errno), errno); - gst_object_unref (client); - return NULL; + return FALSE; } } @@ -666,21 +688,26 @@ gboolean gst_rtsp_server_io_func (GIOChannel * channel, GIOCondition condition, GstRTSPServer * server) { + gboolean result; GstRTSPClient *client = NULL; GstRTSPServerClass *klass; if (condition & G_IO_IN) { klass = GST_RTSP_SERVER_GET_CLASS (server); - /* a new client connected, create a client object to handle the client. */ - if (klass->accept_client) - client = klass->accept_client (server, channel); + if (klass->create_client) + client = klass->create_client (server); if (client == NULL) goto client_failed; - /* can unref the client now, when the request is finished, it will be - * unreffed async. */ - gst_object_unref (client); + /* a new client connected, create a client object to handle the client. */ + if (klass->accept_client) + result = klass->accept_client (server, client, channel); + if (!result) + goto accept_failed; + + /* manage the client connection */ + manage_client (server, client); } else { GST_WARNING_OBJECT (server, "received unknown event %08x", condition); } @@ -692,6 +719,12 @@ client_failed: GST_ERROR_OBJECT (server, "failed to create a client"); return FALSE; } +accept_failed: + { + GST_ERROR_OBJECT (server, "failed to accept client"); + gst_object_unref (client); + return FALSE; + } } /** diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h index 3354f8c..472ca06 100644 --- a/gst/rtsp-server/rtsp-server.h +++ b/gst/rtsp-server/rtsp-server.h @@ -31,19 +31,22 @@ #include #include +#ifndef __GST_RTSP_SERVER_H__ +#define __GST_RTSP_SERVER_H__ + #include +G_BEGIN_DECLS + +typedef struct _GstRTSPServer GstRTSPServer; +typedef struct _GstRTSPServerClass GstRTSPServerClass; + #include "rtsp-session-pool.h" #include "rtsp-media-mapping.h" #include "rtsp-media-factory-uri.h" #include "rtsp-client.h" #include "rtsp-auth.h" -#ifndef __GST_RTSP_SERVER_H__ -#define __GST_RTSP_SERVER_H__ - -G_BEGIN_DECLS - #define GST_TYPE_RTSP_SERVER (gst_rtsp_server_get_type ()) #define GST_IS_RTSP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_SERVER)) #define GST_IS_RTSP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_RTSP_SERVER)) @@ -53,16 +56,21 @@ G_BEGIN_DECLS #define GST_RTSP_SERVER_CAST(obj) ((GstRTSPServer*)(obj)) #define GST_RTSP_SERVER_CLASS_CAST(klass) ((GstRTSPServerClass*)(klass)) -typedef struct _GstRTSPServer GstRTSPServer; -typedef struct _GstRTSPServerClass GstRTSPServerClass; - +/** + * GstRTSPServer: + * + * This object listens on a port, creates and manages the clients connected to + * it. + */ struct _GstRTSPServer { - GObject parent; + GObject parent; + + GMutex *lock; /* server information */ - gchar *address; - gchar *service; - gint backlog; + gchar *address; + gchar *service; + gint backlog; struct sockaddr_in server_sin; @@ -79,20 +87,25 @@ struct _GstRTSPServer { /* authentication manager */ GstRTSPAuth *auth; + + /* the clients that are connected */ + GList *clients; }; /** * GstRTSPServerClass: * - * @accept_client: Create, configure, accept and return a new GstRTSPClient - * object that handles the new connection on @channel. + * @create_client: Create, configure a new GstRTSPClient + * object that handles the new connection on @channel. + * @accept_client: accept a new GstRTSPClient * * The RTSP server class structure */ struct _GstRTSPServerClass { GObjectClass parent_class; - GstRTSPClient * (*accept_client) (GstRTSPServer *server, GIOChannel *channel); + GstRTSPClient * (*create_client) (GstRTSPServer *server); + gboolean (*accept_client) (GstRTSPServer *server, GstRTSPClient *client, GIOChannel *channel); }; GType gst_rtsp_server_get_type (void); -- 2.7.4