diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c index d7a0d1cca3..b9ac26c900 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 3354f8ce33..472ca061cc 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);