diff -r 9b2c3c7a1a9c -r 567bb019e3e3 gst_plugins_base/gst/tcp/gsttcpserversink.c --- a/gst_plugins_base/gst/tcp/gsttcpserversink.c Wed Mar 31 22:03:18 2010 +0300 +++ b/gst_plugins_base/gst/tcp/gsttcpserversink.c Tue Aug 31 15:30:33 2010 +0300 @@ -19,20 +19,24 @@ */ /** - * SECTION:tcpserversink - * @short_description: a sink that acts as a TCP server and sends data to - * multiple clients + * SECTION:element-tcpserversink * @see_also: #multifdsink + * + * + * Example launch line + * |[ + * # server: + * gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000 + * # client: + * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2 + * ]| + * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef __SYMBIAN32__ -#include "gst/gst-i18n-plugin.h" -#else #include -#endif #include /* memset */ #include @@ -105,10 +109,11 @@ g_object_class_install_property (gobject_class, ARG_HOST, g_param_spec_string ("host", "host", "The host/IP to send the packets to", - TCP_DEFAULT_HOST, G_PARAM_READWRITE)); + TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, ARG_PORT, g_param_spec_int ("port", "port", "The port to send the packets to", - 0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE)); + 0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstmultifdsink_class->init = gst_tcp_server_sink_init_send; gstmultifdsink_class->wait = gst_tcp_server_sink_handle_wait; @@ -158,12 +163,8 @@ client_sock_fd = accept (sink->server_sock.fd, (struct sockaddr *) &client_address, &client_address_len); - if (client_sock_fd == -1) { - GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), - ("Could not accept client on server socket %d: %s (%d)", - sink->server_sock.fd, g_strerror (errno), errno)); - return FALSE; - } + if (client_sock_fd == -1) + goto accept_failed; gst_multi_fd_sink_add (GST_MULTI_FD_SINK (sink), client_sock_fd); @@ -171,6 +172,15 @@ inet_ntoa (client_address.sin_addr), client_sock_fd); return TRUE; + + /* ERRORS */ +accept_failed: + { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("Could not accept client on server socket %d: %s (%d)", + sink->server_sock.fd, g_strerror (errno), errno)); + return FALSE; + } } static void @@ -194,13 +204,18 @@ if (gst_poll_fd_can_read (set, &this->server_sock)) { /* handle new client connection on server socket */ - if (!gst_tcp_server_sink_handle_server_read (this)) { - GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), - ("client connection failed: %s", g_strerror (errno))); - return FALSE; - } + if (!gst_tcp_server_sink_handle_server_read (this)) + goto connection_failed; } return TRUE; + + /* ERRORS */ +connection_failed: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("client connection failed: %s", g_strerror (errno))); + return FALSE; + } } static void @@ -263,31 +278,23 @@ GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent); /* create sending server socket */ - if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); - return FALSE; - } + if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + goto no_socket; + GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d", this->server_sock.fd); /* make address reusable */ ret = 1; if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_REUSEADDR, - (void *) &ret, sizeof (ret)) < 0) { - gst_tcp_socket_close (&this->server_sock); - GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), - ("Could not setsockopt: %s", g_strerror (errno))); - return FALSE; - } + (void *) &ret, sizeof (ret)) < 0) + goto reuse_failed; + /* keep connection alive; avoids SIGPIPE during write */ ret = 1; if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_KEEPALIVE, - (void *) &ret, sizeof (ret)) < 0) { - gst_tcp_socket_close (&this->server_sock); - GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), - ("Could not setsockopt: %s", g_strerror (errno))); - return FALSE; - } + (void *) &ret, sizeof (ret)) < 0) + goto keepalive_failed; /* name the socket */ memset (&this->server_sin, 0, sizeof (this->server_sin)); @@ -299,30 +306,17 @@ GST_DEBUG_OBJECT (this, "binding server socket to address"); ret = bind (this->server_sock.fd, (struct sockaddr *) &this->server_sin, sizeof (this->server_sin)); - - if (ret) { - gst_tcp_socket_close (&this->server_sock); - switch (errno) { - default: - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("bind on port %d failed: %s", this->server_port, - g_strerror (errno))); - return FALSE; - break; - } - } + if (ret) + goto bind_failed; /* set the server socket to nonblocking */ fcntl (this->server_sock.fd, F_SETFL, O_NONBLOCK); GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d", this->server_sock.fd, TCP_BACKLOG); - if (listen (this->server_sock.fd, TCP_BACKLOG) == -1) { - gst_tcp_socket_close (&this->server_sock); - GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), - ("Could not listen on server socket: %s", g_strerror (errno))); - return FALSE; - } + if (listen (this->server_sock.fd, TCP_BACKLOG) == -1) + goto listen_failed; + GST_DEBUG_OBJECT (this, "listened on server socket %d, returning from connection setup", this->server_sock.fd); @@ -331,6 +325,46 @@ gst_poll_fd_ctl_read (parent->fdset, &this->server_sock, TRUE); return TRUE; + + /* ERRORS */ +no_socket: + { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } +reuse_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), + ("Could not setsockopt: %s", g_strerror (errno))); + return FALSE; + } +keepalive_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), + ("Could not setsockopt: %s", g_strerror (errno))); + return FALSE; + } +listen_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("Could not listen on server socket: %s", g_strerror (errno))); + return FALSE; + } +bind_failed: + { + gst_tcp_socket_close (&this->server_sock); + switch (errno) { + default: + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("bind on port %d failed: %s", this->server_port, + g_strerror (errno))); + break; + } + return FALSE; + } } static gboolean