gst_plugins_base/gst/tcp/gsttcpserversink.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    18  * Boston, MA 02111-1307, USA.
    18  * Boston, MA 02111-1307, USA.
    19  */
    19  */
    20 
    20 
    21 /**
    21 /**
    22  * SECTION:element-tcpserversink
    22  * SECTION:tcpserversink
       
    23  * @short_description: a sink that acts as a TCP server and sends data to
       
    24  *  multiple clients
    23  * @see_also: #multifdsink
    25  * @see_also: #multifdsink
    24  *
       
    25  * <refsect2>
       
    26  * <title>Example launch line</title>
       
    27  * |[
       
    28  * # server:
       
    29  * gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000
       
    30  * # client:
       
    31  * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2
       
    32  * ]| 
       
    33  * </refsect2>
       
    34  */
    26  */
    35 
    27 
    36 #ifdef HAVE_CONFIG_H
    28 #ifdef HAVE_CONFIG_H
    37 #include "config.h"
    29 #include "config.h"
    38 #endif
    30 #endif
       
    31 #ifdef __SYMBIAN32__
       
    32 #include "gst/gst-i18n-plugin.h"
       
    33 #else
    39 #include <gst/gst-i18n-plugin.h>
    34 #include <gst/gst-i18n-plugin.h>
       
    35 #endif
    40 #include <string.h>             /* memset */
    36 #include <string.h>             /* memset */
    41 
    37 
    42 #include <sys/ioctl.h>
    38 #include <sys/ioctl.h>
    43 
    39 
    44 #ifdef HAVE_FIONREAD_IN_SYS_FILIO
    40 #ifdef HAVE_FIONREAD_IN_SYS_FILIO
   107   gobject_class->get_property = gst_tcp_server_sink_get_property;
   103   gobject_class->get_property = gst_tcp_server_sink_get_property;
   108   gobject_class->finalize = gst_tcp_server_sink_finalize;
   104   gobject_class->finalize = gst_tcp_server_sink_finalize;
   109 
   105 
   110   g_object_class_install_property (gobject_class, ARG_HOST,
   106   g_object_class_install_property (gobject_class, ARG_HOST,
   111       g_param_spec_string ("host", "host", "The host/IP to send the packets to",
   107       g_param_spec_string ("host", "host", "The host/IP to send the packets to",
   112           TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   108           TCP_DEFAULT_HOST, G_PARAM_READWRITE));
   113   g_object_class_install_property (gobject_class, ARG_PORT,
   109   g_object_class_install_property (gobject_class, ARG_PORT,
   114       g_param_spec_int ("port", "port", "The port to send the packets to",
   110       g_param_spec_int ("port", "port", "The port to send the packets to",
   115           0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT,
   111           0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, G_PARAM_READWRITE));
   116           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   117 
   112 
   118   gstmultifdsink_class->init = gst_tcp_server_sink_init_send;
   113   gstmultifdsink_class->init = gst_tcp_server_sink_init_send;
   119   gstmultifdsink_class->wait = gst_tcp_server_sink_handle_wait;
   114   gstmultifdsink_class->wait = gst_tcp_server_sink_handle_wait;
   120   gstmultifdsink_class->close = gst_tcp_server_sink_close;
   115   gstmultifdsink_class->close = gst_tcp_server_sink_close;
   121   gstmultifdsink_class->removed = gst_tcp_server_sink_removed;
   116   gstmultifdsink_class->removed = gst_tcp_server_sink_removed;
   161   client_address_len = 0;
   156   client_address_len = 0;
   162 
   157 
   163   client_sock_fd =
   158   client_sock_fd =
   164       accept (sink->server_sock.fd, (struct sockaddr *) &client_address,
   159       accept (sink->server_sock.fd, (struct sockaddr *) &client_address,
   165       &client_address_len);
   160       &client_address_len);
   166   if (client_sock_fd == -1)
   161   if (client_sock_fd == -1) {
   167     goto accept_failed;
       
   168 
       
   169   gst_multi_fd_sink_add (GST_MULTI_FD_SINK (sink), client_sock_fd);
       
   170 
       
   171   GST_DEBUG_OBJECT (sink, "added new client ip %s with fd %d",
       
   172       inet_ntoa (client_address.sin_addr), client_sock_fd);
       
   173 
       
   174   return TRUE;
       
   175 
       
   176   /* ERRORS */
       
   177 accept_failed:
       
   178   {
       
   179     GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
   162     GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
   180         ("Could not accept client on server socket %d: %s (%d)",
   163         ("Could not accept client on server socket %d: %s (%d)",
   181             sink->server_sock.fd, g_strerror (errno), errno));
   164             sink->server_sock.fd, g_strerror (errno), errno));
   182     return FALSE;
   165     return FALSE;
   183   }
   166   }
       
   167 
       
   168   gst_multi_fd_sink_add (GST_MULTI_FD_SINK (sink), client_sock_fd);
       
   169 
       
   170   GST_DEBUG_OBJECT (sink, "added new client ip %s with fd %d",
       
   171       inet_ntoa (client_address.sin_addr), client_sock_fd);
       
   172 
       
   173   return TRUE;
   184 }
   174 }
   185 
   175 
   186 static void
   176 static void
   187 gst_tcp_server_sink_removed (GstMultiFdSink * sink, int fd)
   177 gst_tcp_server_sink_removed (GstMultiFdSink * sink, int fd)
   188 {
   178 {
   202 {
   192 {
   203   GstTCPServerSink *this = GST_TCP_SERVER_SINK (sink);
   193   GstTCPServerSink *this = GST_TCP_SERVER_SINK (sink);
   204 
   194 
   205   if (gst_poll_fd_can_read (set, &this->server_sock)) {
   195   if (gst_poll_fd_can_read (set, &this->server_sock)) {
   206     /* handle new client connection on server socket */
   196     /* handle new client connection on server socket */
   207     if (!gst_tcp_server_sink_handle_server_read (this))
   197     if (!gst_tcp_server_sink_handle_server_read (this)) {
   208       goto connection_failed;
   198       GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
       
   199           ("client connection failed: %s", g_strerror (errno)));
       
   200       return FALSE;
       
   201     }
   209   }
   202   }
   210   return TRUE;
   203   return TRUE;
   211 
       
   212   /* ERRORS */
       
   213 connection_failed:
       
   214   {
       
   215     GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL),
       
   216         ("client connection failed: %s", g_strerror (errno)));
       
   217     return FALSE;
       
   218   }
       
   219 }
   204 }
   220 
   205 
   221 static void
   206 static void
   222 gst_tcp_server_sink_set_property (GObject * object, guint prop_id,
   207 gst_tcp_server_sink_set_property (GObject * object, guint prop_id,
   223     const GValue * value, GParamSpec * pspec)
   208     const GValue * value, GParamSpec * pspec)
   276 {
   261 {
   277   int ret;
   262   int ret;
   278   GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent);
   263   GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent);
   279 
   264 
   280   /* create sending server socket */
   265   /* create sending server socket */
   281   if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
   266   if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
   282     goto no_socket;
   267     GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM);
   283 
   268     return FALSE;
       
   269   }
   284   GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d",
   270   GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d",
   285       this->server_sock.fd);
   271       this->server_sock.fd);
   286 
   272 
   287   /* make address reusable */
   273   /* make address reusable */
   288   ret = 1;
   274   ret = 1;
   289   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_REUSEADDR,
   275   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_REUSEADDR,
   290           (void *) &ret, sizeof (ret)) < 0)
   276           (void *) &ret, sizeof (ret)) < 0) {
   291     goto reuse_failed;
   277     gst_tcp_socket_close (&this->server_sock);
   292 
   278     GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
       
   279         ("Could not setsockopt: %s", g_strerror (errno)));
       
   280     return FALSE;
       
   281   }
   293   /* keep connection alive; avoids SIGPIPE during write */
   282   /* keep connection alive; avoids SIGPIPE during write */
   294   ret = 1;
   283   ret = 1;
   295   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_KEEPALIVE,
   284   if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_KEEPALIVE,
   296           (void *) &ret, sizeof (ret)) < 0)
   285           (void *) &ret, sizeof (ret)) < 0) {
   297     goto keepalive_failed;
   286     gst_tcp_socket_close (&this->server_sock);
       
   287     GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
       
   288         ("Could not setsockopt: %s", g_strerror (errno)));
       
   289     return FALSE;
       
   290   }
   298 
   291 
   299   /* name the socket */
   292   /* name the socket */
   300   memset (&this->server_sin, 0, sizeof (this->server_sin));
   293   memset (&this->server_sin, 0, sizeof (this->server_sin));
   301   this->server_sin.sin_family = AF_INET;        /* network socket */
   294   this->server_sin.sin_family = AF_INET;        /* network socket */
   302   this->server_sin.sin_port = htons (this->server_port);        /* on port */
   295   this->server_sin.sin_port = htons (this->server_port);        /* on port */
   304 
   297 
   305   /* bind it */
   298   /* bind it */
   306   GST_DEBUG_OBJECT (this, "binding server socket to address");
   299   GST_DEBUG_OBJECT (this, "binding server socket to address");
   307   ret = bind (this->server_sock.fd, (struct sockaddr *) &this->server_sin,
   300   ret = bind (this->server_sock.fd, (struct sockaddr *) &this->server_sin,
   308       sizeof (this->server_sin));
   301       sizeof (this->server_sin));
   309   if (ret)
   302 
   310     goto bind_failed;
   303   if (ret) {
   311 
       
   312   /* set the server socket to nonblocking */
       
   313   fcntl (this->server_sock.fd, F_SETFL, O_NONBLOCK);
       
   314 
       
   315   GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d",
       
   316       this->server_sock.fd, TCP_BACKLOG);
       
   317   if (listen (this->server_sock.fd, TCP_BACKLOG) == -1)
       
   318     goto listen_failed;
       
   319 
       
   320   GST_DEBUG_OBJECT (this,
       
   321       "listened on server socket %d, returning from connection setup",
       
   322       this->server_sock.fd);
       
   323 
       
   324   gst_poll_add_fd (parent->fdset, &this->server_sock);
       
   325   gst_poll_fd_ctl_read (parent->fdset, &this->server_sock, TRUE);
       
   326 
       
   327   return TRUE;
       
   328 
       
   329   /* ERRORS */
       
   330 no_socket:
       
   331   {
       
   332     GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM);
       
   333     return FALSE;
       
   334   }
       
   335 reuse_failed:
       
   336   {
       
   337     gst_tcp_socket_close (&this->server_sock);
       
   338     GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
       
   339         ("Could not setsockopt: %s", g_strerror (errno)));
       
   340     return FALSE;
       
   341   }
       
   342 keepalive_failed:
       
   343   {
       
   344     gst_tcp_socket_close (&this->server_sock);
       
   345     GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL),
       
   346         ("Could not setsockopt: %s", g_strerror (errno)));
       
   347     return FALSE;
       
   348   }
       
   349 listen_failed:
       
   350   {
       
   351     gst_tcp_socket_close (&this->server_sock);
       
   352     GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
       
   353         ("Could not listen on server socket: %s", g_strerror (errno)));
       
   354     return FALSE;
       
   355   }
       
   356 bind_failed:
       
   357   {
       
   358     gst_tcp_socket_close (&this->server_sock);
   304     gst_tcp_socket_close (&this->server_sock);
   359     switch (errno) {
   305     switch (errno) {
   360       default:
   306       default:
   361         GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
   307         GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
   362             ("bind on port %d failed: %s", this->server_port,
   308             ("bind on port %d failed: %s", this->server_port,
   363                 g_strerror (errno)));
   309                 g_strerror (errno)));
       
   310         return FALSE;
   364         break;
   311         break;
   365     }
   312     }
   366     return FALSE;
   313   }
   367   }
   314 
       
   315   /* set the server socket to nonblocking */
       
   316   fcntl (this->server_sock.fd, F_SETFL, O_NONBLOCK);
       
   317 
       
   318   GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d",
       
   319       this->server_sock.fd, TCP_BACKLOG);
       
   320   if (listen (this->server_sock.fd, TCP_BACKLOG) == -1) {
       
   321     gst_tcp_socket_close (&this->server_sock);
       
   322     GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL),
       
   323         ("Could not listen on server socket: %s", g_strerror (errno)));
       
   324     return FALSE;
       
   325   }
       
   326   GST_DEBUG_OBJECT (this,
       
   327       "listened on server socket %d, returning from connection setup",
       
   328       this->server_sock.fd);
       
   329 
       
   330   gst_poll_add_fd (parent->fdset, &this->server_sock);
       
   331   gst_poll_fd_ctl_read (parent->fdset, &this->server_sock, TRUE);
       
   332 
       
   333   return TRUE;
   368 }
   334 }
   369 
   335 
   370 static gboolean
   336 static gboolean
   371 gst_tcp_server_sink_close (GstMultiFdSink * parent)
   337 gst_tcp_server_sink_close (GstMultiFdSink * parent)
   372 {
   338 {