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.
This commit is contained in:
Wim Taymans 2011-01-12 10:57:08 +01:00
parent 8ccebd90b4
commit 6d6ba1ee61
2 changed files with 75 additions and 29 deletions

View file

@ -55,8 +55,9 @@ static void gst_rtsp_server_set_property (GObject * object, guint propid,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
static void gst_rtsp_server_finalize (GObject * object); static void gst_rtsp_server_finalize (GObject * object);
static GstRTSPClient *default_accept_client (GstRTSPServer * server, static GstRTSPClient *default_create_client (GstRTSPServer * server);
GIOChannel * channel); static gboolean default_accept_client (GstRTSPServer * server,
GstRTSPClient * client, GIOChannel * channel);
static void static void
gst_rtsp_server_class_init (GstRTSPServerClass * klass) gst_rtsp_server_class_init (GstRTSPServerClass * klass)
@ -127,6 +128,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
GST_TYPE_RTSP_MEDIA_MAPPING, GST_TYPE_RTSP_MEDIA_MAPPING,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
klass->create_client = default_create_client;
klass->accept_client = default_accept_client; klass->accept_client = default_accept_client;
GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer"); GST_DEBUG_CATEGORY_INIT (rtsp_server_debug, "rtspserver", 0, "GstRTSPServer");
@ -135,6 +137,7 @@ gst_rtsp_server_class_init (GstRTSPServerClass * klass)
static void static void
gst_rtsp_server_init (GstRTSPServer * server) gst_rtsp_server_init (GstRTSPServer * server)
{ {
server->lock = g_mutex_new ();
server->address = g_strdup (DEFAULT_ADDRESS); server->address = g_strdup (DEFAULT_ADDRESS);
server->service = g_strdup (DEFAULT_SERVICE); server->service = g_strdup (DEFAULT_SERVICE);
server->backlog = DEFAULT_BACKLOG; server->backlog = DEFAULT_BACKLOG;
@ -147,6 +150,7 @@ gst_rtsp_server_finalize (GObject * object)
{ {
GstRTSPServer *server = GST_RTSP_SERVER (object); GstRTSPServer *server = GST_RTSP_SERVER (object);
g_mutex_free (server->lock);
g_free (server->address); g_free (server->address);
g_free (server->service); g_free (server->service);
@ -616,10 +620,20 @@ close_error:
} }
} }
/* default method for creating a new client object in the server to accept and /* add the client to the active list of clients, takes ownership of
* handle a client connection on this server */ * 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 * static GstRTSPClient *
default_accept_client (GstRTSPServer * server, GIOChannel * channel) default_create_client (GstRTSPServer * server)
{ {
GstRTSPClient *client; GstRTSPClient *client;
@ -633,13 +647,22 @@ default_accept_client (GstRTSPServer * server, GIOChannel * channel)
/* set authentication manager */ /* set authentication manager */
gst_rtsp_client_set_auth (client, server->auth); 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 /* accept connections for that client, this function returns after accepting
* the connection and will run the remainder of the communication with the * the connection and will run the remainder of the communication with the
* client asyncronously. */ * client asyncronously. */
if (!gst_rtsp_client_accept (client, channel)) if (!gst_rtsp_client_accept (client, channel))
goto accept_failed; goto accept_failed;
return client; return TRUE;
/* ERRORS */ /* ERRORS */
accept_failed: accept_failed:
@ -647,8 +670,7 @@ accept_failed:
GST_ERROR_OBJECT (server, GST_ERROR_OBJECT (server,
"Could not accept client on server socket %d: %s (%d)", "Could not accept client on server socket %d: %s (%d)",
server->server_sock.fd, g_strerror (errno), errno); server->server_sock.fd, g_strerror (errno), errno);
gst_object_unref (client); return FALSE;
return NULL;
} }
} }
@ -666,21 +688,26 @@ gboolean
gst_rtsp_server_io_func (GIOChannel * channel, GIOCondition condition, gst_rtsp_server_io_func (GIOChannel * channel, GIOCondition condition,
GstRTSPServer * server) GstRTSPServer * server)
{ {
gboolean result;
GstRTSPClient *client = NULL; GstRTSPClient *client = NULL;
GstRTSPServerClass *klass; GstRTSPServerClass *klass;
if (condition & G_IO_IN) { if (condition & G_IO_IN) {
klass = GST_RTSP_SERVER_GET_CLASS (server); klass = GST_RTSP_SERVER_GET_CLASS (server);
/* a new client connected, create a client object to handle the client. */ if (klass->create_client)
if (klass->accept_client) client = klass->create_client (server);
client = klass->accept_client (server, channel);
if (client == NULL) if (client == NULL)
goto client_failed; goto client_failed;
/* can unref the client now, when the request is finished, it will be /* a new client connected, create a client object to handle the client. */
* unreffed async. */ if (klass->accept_client)
gst_object_unref (client); result = klass->accept_client (server, client, channel);
if (!result)
goto accept_failed;
/* manage the client connection */
manage_client (server, client);
} else { } else {
GST_WARNING_OBJECT (server, "received unknown event %08x", condition); GST_WARNING_OBJECT (server, "received unknown event %08x", condition);
} }
@ -692,6 +719,12 @@ client_failed:
GST_ERROR_OBJECT (server, "failed to create a client"); GST_ERROR_OBJECT (server, "failed to create a client");
return FALSE; return FALSE;
} }
accept_failed:
{
GST_ERROR_OBJECT (server, "failed to accept client");
gst_object_unref (client);
return FALSE;
}
} }
/** /**

View file

@ -31,19 +31,22 @@
#include <fcntl.h> #include <fcntl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef __GST_RTSP_SERVER_H__
#define __GST_RTSP_SERVER_H__
#include <gst/gst.h> #include <gst/gst.h>
G_BEGIN_DECLS
typedef struct _GstRTSPServer GstRTSPServer;
typedef struct _GstRTSPServerClass GstRTSPServerClass;
#include "rtsp-session-pool.h" #include "rtsp-session-pool.h"
#include "rtsp-media-mapping.h" #include "rtsp-media-mapping.h"
#include "rtsp-media-factory-uri.h" #include "rtsp-media-factory-uri.h"
#include "rtsp-client.h" #include "rtsp-client.h"
#include "rtsp-auth.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_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(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)) #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_CAST(obj) ((GstRTSPServer*)(obj))
#define GST_RTSP_SERVER_CLASS_CAST(klass) ((GstRTSPServerClass*)(klass)) #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 { struct _GstRTSPServer {
GObject parent; GObject parent;
GMutex *lock;
/* server information */ /* server information */
gchar *address; gchar *address;
gchar *service; gchar *service;
gint backlog; gint backlog;
struct sockaddr_in server_sin; struct sockaddr_in server_sin;
@ -79,20 +87,25 @@ struct _GstRTSPServer {
/* authentication manager */ /* authentication manager */
GstRTSPAuth *auth; GstRTSPAuth *auth;
/* the clients that are connected */
GList *clients;
}; };
/** /**
* GstRTSPServerClass: * GstRTSPServerClass:
* *
* @accept_client: Create, configure, accept and return a new GstRTSPClient * @create_client: Create, configure a new GstRTSPClient
* object that handles the new connection on @channel. * object that handles the new connection on @channel.
* @accept_client: accept a new GstRTSPClient
* *
* The RTSP server class structure * The RTSP server class structure
*/ */
struct _GstRTSPServerClass { struct _GstRTSPServerClass {
GObjectClass parent_class; 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); GType gst_rtsp_server_get_type (void);