diff options
Diffstat (limited to 'gst/dccp/gstdccpserversink.c')
-rw-r--r-- | gst/dccp/gstdccpserversink.c | 465 |
1 files changed, 0 insertions, 465 deletions
diff --git a/gst/dccp/gstdccpserversink.c b/gst/dccp/gstdccpserversink.c deleted file mode 100644 index 7623523f9..000000000 --- a/gst/dccp/gstdccpserversink.c +++ /dev/null @@ -1,465 +0,0 @@ -/* GStreamer - * Copyright (C) <2007> Leandro Melo de Sales <leandroal@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-dccpserversink - * @see_also: dccpclientsink, dccpclientsrc, dccpserversrc - * - * This element wait for connections from clients and send data to them. - * <ulink url="http://www.linuxfoundation.org/en/Net:DCCP">DCCP</ulink> (Datagram - * Congestion Control Protocol) is a Transport Layer protocol like - * TCP and UDP. - * - * <refsect2> - * <title>Example pipeline</title> - * <para> - * |[ - * gst-launch -v dccpclientsrc host=localhost port=9011 ccid=2 ! decodebin ! alsasink - * ]| Client - * |[ - * gst-launch -v filesrc location=music.mp3 ! mp3parse ! dccpserversink port=9011 ccid=2 - * ]| Server - * - * This example pipeline will send a MP3 stream to the client using DCCP. - * The client will decode the MP3 and play it. Run the server pipeline - * first than the client pipeline. If you want, you can run more than one dccpclientsrc - * to connect to the same server (see wait-connections property at dccpserversink). - * </para> - * </refsect2> - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstdccpserversink.h" -#include "gstdccp.h" -#include <fcntl.h> - -/* signals */ -enum -{ - SIGNAL_CONNECTED, - LAST_SIGNAL -}; - -/* properties */ -enum -{ - PROP_0, - PROP_PORT, - PROP_CLIENT_SOCK_FD, - PROP_CCID, - PROP_CLOSED, - PROP_WAIT_CONNECTIONS -}; - -static pthread_t accept_thread_id; - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -static gboolean gst_dccp_server_sink_stop (GstBaseSink * bsink); - -GST_DEBUG_CATEGORY_STATIC (dccpserversink_debug); - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GST_BOILERPLATE (GstDCCPServerSink, gst_dccp_server_sink, GstBaseSink, - GST_TYPE_BASE_SINK); - -static guint gst_dccp_server_sink_signals[LAST_SIGNAL] = { 0 }; - -/* - * Create a new client with the socket and the MTU - * - * @param element - the gstdccpserversink instance - * @param socket - the client socket - * @return the client - */ -static Client * -gst_dccp_server_create_client (GstElement * element, int socket) -{ - Client *client = (Client *) g_malloc (sizeof (Client)); - client->socket = socket; - client->pksize = gst_dccp_get_max_packet_size (element, client->socket); - client->flow_status = GST_FLOW_OK; - - GST_DEBUG_OBJECT (element, "Creating a new client with fd %d and MTU %d.", - client->socket, client->pksize); - - /* the socket is connected */ - g_signal_emit (element, gst_dccp_server_sink_signals[SIGNAL_CONNECTED], 0, - socket); - - return client; -} - -/* - * Wait connections of new clients - * - * @param arg - the gstdccpserversink instance - */ -static void * -gst_dccp_server_accept_new_clients (void *arg) -{ - GstDCCPServerSink *sink = (GstDCCPServerSink *) arg; - int newsockfd; - Client *client; - - while (1) { - newsockfd = - gst_dccp_server_wait_connections (GST_ELEMENT (sink), sink->sock_fd); - - client = gst_dccp_server_create_client (GST_ELEMENT (sink), newsockfd); - - pthread_mutex_lock (&lock); - sink->clients = g_list_append (sink->clients, client); - pthread_mutex_unlock (&lock); - } - - return NULL; -} - -/* - * Send the buffer to a client - * - * @param arg - the client - */ -static void * -gst_dccp_server_send_buffer (void *arg) -{ - Client *client = (Client *) arg; - GstDCCPServerSink *sink = client->server; - GstBuffer *buf = client->buf; - int client_sock_fd = client->socket; - int pksize = client->pksize; - - if (gst_dccp_send_buffer (GST_ELEMENT (sink), buf, client_sock_fd, - pksize) == GST_FLOW_ERROR) { - client->flow_status = GST_FLOW_ERROR; - } - return NULL; -} - -/* Remove clients with problems to send. - * - * @param arg - the gstdccpserversink instance - */ -static void * -gst_dccp_server_delete_dead_clients (void *arg) -{ - GstDCCPServerSink *sink = (GstDCCPServerSink *) arg; - GList *tmp = NULL; - GList *l; - - pthread_mutex_lock (&lock); - for (l = sink->clients; l != NULL; l = l->next) { - Client *client = (Client *) l->data; - - if (client->flow_status == GST_FLOW_OK) { - tmp = g_list_append (tmp, client); - } else { - close (client->socket); - g_free (client); - } - } - g_list_free (sink->clients); - sink->clients = tmp; - pthread_mutex_unlock (&lock); - return 0; -} - -static void -gst_dccp_server_sink_init (GstDCCPServerSink * this, - GstDCCPServerSinkClass * g_class) -{ - this->port = DCCP_DEFAULT_PORT; - this->sock_fd = DCCP_DEFAULT_SOCK_FD; - this->client_sock_fd = DCCP_DEFAULT_CLIENT_SOCK_FD; - this->closed = DCCP_DEFAULT_CLOSED; - this->ccid = DCCP_DEFAULT_CCID; - this->wait_connections = DCCP_DEFAULT_WAIT_CONNECTIONS; - this->clients = NULL; -} - -/* - * Starts the element. If the sockfd property was not the default, this method - * will wait for a client connection. If wait-connections property is true, it - * creates a thread to wait for new client connections. - * - * @param bsink - the element - * @return TRUE if the send operation was successful, FALSE otherwise. - */ -static gboolean -gst_dccp_server_sink_start (GstBaseSink * bsink) -{ - GstDCCPServerSink *sink = GST_DCCP_SERVER_SINK (bsink); - Client *client; - - if ((sink->sock_fd = gst_dccp_create_new_socket (GST_ELEMENT (sink))) < 0) { - return FALSE; - } - - if (!gst_dccp_make_address_reusable (GST_ELEMENT (sink), sink->sock_fd)) { - return FALSE; - } - - /* name the server socket */ - memset (&sink->server_sin, 0, sizeof (sink->server_sin)); - sink->server_sin.sin_family = AF_INET; /* network socket */ - sink->server_sin.sin_port = htons (sink->port); /* on port */ - sink->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); /* for hosts */ - - if (!gst_dccp_bind_server_socket (GST_ELEMENT (sink), sink->sock_fd, - sink->server_sin)) { - return FALSE; - } - - if (!gst_dccp_set_ccid (GST_ELEMENT (sink), sink->sock_fd, sink->ccid)) { - return FALSE; - } - - if (!gst_dccp_listen_server_socket (GST_ELEMENT (sink), sink->sock_fd)) { - return FALSE; - } - - - if (sink->client_sock_fd == DCCP_DEFAULT_CLIENT_SOCK_FD) { - sink->client_sock_fd = - gst_dccp_server_wait_connections (GST_ELEMENT (sink), sink->sock_fd); - } - - if (sink->client_sock_fd == -1) { - return FALSE; - } - - client = - gst_dccp_server_create_client (GST_ELEMENT (sink), sink->client_sock_fd); - sink->clients = g_list_append (sink->clients, client); - - pthread_mutex_init (&lock, NULL); - - if (sink->wait_connections == TRUE) { - pthread_create (&accept_thread_id, NULL, gst_dccp_server_accept_new_clients, - sink); - pthread_detach (accept_thread_id); - } - - return TRUE; -} - -static GstFlowReturn -gst_dccp_server_sink_render (GstBaseSink * bsink, GstBuffer * buf) -{ - GstDCCPServerSink *sink = GST_DCCP_SERVER_SINK (bsink); - - pthread_t thread_id; - GList *l; - - pthread_mutex_lock (&lock); - - for (l = sink->clients; l != NULL; l = l->next) { - Client *client = (Client *) l->data; - - client->buf = buf; - client->server = sink; - - /* FIXME: are we really creating a new thread here for every single buffer - * and every single client? */ - if (client->flow_status == GST_FLOW_OK) { - pthread_create (&thread_id, NULL, gst_dccp_server_send_buffer, - (void *) client); - pthread_detach (thread_id); - } else { - /* FIXME: what's the point of doing this in a separate thread if it - * keeps he global lock anyway while going through all the clients and - * waiting for close() to finish? */ - pthread_create (&thread_id, NULL, gst_dccp_server_delete_dead_clients, - (void *) sink); - pthread_detach (thread_id); - } - } - - pthread_mutex_unlock (&lock); - return GST_FLOW_OK; -} - -static gboolean -gst_dccp_server_sink_stop (GstBaseSink * bsink) -{ - GstDCCPServerSink *sink; - GList *l; - - sink = GST_DCCP_SERVER_SINK (bsink); - - if (sink->wait_connections == TRUE) { - pthread_cancel (accept_thread_id); - } - - gst_dccp_socket_close (GST_ELEMENT (sink), &(sink->sock_fd)); - - pthread_mutex_lock (&lock); - for (l = sink->clients; l != NULL; l = l->next) { - Client *client = (Client *) l->data; - - if (client->socket != DCCP_DEFAULT_CLIENT_SOCK_FD && sink->closed == TRUE) { - gst_dccp_socket_close (GST_ELEMENT (sink), &(client->socket)); - } - g_free (client); - } - pthread_mutex_unlock (&lock); - - return TRUE; -} - -static void -gst_dccp_server_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_static_pad_template (element_class, &sinktemplate); - - gst_element_class_set_static_metadata (element_class, "DCCP server sink", - "Sink/Network", - "Send data as a server over the network via DCCP", - "E-Phone Team at Federal University of Campina Grande <leandroal@gmail.com>"); -} - -/* - * Set the value of a property for the server sink. - */ -static void -gst_dccp_server_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstDCCPServerSink *sink = GST_DCCP_SERVER_SINK (object); - - switch (prop_id) { - case PROP_PORT: - sink->port = g_value_get_int (value); - break; - case PROP_CLIENT_SOCK_FD: - sink->client_sock_fd = g_value_get_int (value); - break; - case PROP_CLOSED: - sink->closed = g_value_get_boolean (value); - break; - case PROP_WAIT_CONNECTIONS: - sink->wait_connections = g_value_get_boolean (value); - break; - case PROP_CCID: - sink->ccid = g_value_get_int (value); - break; - default: - break; - } -} - -static void -gst_dccp_server_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstDCCPServerSink *sink = GST_DCCP_SERVER_SINK (object); - - switch (prop_id) { - case PROP_PORT: - g_value_set_int (value, sink->port); - break; - case PROP_CLIENT_SOCK_FD: - g_value_set_int (value, sink->client_sock_fd); - break; - case PROP_CLOSED: - g_value_set_boolean (value, sink->closed); - break; - case PROP_WAIT_CONNECTIONS: - g_value_set_boolean (value, sink->wait_connections); - break; - case PROP_CCID: - g_value_set_int (value, sink->ccid); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -static void -gst_dccp_server_sink_class_init (GstDCCPServerSinkClass * klass) -{ - GObjectClass *gobject_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - gobject_class->set_property = gst_dccp_server_sink_set_property; - gobject_class->get_property = gst_dccp_server_sink_get_property; - - g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PORT, - g_param_spec_int ("port", "Port", - "The port to listen to", 0, G_MAXUINT16, - DCCP_DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CLIENT_SOCK_FD, - g_param_spec_int ("sockfd", "Socket fd", - "The client socket file descriptor", -1, G_MAXINT, - DCCP_DEFAULT_CLIENT_SOCK_FD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CLOSED, - g_param_spec_boolean ("close-socket", "Close", - "Close the client sockets at end of stream", - DCCP_DEFAULT_CLOSED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CCID, - g_param_spec_int ("ccid", "CCID", - "The Congestion Control IDentified to be used", 2, G_MAXINT, - DCCP_DEFAULT_CCID, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_WAIT_CONNECTIONS, - g_param_spec_boolean ("wait-connections", "Wait connections", - "Wait for many client connections", - DCCP_DEFAULT_WAIT_CONNECTIONS, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - - /* signals */ - /** - * GstDccpServerSink::connected: - * @sink: the gstdccpserversink element that emitted this signal - * @fd: the connected socket file descriptor - * - * Reports that the element has connected, giving the fd of the socket - */ - gst_dccp_server_sink_signals[SIGNAL_CONNECTED] = - g_signal_new ("connected", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (GstDCCPServerSinkClass, connected), NULL, NULL, - gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - - gstbasesink_class->start = gst_dccp_server_sink_start; - gstbasesink_class->stop = gst_dccp_server_sink_stop; - gstbasesink_class->render = gst_dccp_server_sink_render; - - GST_DEBUG_CATEGORY_INIT (dccpserversink_debug, "dccpserversink", 0, - "DCCP Server Sink"); -} |