* Preamble
*****************************************************************************/
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
#include <vlc_interface.h>
#include <vlc_input.h>
#include <stdbool.h>
-#include <sys/stat.h>
#include <errno.h>
-#include <fcntl.h>
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
"to protect this interface. The default value is \"admin\"." )
#define TELNETPWD_DEFAULT "admin"
-vlc_module_begin();
- set_shortname( "Telnet" );
- set_category( CAT_INTERFACE );
- set_subcategory( SUBCAT_INTERFACE_CONTROL );
+vlc_module_begin ()
+ set_shortname( "Telnet" )
+ set_category( CAT_INTERFACE )
+ set_subcategory( SUBCAT_INTERFACE_CONTROL )
add_string( "telnet-host", "", NULL, TELNETHOST_TEXT,
- TELNETHOST_LONGTEXT, VLC_TRUE );
+ TELNETHOST_LONGTEXT, true )
add_integer( "telnet-port", TELNETPORT_DEFAULT, NULL, TELNETPORT_TEXT,
- TELNETPORT_LONGTEXT, VLC_TRUE );
+ TELNETPORT_LONGTEXT, true )
add_password( "telnet-password", TELNETPWD_DEFAULT, NULL, TELNETPWD_TEXT,
- TELNETPWD_LONGTEXT, VLC_TRUE );
- set_description( _("VLM remote control interface") );
- add_category_hint( "VLM", NULL, VLC_FALSE );
- set_capability( "interface", 0 );
- set_callbacks( Open , Close );
-vlc_module_end();
+ TELNETPWD_LONGTEXT, true )
+ set_description( N_("VLM remote control interface") )
+ add_category_hint( "VLM", NULL, false )
+ set_capability( "interface", 0 )
+ set_callbacks( Open , Close )
+vlc_module_end ()
/*****************************************************************************
* Local prototypes.
* This code relies upon the fact the url.i_port is 0 if the :PORT
* option is missing from --telnet-host.
*/
-static int getPort(intf_thread_t *p_intf, vlc_url_t url, int i_port)
+static int getPort(intf_thread_t *p_intf, const vlc_url_t *url, int i_port)
{
- // Print error if two different ports have been specified
- if (url.i_port != 0 &&
- i_port != TELNETPORT_DEFAULT &&
- url.i_port != i_port )
- {
- msg_Err( p_intf, "ignoring port %d and using %d", url.i_port,
- i_port);
- }
- if (i_port != TELNETPORT_DEFAULT)
- {
- return i_port;
- }
- if (url.i_port != 0)
- {
- return url.i_port;
- }
+ if (i_port == TELNETPORT_DEFAULT && url->i_port != 0)
+ i_port = url->i_port;
+ if (url->i_port != 0 && url->i_port != i_port)
+ // Print error if two different ports have been specified
+ msg_Warn( p_intf, "ignoring port %d (using %d)", url->i_port, i_port );
return i_port;
}
msg_Info( p_intf, "using the VLM interface plugin..." );
- i_telnetport = config_GetInt( p_intf, "telnet-port" );
- psz_address = config_GetPsz( p_intf, "telnet-host" );
-
+ i_telnetport = var_InheritInteger( p_intf, "telnet-port" );
+ psz_address = var_InheritString( p_intf, "telnet-host" );
vlc_UrlParse(&url, psz_address, 0);
+ free( psz_address );
// There might be two ports given, resolve any potentially
// conflict
- url.i_port = getPort(p_intf, url, i_telnetport);
+ url.i_port = getPort(p_intf, &url, i_telnetport);
p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
- if( ( p_intf->p_sys->pi_fd = net_ListenTCP( p_intf, url.psz_host, url.i_port ) )
- == NULL )
+ if( !p_intf->p_sys )
+ {
+ vlm_Delete( mediatheque );
+ vlc_UrlClean( &url );
+ return VLC_ENOMEM;
+ }
+ if( ( p_intf->p_sys->pi_fd = net_ListenTCP( p_intf, url.psz_host, url.i_port ) ) == NULL )
{
msg_Err( p_intf, "cannot listen for telnet" );
- vlc_UrlClean(&url);
- free( psz_address );
+ vlm_Delete( mediatheque );
+ vlc_UrlClean( &url );
free( p_intf->p_sys );
return VLC_EGENERIC;
}
p_intf->p_sys->mediatheque = mediatheque;
p_intf->pf_run = Run;
- vlc_UrlClean(&url);
- free( psz_address );
+ vlc_UrlClean( &url );
return VLC_SUCCESS;
}
{
telnet_client_t *cl = p_sys->clients[i];
net_Close( cl->fd );
+ free( cl->buffer_write );
free( cl );
- p_sys->clients[i] = NULL;
}
- if( p_sys->clients != NULL ) free( p_sys->clients );
+ free( p_sys->clients );
net_ListenClose( p_sys->pi_fd );
for (const int *pfd = p_sys->pi_fd; *pfd != -1; pfd++)
nlisten++; /* How many listening sockets do we have? */
- psz_password = config_GetPsz( p_intf, "telnet-password" );
+ /* FIXME: make sure config_* is cancel-safe */
+ psz_password = var_InheritString( p_intf, "telnet-password" );
+ vlc_cleanup_push( free, psz_password );
- while( !intf_ShouldDie( p_intf ) )
+ for( ;; )
{
unsigned ncli = p_sys->i_clients;
struct pollfd ufd[ncli + nlisten];
ufd[ncli + i].revents = 0;
}
- /* FIXME: arbitrary tick */
- switch (poll (ufd, sizeof (ufd) / sizeof (ufd[0]), 500))
+ switch (poll (ufd, sizeof (ufd) / sizeof (ufd[0]), -1))
{
case -1:
if (net_errno != EINTR)
{
msg_Err (p_intf, "network poll error");
- msleep (1000);
- continue;
+#ifndef WIN32
+ pause (); /* We are screwed! */
+#else
+ abort (); /* We are even more screwed! (no pause() in win32) */
+#endif
+ break;
}
case 0:
continue;
}
+ int canc = vlc_savecancel ();
/* check if there is something to do with the socket */
for (unsigned i = 0; i < ncli; i++)
{
net_Close( cl->fd );
TAB_REMOVE( p_intf->p_sys->i_clients ,
p_intf->p_sys->clients , cl );
+ free( cl->buffer_write );
free( cl );
continue;
}
cl->i_mode + 2 );
}
- if (i_recv <= 0)
+#ifdef WIN32
+ if( i_recv <= 0 && WSAGetLastError() == WSAEWOULDBLOCK )
+ {
+ errno = EAGAIN;
+ }
+#endif
+ if( i_recv == 0 || ( i_recv == -1 && ( end || errno != EAGAIN ) ) )
goto drop;
}
}
net_Close( cl->fd );
TAB_REMOVE( p_intf->p_sys->i_clients ,
p_intf->p_sys->clients , cl );
+ free( cl->buffer_write );
free( cl );
}
else if( !strncmp( cl->buffer_read, "shutdown", 8 ) )
{
msg_Err( p_intf, "shutdown requested" );
- vlc_object_kill( p_intf->p_libvlc );
+ libvlc_Quit( p_intf->p_libvlc );
}
else if( *cl->buffer_read == '@'
&& strchr( cl->buffer_read, ' ' ) )
if( psz_msg )
{
vlm_message_t *message;
- message = vlm_MessageNew( "Module command", psz_msg );
+ message = vlm_MessageNew( "Module command", "%s", psz_msg );
Write_message( cl, message, NULL, WRITE_MODE_CMD );
vlm_MessageDelete( message );
free( psz_msg );
if( !strncmp( cl->buffer_read, "help", 4 ) )
{
vlm_message_t *p_my_help =
- vlm_MessageNew( "Telnet Specific Commands:", NULL );
+ vlm_MessageSimpleNew( "Telnet Specific Commands:" );
vlm_MessageAdd( p_my_help,
- vlm_MessageNew( "logout, quit, exit" , NULL ) );
+ vlm_MessageSimpleNew( "logout, quit, exit" ) );
vlm_MessageAdd( p_my_help,
- vlm_MessageNew( "shutdown" , NULL ) );
+ vlm_MessageSimpleNew( "shutdown" ) );
vlm_MessageAdd( p_my_help,
- vlm_MessageNew( "@moduleinstance command argument",
- NULL) );
+ vlm_MessageSimpleNew( "@moduleinstance command argument" ) );
vlm_MessageAdd( message, p_my_help );
}
Write_message( cl, message, NULL, WRITE_MODE_CMD );
vlm_MessageDelete( message );
-
}
}
}
if (ufd[ncli + i].revents == 0)
continue;
- fd = accept (ufd[ncli + i].fd, NULL, NULL);
+ fd = net_AcceptSingle (VLC_OBJECT(p_intf), ufd[ncli + i].fd);
if (fd == -1)
continue;
- telnet_client_t *cl = malloc( sizeof( telnet_client_t ));
+ telnet_client_t *cl = calloc( 1, sizeof( telnet_client_t ));
if (cl == NULL)
{
net_Close (fd);
continue;
}
- memset( cl, 0, sizeof(telnet_client_t) );
cl->i_tel_cmd = 0;
cl->fd = fd;
cl->buffer_write = NULL;
"Password: \xff\xfb\x01" , WRITE_MODE_PWD );
TAB_APPEND( p_sys->i_clients, p_sys->clients, cl );
}
+ vlc_restorecancel( canc );
}
- if( psz_password )
- free( psz_password );
+ vlc_cleanup_run ();
}
static void Write_message( telnet_client_t *client, vlm_message_t *message,
client->p_buffer_read = client->buffer_read;
(client->p_buffer_read)[0] = 0; // if (cl->p_buffer_read)[0] = '\n'
- if( client->buffer_write ) free( client->buffer_write );
+ free( client->buffer_write );
/* generate the psz_message string */
if( message )
}
i_message += strlen( message->psz_name ) + i_level * sizeof( " " ) + 1;
- psz_message = malloc( i_message );
+ psz_message = xmalloc( i_message );
*psz_message = 0;
for( i = 0; i < i_level; i++ ) strcat( psz_message, " " );
strcat( psz_message, message->psz_name );
{
i_message += sizeof( " : " ) + strlen( message->psz_value ) +
sizeof( STRING_CR );
- psz_message = realloc( psz_message, i_message );
+ psz_message = xrealloc( psz_message, i_message );
strcat( psz_message, " : " );
strcat( psz_message, message->psz_value );
strcat( psz_message, STRING_CR );
else
{
i_message += sizeof( STRING_CR );
- psz_message = realloc( psz_message, i_message );
+ psz_message = xrealloc( psz_message, i_message );
strcat( psz_message, STRING_CR );
}
MessageToString( message->child[i], i_level + 1 );
i_message += strlen( child_message );
- psz_message = realloc( psz_message, i_message );
+ psz_message = xrealloc( psz_message, i_message );
strcat( psz_message, child_message );
free( child_message );
}