]> git.sesse.net Git - vlc/commitdiff
Patch by Rémi Denis-Courmont to include TCP listening sockets in the abstraction...
authorClément Stenac <zorglub@videolan.org>
Sun, 6 Jun 2004 12:45:32 +0000 (12:45 +0000)
committerClément Stenac <zorglub@videolan.org>
Sun, 6 Jun 2004 12:45:32 +0000 (12:45 +0000)
include/network.h
modules/control/telnet.c
modules/misc/network/ipv4.c
modules/misc/network/ipv6.c
src/misc/net.c

index d44157e2c89158bd3eadb6730186689310f9007f..5aa4b8ef0cefb42be8cbdbcd3d5ce523d990ab7b 100644 (file)
@@ -46,6 +46,7 @@ struct network_socket_t
 /* Socket types */
 #define NETWORK_UDP 1
 #define NETWORK_TCP 2
+#define NETWORK_TCP_PASSIVE 3
 
 
 typedef struct
@@ -165,6 +166,9 @@ static inline void vlc_UrlClean( vlc_url_t *url )
 #define net_OpenTCP(a, b, c) __net_OpenTCP(VLC_OBJECT(a), b, c)
 VLC_EXPORT( int, __net_OpenTCP, ( vlc_object_t *p_this, char *psz_host, int i_port ) );
 
+#define net_ListenTCP(a, b, c) __net_ListenTCP(VLC_OBJECT(a), b, c)
+VLC_EXPORT( int, __net_ListenTCP, ( vlc_object_t *p_this, char *psz_localaddr, int i_port ) );
+
 #define net_OpenUDP(a, b, c, d, e ) __net_OpenUDP(VLC_OBJECT(a), b, c, d, e)
 VLC_EXPORT( int, __net_OpenUDP, ( vlc_object_t *p_this, char *psz_bind, int i_bind, char *psz_server, int i_server ) );
 
index 7fcbc4cd90c98fb7e32fe53ea16a6219a6224f3e..611d8acfd4966666a1dee4717db6a51aea76dc79 100644 (file)
 #   include <winsock.h>
 #elif defined( WIN32 )
 #   include <winsock2.h>
-#   include <ws2tcpip.h>
-#   ifndef IN_MULTICAST
-#       define IN_MULTICAST(a) IN_CLASSD(a)
-#   endif
 #else
-#   include <netdb.h>                                         /* hostent ... */
 #   include <sys/socket.h>
-#   include <netinet/in.h>
-#   ifdef HAVE_ARPA_INET_H
-#       include <arpa/inet.h>                    /* inet_ntoa(), inet_aton() */
-#   endif
 #endif
 
 #include "network.h"
@@ -72,8 +63,6 @@
 #define SOCKET_CLOSE(a)    close(a)
 #endif
 
-#define LISTEN_BACKLOG 100
-
 #define READ_MODE_PWD 1
 #define READ_MODE_CMD 2
 #define WRITE_MODE_PWD 3 // when we write the word "Password:"
@@ -127,7 +116,6 @@ typedef struct
 
 static char* MessageToString( vlm_message_t* , int );
 static void Write_message( telnet_client_t * , vlm_message_t* , char * , int );
-static int  SocketListen( intf_thread_t * , int );
 
 struct intf_sys_t
 {
@@ -159,7 +147,7 @@ static int Open( vlc_object_t *p_this )
     p_intf->pf_run = Run;
 
     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
-    if( ( p_intf->p_sys->fd = SocketListen( p_intf , i_telnetport ) ) < 0 )
+    if( ( p_intf->p_sys->fd = net_ListenTCP( p_intf , "", i_telnetport ) ) < 0 )
     {
         msg_Err( p_intf, "cannot listen for telnet" );
         free( p_intf->p_sys );
@@ -207,7 +195,6 @@ static void Run( intf_thread_t *p_intf )
 {
     intf_sys_t     *p_sys = p_intf->p_sys;
     struct timeval  timeout;
-    int             i_sock_size = sizeof( struct sockaddr_in );
     char           *s_password;
 
     s_password = config_GetPsz( p_intf, "telnet-password" );
@@ -218,13 +205,12 @@ static void Run( intf_thread_t *p_intf )
         fd_set          fds_write;
         int             i_handle_max = 0;
         int             i_ret;
-        struct          sockaddr_in sock2;
         int             i_len;
         int             fd;
         int             i;
 
         /* if a new client wants to communicate */
-        fd = accept( p_sys->fd, (struct sockaddr *)&sock2, &i_sock_size );
+        fd = accept( p_sys->fd, NULL, NULL );
         if( fd > 0 )
         {
             telnet_client_t *cl;
@@ -440,81 +426,6 @@ static void Write_message( telnet_client_t * client, vlm_message_t * message, ch
     free( psz_message );
 }
 
-/* Does what we want except select and accept */
-static int SocketListen( intf_thread_t *p_intf , int i_port )
-{
-    struct sockaddr_in sock;
-    int fd;
-    int i_opt;
-    int i_flags;
-
-    /* open socket */
-    fd = socket( AF_INET, SOCK_STREAM, 0 );
-    if( fd < 0 )
-    {
-        msg_Err( p_intf, "cannot open socket" );
-        goto socket_failed;
-    }
-    /* reuse socket */
-    i_opt = 1;
-    if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
-                    (void *) &i_opt, sizeof( i_opt ) ) < 0 )
-    {
-        msg_Warn( p_intf, "cannot configure socket (SO_REUSEADDR)" );
-    }
-
-    /* fill p_socket structure */
-    memset( &sock, 0, sizeof( struct sockaddr_in ) );
-    sock.sin_family = AF_INET;                             /* family */
-    sock.sin_port = htons( (uint16_t)i_port );
-    sock.sin_addr.s_addr = INADDR_ANY;
-
-    /* bind it */
-    if( bind( fd, (struct sockaddr *)&sock, sizeof( struct sockaddr_in ) ) < 0 )
-    {
-        msg_Err( p_intf, "cannot bind socket" );
-        goto socket_failed;
-    }
-
-   /* set to non-blocking */
-#if defined( WIN32 ) || defined( UNDER_CE )
-    {
-        unsigned long i_dummy = 1;
-        if( ioctlsocket( fd, FIONBIO, &i_dummy ) != 0 )
-        {
-            msg_Err( p_intf, "cannot set socket to non-blocking mode" );
-            goto socket_failed;
-        }
-    }
-#else
-    if( ( i_flags = fcntl( fd, F_GETFL, 0 ) ) < 0 )
-    {
-        msg_Err( p_intf, "cannot F_GETFL socket" );
-        goto socket_failed;
-    }
-    if( fcntl( fd, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
-    {
-        msg_Err( p_intf, "cannot F_SETFL O_NONBLOCK" );
-        goto socket_failed;
-    }
-#endif
-    /* listen */
-    if( listen( fd, LISTEN_BACKLOG ) < 0 )
-    {
-        msg_Err( p_intf, "cannot listen socket" );
-        goto socket_failed;
-    }
-
-    return fd;
-
-socket_failed:
-    if( fd >= 0 )
-    {
-        SOCKET_CLOSE( fd );
-    }
-    return -1;
-}
-
 /* we need the level of the message to put a beautiful indentation.
    first level is 0 */
 static char* MessageToString( vlm_message_t* message , int i_level )
index a638eecc323df0bb448dc5b033fbe9a03eb2fe67..03e4e4d8c6184c0d56d6659dcdd2c94cbe594d46 100644 (file)
@@ -437,43 +437,24 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
 }
 
 /*****************************************************************************
- * OpenTCP: open a TCP socket
+ * SocketTCP: create a TCP socket
  *****************************************************************************
- * psz_server_addr, i_server_port : address and port used for the connect()
- *   system call. If i_server_port == 0, 80 is used.
- * Other parameters are ignored.
  * This function returns -1 in case of error.
  *****************************************************************************/
-static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+static int SocketTCP( vlc_object_t * p_this )
 {
-    char * psz_server_addr = p_socket->psz_server_addr;
-    int i_server_port = p_socket->i_server_port;
-
     int i_handle;
-    struct sockaddr_in sock;
-
-    if( i_server_port == 0 )
-    {
-        i_server_port = 80;
-    }
-
-    /* Open a SOCK_STREAM (TCP) socket, in the AF_INET domain, automatic (0)
+    
+    /* Open a SOCK_STREAM (TCP) socket, in the PF_INET domain, automatic (0)
      * protocol */
-    if( (i_handle = socket( AF_INET, SOCK_STREAM, 0 )) == -1 )
+    if( (i_handle = socket( PF_INET, SOCK_STREAM, 0 )) == -1 )
     {
 #ifdef HAVE_ERRNO_H
         msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
 #else
         msg_Warn( p_this, "cannot create socket" );
 #endif
-        goto error;
-    }
-
-    /* Build remote address */
-    if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
-    {
-        msg_Dbg( p_this, "could not build local address" );
-        goto error;
+        return -1;
     }
 
     /* Set to non-blocking */
@@ -496,6 +477,40 @@ static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
     }
 #endif
 
+    return i_handle;
+}
+
+/*****************************************************************************
+ * OpenTCP: open a TCP socket
+ *****************************************************************************
+ * psz_server_addr, i_server_port : address and port used for the connect()
+ *   system call. If i_server_port == 0, 80 is used.
+ * Other parameters are ignored.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+    char * psz_server_addr = p_socket->psz_server_addr;
+    int i_server_port = p_socket->i_server_port;
+
+    int i_handle;
+    struct sockaddr_in sock;
+
+    if( i_server_port == 0 )
+    {
+        i_server_port = 80;
+    }
+
+    if( (i_handle = SocketTCP( p_this )) == -1 )
+        return VLC_EGENERIC;
+
+    /* Build remote address */
+    if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+    {
+        msg_Dbg( p_this, "could not build local address" );
+        goto error;
+    }
+
     /* Connect the socket */
     if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
     {
@@ -580,15 +595,76 @@ static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
     return VLC_SUCCESS;
 
 error:
-    if( i_handle > 0 )
+    close( i_handle );
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * ListenTCP: open a TCP passive socket (server-side)
+ *****************************************************************************
+ * psz_server_addr, i_server_port : address and port used for the bind()
+ *   system call. If i_server_port == 0, 80 is used.
+ * Other parameters are ignored.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int ListenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+    char * psz_server_addr = p_socket->psz_server_addr;
+    int i_server_port = p_socket->i_server_port;
+
+    int i_handle, i_dummy = 1;
+    struct sockaddr_in sock;
+
+    if( (i_handle = SocketTCP( p_this )) == -1 )
+        return VLC_EGENERIC;
+
+    if ( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
+                (void *)&i_dummy, sizeof( i_dummy ) ) == -1 )
     {
-        close( i_handle );
+        msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
+    }
+
+    /* Build remote address */
+    if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
+    {
+        msg_Dbg( p_this, "could not build local address" );
+        return VLC_EGENERIC;
+    }
+    
+    /* Bind the socket */
+    if( bind( i_handle, (struct sockaddr *) &sock, sizeof( sock )) == -1 )
+    {
+#ifdef HAVE_ERRNO_H
+        msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
+#else
+        msg_Err( p_this, "cannot bind socket" );
+#endif
+        goto error;
+    }
+    /* Listen */
+    if( listen( i_handle, 100 ) == -1 )
+    {
+#ifdef HAVE_ERRNO_H
+         msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
+                  strerror(errno) );
+#else
+         msg_Err( p_this, "cannot bring the socket in listening mode" );
+#endif
+         goto error;
     }
+
+    p_socket->i_handle = i_handle;
+    p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
+    return VLC_SUCCESS;
+
+error:
+    close( i_handle );
     return VLC_EGENERIC;
 }
 
 /*****************************************************************************
- * NetOpen: wrapper around OpenUDP and OpenTCP
+ * NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP
  *****************************************************************************/
 static int NetOpen( vlc_object_t * p_this )
 {
@@ -598,6 +674,10 @@ static int NetOpen( vlc_object_t * p_this )
     {
         return OpenUDP( p_this, p_socket );
     }
+    else if( p_socket->i_type == NETWORK_TCP_PASSIVE )
+    {
+        return ListenTCP( p_this, p_socket );
+    }
     else
     {
         return OpenTCP( p_this, p_socket );
index c09dd98665c4c704228e61fc9e8b57b25ec7de95..a9ab69399b6010005cbe20bb9ccec5fe4272be87 100644 (file)
@@ -77,7 +77,7 @@ static const struct in6_addr in6addr_any = {{IN6ADDR_ANY_INIT}};
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int Open( vlc_object_t * );
+static int NetOpen( vlc_object_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -85,7 +85,7 @@ static int Open( vlc_object_t * );
 vlc_module_begin();
     set_description( _("IPv6 network abstraction layer") );
     set_capability( "network", 40 );
-    set_callbacks( Open, NULL );
+    set_callbacks( NetOpen, NULL );
 vlc_module_end();
 
 /*****************************************************************************
@@ -437,6 +437,50 @@ static int OpenUDP( vlc_object_t * p_this, network_socket_t * p_socket )
     return( 0 );
 }
 
+/*****************************************************************************
+ * SocketTCP: create a TCP socket
+ *****************************************************************************
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int SocketTCP( vlc_object_t * p_this )
+{
+    int i_handle;
+    
+    /* Open a SOCK_STREAM (TCP) socket, in the PF_INET6 domain, automatic (0)
+     * protocol */
+    if( (i_handle = socket( PF_INET6, SOCK_STREAM, 0 )) == -1 )
+    {
+#ifdef HAVE_ERRNO_H
+        msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
+#else
+        msg_Warn( p_this, "cannot create socket" );
+#endif
+        return -1;
+    }
+
+    /* Set to non-blocking */
+#if defined( WIN32 ) || defined( UNDER_CE )
+    {
+        unsigned long i_dummy = 1;
+        if( ioctlsocket( i_handle, FIONBIO, &i_dummy ) != 0 )
+        {
+            msg_Err( p_this, "cannot set socket to non-blocking mode" );
+        }
+    }
+#elif defined( HAVE_ERRNO_H )
+    {
+        int i_flags;
+        if( ( i_flags = fcntl( i_handle, F_GETFL, 0 ) ) < 0 ||
+            fcntl( i_handle, F_SETFL, i_flags | O_NONBLOCK ) < 0 )
+        {
+            msg_Err( p_this, "cannot set socket to non-blocking mode" );
+        }
+    }
+#endif
+
+    return i_handle;
+}
+
 /*****************************************************************************
  * OpenTCP: open a TCP socket
  *****************************************************************************
@@ -458,40 +502,171 @@ static int OpenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
         i_server_port = 80;
     }
 
-    /* Open a SOCK_STREAM (TCP) socket, in the AF_INET6 domain, automatic (0)
-     * protocol */
-    if( (i_handle = socket( AF_INET6, SOCK_STREAM, 0 )) == -1 )
+    if( (i_handle = SocketTCP( p_this )) == -1 )
+        return VLC_EGENERIC;
+
+    /* Build remote address */
+    if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
+        goto error;
+
+    /* Connect the socket */
+    if( connect( i_handle, (struct sockaddr *) &sock, sizeof( sock ) ) == -1 )
     {
-        msg_Warn( p_this, "cannot create socket (%s)", strerror(errno) );
-        return( -1 );
+#if defined( WIN32 ) || defined( UNDER_CE )
+        if( WSAGetLastError() == WSAEWOULDBLOCK )
+#elif defined( HAVE_ERRNO_H )
+        if( errno == EINPROGRESS )
+#else
+        if( 0 )
+#endif
+        {
+            int i_ret, i_opt, i_opt_size = sizeof( i_opt ), i_max_count;
+            struct timeval timeout;
+            vlc_value_t val;
+            fd_set fds;
+
+            /* FIXME: There is no ipv6-timeout option, so we use ipv4-timeout
+             * instead */
+            if( !var_Type( p_this, "ipv4-timeout" ) )
+            {
+                var_Create( p_this, "ipv4-timeout",
+                            VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+            }
+            var_Get( p_this, "ipv4-timeout", &val );
+            i_max_count = val.i_int * 1000 / 100000 /* timeout.tv_usec */;
+
+            msg_Dbg( p_this, "connection in progress" );
+            do
+            {
+                if( p_this->b_die || i_max_count <= 0 )
+                {
+                    msg_Dbg( p_this, "connection aborted" );
+                    goto error;
+                }
+
+                i_max_count--;
+
+                /* Initialize file descriptor set */
+                FD_ZERO( &fds );
+                FD_SET( i_handle, &fds );
+
+                /* We'll wait 0.1 second if nothing happens */
+                timeout.tv_sec = 0;
+                timeout.tv_usec = 100000;
+
+            } while( ( i_ret = select( i_handle + 1, NULL, &fds, NULL,
+                                       &timeout ) ) == 0 ||
+#if defined( WIN32 ) || defined( UNDER_CE )
+                     ( i_ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK ) );
+#elif defined( HAVE_ERRNO_H )
+                     ( i_ret < 0 && errno == EINTR ) );
+#else
+                     ( i_ret < 0 ) );
+#endif
+
+            if( i_ret < 0 )
+            {
+                msg_Warn( p_this, "cannot connect socket (select failed)" );
+                goto error;
+            }
+
+#if !defined( SYS_BEOS )
+            if( getsockopt( i_handle, SOL_SOCKET, SO_ERROR, (void*)&i_opt,
+                            &i_opt_size ) == -1 || i_opt != 0 )
+            {
+                msg_Warn( p_this, "cannot connect socket (SO_ERROR)" );
+                goto error;
+            }
+#endif
+        }
+        else
+        {
+#if defined( HAVE_ERRNO_H )
+            msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
+#else
+            msg_Warn( p_this, "cannot connect socket" );
+#endif
+            goto error;
+        }
+    }
+
+    p_socket->i_handle = i_handle;
+    p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
+    return VLC_SUCCESS;
+
+error:
+    close( i_handle );
+    return VLC_EGENERIC;
+}
+
+/*****************************************************************************
+ * ListenTCP: open a TCP passive socket (server-side)
+ *****************************************************************************
+ * psz_server_addr, i_server_port : address and port used for the bind()
+ *   system call. If i_server_port == 0, 80 is used.
+ * Other parameters are ignored.
+ * This function returns -1 in case of error.
+ *****************************************************************************/
+static int ListenTCP( vlc_object_t * p_this, network_socket_t * p_socket )
+{
+    char * psz_server_addr = p_socket->psz_server_addr;
+    int i_server_port = p_socket->i_server_port;
+
+    int i_handle, i_dummy = 1;
+    struct sockaddr_in6 sock;
+
+    if( (i_handle = SocketTCP( p_this )) == -1 )
+        return VLC_EGENERIC;
+
+    if ( setsockopt( i_handle, SOL_SOCKET, SO_REUSEADDR,
+                (void *)&i_dummy, sizeof( i_dummy ) ) == -1 )
+    {
+        msg_Warn( p_this, "cannot configure socket (SO_REUSEADDR)" );
     }
 
     /* Build remote address */
     if ( BuildAddr( p_this, &sock, psz_server_addr, i_server_port ) == -1 )
     {
-        close( i_handle );
-        return( -1 );
+        msg_Dbg( p_this, "could not build local address" );
+        return VLC_EGENERIC;
     }
-
-    /* Connect the socket */
-    if( connect( i_handle, (struct sockaddr *) &sock,
-                 sizeof( sock ) ) == (-1) )
+    
+    /* Bind the socket */
+    if( bind( i_handle, (struct sockaddr *) &sock, sizeof( sock )) == -1 )
     {
-        msg_Warn( p_this, "cannot connect socket (%s)", strerror(errno) );
-        close( i_handle );
-        return( -1 );
+#ifdef HAVE_ERRNO_H
+        msg_Err( p_this, "cannot bind socket (%s)", strerror(errno) );
+#else
+        msg_Err( p_this, "cannot bind socket" );
+#endif
+        goto error;
+    }
+    /* Listen */
+    if( listen( i_handle, 100 ) == -1 )
+    {
+#ifdef HAVE_ERRNO_H
+         msg_Err( p_this, "cannot bring the socket in listening mode (%s)",
+                  strerror(errno) );
+#else
+         msg_Err( p_this, "cannot bring the socket in listening mode" );
+#endif
+         goto error;
     }
 
     p_socket->i_handle = i_handle;
     p_socket->i_mtu = 0; /* There is no MTU notion in TCP */
+    return VLC_SUCCESS;
 
-    return( 0 );
+error:
+    close( i_handle );
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
- * Open: wrapper around OpenUDP and OpenTCP
+ * NetOpen: wrapper around OpenUDP, ListenTCP and OpenTCP
  *****************************************************************************/
-static int Open( vlc_object_t * p_this )
+static int NetOpen( vlc_object_t * p_this )
 {
     network_socket_t * p_socket = p_this->p_private;
 
@@ -499,6 +674,10 @@ static int Open( vlc_object_t * p_this )
     {
         return OpenUDP( p_this, p_socket );
     }
+    else if( p_socket->i_type == NETWORK_TCP_PASSIVE )
+    {
+        return ListenTCP( p_this, p_socket );
+    }
     else
     {
         return OpenTCP( p_this, p_socket );
index 361fc80e71cd807a3f3518f102ea6e65e2ae9e88..e15138e9bdafdd5904766ff68d778457ace95a19 100644 (file)
@@ -110,6 +110,58 @@ int __net_OpenTCP( vlc_object_t *p_this, char *psz_host, int i_port )
     return sock.i_handle;
 }
 
+/*****************************************************************************
+ * __net_ListenTCP:
+ *****************************************************************************
+ * Open a TCP listening socket and return it
+ *****************************************************************************/
+int __net_ListenTCP( vlc_object_t *p_this, char *psz_host, int i_port )
+{
+    vlc_value_t      val;
+    void            *private;
+
+    char            *psz_network = "";
+    network_socket_t sock;
+    module_t         *p_network;
+
+    /* Check if we have force ipv4 or ipv6 */
+    var_Create( p_this, "ipv4", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Get( p_this, "ipv4", &val );
+    if( val.b_bool )
+    {
+        psz_network = "ipv4";
+    }
+
+    var_Create( p_this, "ipv6", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Get( p_this, "ipv6", &val );
+    if( val.b_bool )
+    {
+        psz_network = "ipv6";
+    }
+
+    /* Prepare the network_socket_t structure */
+    sock.i_type = NETWORK_TCP_PASSIVE;
+    sock.psz_bind_addr   = "";
+    sock.i_bind_port     = 0;
+    sock.psz_server_addr = psz_host;
+    sock.i_server_port   = i_port;
+    sock.i_ttl           = 0;
+
+    msg_Dbg( p_this, "net: listening to '%s:%d'", psz_host, i_port );
+    private = p_this->p_private;
+    p_this->p_private = (void*)&sock;
+    if( !( p_network = module_Need( p_this, "network", psz_network, 0 ) ) )
+    {
+        msg_Dbg( p_this, "net: listening to '%s:%d' failed",
+                 psz_host, i_port );
+        return -1;
+    }
+    module_Unneed( p_this, p_network );
+    p_this->p_private = private;
+
+    return sock.i_handle;
+}
+
 /*****************************************************************************
  * __net_OpenUDP:
  *****************************************************************************