2004-07-16 19:56:36 +00:00
/* $Id$ */
/***
This file is part of polypaudio .
polypaudio is free software ; you can redistribute it and / or modify
2004-11-14 14:58:54 +00:00
it under the terms of the GNU Lesser General Public License as published
2004-07-16 19:56:36 +00:00
by the Free Software Foundation ; either version 2 of the License ,
or ( at your option ) any later version .
polypaudio 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
General Public License for more details .
2004-11-14 14:58:54 +00:00
You should have received a copy of the GNU Lesser General Public License
2004-07-16 19:56:36 +00:00
along with polypaudio ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
USA .
* * */
2004-07-16 19:16:42 +00:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2004-07-06 00:08:44 +00:00
# include <string.h>
# include <errno.h>
2004-06-29 16:48:37 +00:00
# include <stdio.h>
2004-06-08 23:54:24 +00:00
# include <assert.h>
2004-06-29 16:48:37 +00:00
# include <unistd.h>
2006-01-10 17:51:06 +00:00
# include <limits.h>
# ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# endif
# ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
# endif
# ifdef HAVE_NETINET_IN_H
2004-09-23 15:57:15 +00:00
# include <netinet/in.h>
2006-01-10 17:51:06 +00:00
# endif
2006-02-17 12:10:58 +00:00
# include "../polypcore/winsock.h"
2004-06-08 23:54:24 +00:00
2006-02-16 19:19:58 +00:00
# include <polypcore/module.h>
# include <polypcore/socket-server.h>
# include <polypcore/socket-util.h>
# include <polypcore/util.h>
# include <polypcore/modargs.h>
# include <polypcore/log.h>
# include <polypcore/native-common.h>
2006-03-07 16:02:34 +00:00
# include <polypcore/xmalloc.h>
2004-06-19 18:51:30 +00:00
2004-09-11 23:17:38 +00:00
# ifdef USE_TCP_SOCKETS
# define SOCKET_DESCRIPTION "(TCP sockets)"
2006-02-22 20:44:37 +00:00
# define SOCKET_USAGE "port=<TCP port number> loopback=<listen on loopback device only?> listen=<address to listen on>"
2004-09-11 23:17:38 +00:00
# else
# define SOCKET_DESCRIPTION "(UNIX sockets)"
2004-09-20 17:19:35 +00:00
# define SOCKET_USAGE "socket=<path to UNIX socket>"
2004-09-11 23:17:38 +00:00
# endif
2004-08-18 01:00:18 +00:00
# if defined(USE_PROTOCOL_SIMPLE)
2006-02-16 19:19:58 +00:00
# include <polypcore/protocol-simple.h>
2004-07-11 22:20:08 +00:00
# define protocol_new pa_protocol_simple_new
2004-07-03 23:35:12 +00:00
# define protocol_free pa_protocol_simple_free
2004-09-29 20:13:05 +00:00
# define TCPWRAP_SERVICE "polypaudio-simple"
2004-06-20 01:12:13 +00:00
# define IPV4_PORT 4711
2004-11-11 21:18:33 +00:00
# define UNIX_SOCKET "simple"
2004-07-11 22:20:08 +00:00
# define MODULE_ARGUMENTS "rate", "format", "channels", "sink", "source", "playback", "record",
2004-11-11 21:18:33 +00:00
# if defined(USE_TCP_SOCKETS)
2004-10-30 01:55:16 +00:00
# include "module-simple-protocol-tcp-symdef.h"
# else
# include "module-simple-protocol-unix-symdef.h"
# endif
2004-09-11 23:17:38 +00:00
PA_MODULE_DESCRIPTION ( " Simple protocol " SOCKET_DESCRIPTION )
2004-09-20 17:19:35 +00:00
PA_MODULE_USAGE ( " rate=<sample rate> format=<sample format> channels=<number of channels> sink=<sink to connect to> source=<source to connect to> playback=<enable playback?> record=<enable record?> " SOCKET_USAGE )
2004-08-18 01:00:18 +00:00
# elif defined(USE_PROTOCOL_CLI)
2006-02-16 19:19:58 +00:00
# include <polypcore/protocol-cli.h>
2004-08-18 01:00:18 +00:00
# define protocol_new pa_protocol_cli_new
# define protocol_free pa_protocol_cli_free
2004-09-29 20:13:05 +00:00
# define TCPWRAP_SERVICE "polypaudio-cli"
2004-08-18 01:00:18 +00:00
# define IPV4_PORT 4712
2004-11-11 21:18:33 +00:00
# define UNIX_SOCKET "cli"
2004-08-18 01:00:18 +00:00
# define MODULE_ARGUMENTS
2004-10-30 01:55:16 +00:00
# ifdef USE_TCP_SOCKETS
# include "module-cli-protocol-tcp-symdef.h"
# else
# include "module-cli-protocol-unix-symdef.h"
# endif
2004-09-11 23:17:38 +00:00
PA_MODULE_DESCRIPTION ( " Command line interface protocol " SOCKET_DESCRIPTION )
2004-09-20 17:19:35 +00:00
PA_MODULE_USAGE ( SOCKET_USAGE )
2005-01-12 17:37:31 +00:00
# elif defined(USE_PROTOCOL_HTTP)
2006-02-16 19:19:58 +00:00
# include <polypcore/protocol-http.h>
2005-01-12 17:37:31 +00:00
# define protocol_new pa_protocol_http_new
# define protocol_free pa_protocol_http_free
# define TCPWRAP_SERVICE "polypaudio-http"
# define IPV4_PORT 4714
# define UNIX_SOCKET "http"
# define MODULE_ARGUMENTS
# ifdef USE_TCP_SOCKETS
# include "module-http-protocol-tcp-symdef.h"
# else
# include "module-http-protocol-unix-symdef.h"
# endif
PA_MODULE_DESCRIPTION ( " HTTP " SOCKET_DESCRIPTION )
PA_MODULE_USAGE ( SOCKET_USAGE )
2004-08-18 01:00:18 +00:00
# elif defined(USE_PROTOCOL_NATIVE)
2006-02-16 19:19:58 +00:00
# include <polypcore/protocol-native.h>
2004-08-18 01:00:18 +00:00
# define protocol_new pa_protocol_native_new
# define protocol_free pa_protocol_native_free
2004-09-29 20:13:05 +00:00
# define TCPWRAP_SERVICE "polypaudio-native"
2004-09-28 22:47:48 +00:00
# define IPV4_PORT PA_NATIVE_DEFAULT_PORT
2004-11-11 21:18:33 +00:00
# define UNIX_SOCKET PA_NATIVE_DEFAULT_UNIX_SOCKET
2006-02-24 17:14:23 +00:00
# define MODULE_ARGUMENTS_COMMON "cookie", "auth-anonymous",
2004-10-30 01:55:16 +00:00
# ifdef USE_TCP_SOCKETS
# include "module-native-protocol-tcp-symdef.h"
# else
# include "module-native-protocol-unix-symdef.h"
# endif
2006-02-24 17:14:23 +00:00
# if defined(SCM_CREDENTIALS) && !defined(USE_TCP_SOCKETS)
# define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group",
# define AUTH_USAGE "auth-group=<local group to allow access>"
# else
# define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
# define AUTH_USAGE
# endif
2004-09-11 23:17:38 +00:00
PA_MODULE_DESCRIPTION ( " Native protocol " SOCKET_DESCRIPTION )
2006-02-24 17:14:23 +00:00
PA_MODULE_USAGE ( " auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> " AUTH_USAGE SOCKET_USAGE )
2004-08-18 01:00:18 +00:00
# elif defined(USE_PROTOCOL_ESOUND)
2006-02-16 19:19:58 +00:00
# include <polypcore/protocol-esound.h>
# include <polypcore/esound.h>
2004-08-18 01:00:18 +00:00
# define protocol_new pa_protocol_esound_new
# define protocol_free pa_protocol_esound_free
2004-09-29 20:13:05 +00:00
# define TCPWRAP_SERVICE "esound"
2004-08-18 01:00:18 +00:00
# define IPV4_PORT ESD_DEFAULT_PORT
# define UNIX_SOCKET ESD_UNIX_SOCKET_NAME
2006-02-24 17:14:23 +00:00
# define MODULE_ARGUMENTS "sink", "source", "auth-anonymous", "cookie",
2004-10-30 01:55:16 +00:00
# ifdef USE_TCP_SOCKETS
# include "module-esound-protocol-tcp-symdef.h"
# else
# include "module-esound-protocol-unix-symdef.h"
# endif
2006-01-27 16:25:31 +00:00
PA_MODULE_DESCRIPTION ( " ESOUND protocol " SOCKET_DESCRIPTION )
2006-02-24 17:14:23 +00:00
PA_MODULE_USAGE ( " sink=<sink to connect to> source=<source to connect to> auth-anonymous=<don't check for cookies?> cookie=<path to cookie file> " SOCKET_USAGE )
2004-06-19 18:51:30 +00:00
# else
2004-08-18 01:00:18 +00:00
# error "Broken build system"
2004-06-19 18:51:30 +00:00
# endif
2004-06-08 23:54:24 +00:00
2004-10-30 01:55:16 +00:00
PA_MODULE_AUTHOR ( " Lennart Poettering " )
PA_MODULE_VERSION ( PACKAGE_VERSION )
2004-07-11 22:20:08 +00:00
static const char * const valid_modargs [ ] = {
MODULE_ARGUMENTS
2006-02-21 01:08:53 +00:00
# if defined(USE_TCP_SOCKETS)
2004-07-11 22:20:08 +00:00
" port " ,
" loopback " ,
2006-02-22 20:44:37 +00:00
" listen " ,
2004-07-11 22:20:08 +00:00
# else
" socket " ,
# endif
NULL
} ;
2004-06-08 23:54:24 +00:00
2006-03-07 16:02:34 +00:00
struct userdata {
# if defined(USE_TCP_SOCKETS)
void * protocol_ipv4 ;
void * protocol_ipv6 ;
# else
void * protocol_unix ;
# endif
} ;
int pa__init ( pa_core * c , pa_module * m ) {
pa_modargs * ma = NULL ;
int ret = - 1 ;
struct userdata * u = NULL ;
2006-02-21 01:08:53 +00:00
# if defined(USE_TCP_SOCKETS)
2006-03-07 16:02:34 +00:00
pa_socket_server * s_ipv4 = NULL ;
pa_socket_server * s_ipv6 = NULL ;
2004-09-04 00:27:36 +00:00
int loopback = 1 ;
uint32_t port = IPV4_PORT ;
2006-02-22 20:44:37 +00:00
const char * listen_on ;
2006-03-07 16:02:34 +00:00
# else
pa_socket_server * s ;
int r ;
const char * v ;
char tmp [ PATH_MAX ] ;
# endif
assert ( c & & m ) ;
# if defined(USE_TCP_SOCKETS)
if ( ! ( ma = pa_modargs_new ( m - > argument , valid_modargs ) ) ) {
pa_log ( __FILE__ " : Failed to parse module arguments " ) ;
goto finish ;
}
2004-07-11 22:20:08 +00:00
2004-09-04 00:27:36 +00:00
if ( pa_modargs_get_value_boolean ( ma , " loopback " , & loopback ) < 0 ) {
2006-02-23 02:27:19 +00:00
pa_log ( __FILE__ " : loopback= expects a boolean argument. " ) ;
2006-03-07 16:02:34 +00:00
goto fail ;
2004-07-11 22:20:08 +00:00
}
2004-09-04 00:27:36 +00:00
if ( pa_modargs_get_value_u32 ( ma , " port " , & port ) < 0 | | port < 1 | | port > 0xFFFF ) {
2006-02-23 02:27:19 +00:00
pa_log ( __FILE__ " : port= expects a numerical argument between 1 and 65535. " ) ;
2006-03-07 16:02:34 +00:00
goto fail ;
2004-07-11 22:20:08 +00:00
}
2004-11-11 21:18:33 +00:00
2006-02-22 20:44:37 +00:00
listen_on = pa_modargs_get_value ( ma , " listen " , NULL ) ;
2006-02-21 01:08:53 +00:00
2006-02-22 20:44:37 +00:00
if ( listen_on ) {
2006-03-07 16:02:34 +00:00
s_ipv4 = pa_socket_server_new_ipv4_string ( c - > mainloop , listen_on , port , TCPWRAP_SERVICE ) ;
s_ipv6 = pa_socket_server_new_ipv6_string ( c - > mainloop , listen_on , port , TCPWRAP_SERVICE ) ;
if ( ! s_ipv4 & & ! s_ipv6 )
goto fail ;
2006-02-22 20:44:37 +00:00
} else if ( loopback ) {
2006-03-07 16:02:34 +00:00
s_ipv4 = pa_socket_server_new_ipv4_loopback ( c - > mainloop , port , TCPWRAP_SERVICE ) ;
s_ipv6 = pa_socket_server_new_ipv6_loopback ( c - > mainloop , port , TCPWRAP_SERVICE ) ;
if ( ! s_ipv4 & & ! s_ipv6 )
goto fail ;
2006-02-21 01:08:53 +00:00
} else {
2006-03-07 16:02:34 +00:00
s_ipv4 = pa_socket_server_new_ipv4_any ( c - > mainloop , port , TCPWRAP_SERVICE ) ;
s_ipv6 = pa_socket_server_new_ipv6_any ( c - > mainloop , port , TCPWRAP_SERVICE ) ;
if ( ! s_ipv4 & & ! s_ipv6 )
goto fail ;
2006-02-21 01:08:53 +00:00
}
2004-06-19 18:41:24 +00:00
# else
2004-11-11 21:18:33 +00:00
v = pa_modargs_get_value ( ma , " socket " , UNIX_SOCKET ) ;
assert ( v ) ;
2004-07-11 22:20:08 +00:00
2004-11-11 21:18:33 +00:00
pa_runtime_path ( v , tmp , sizeof ( tmp ) ) ;
2004-07-11 22:20:08 +00:00
2004-11-11 21:18:33 +00:00
if ( pa_make_secure_parent_dir ( tmp ) < 0 ) {
2006-02-23 02:27:19 +00:00
pa_log ( __FILE__ " : Failed to create secure socket directory. " ) ;
2006-03-07 16:02:34 +00:00
goto fail ;
2004-06-29 16:48:37 +00:00
}
2004-07-06 00:08:44 +00:00
2004-11-11 21:18:33 +00:00
if ( ( r = pa_unix_socket_remove_stale ( tmp ) ) < 0 ) {
2006-02-23 02:27:19 +00:00
pa_log ( __FILE__ " : Failed to remove stale UNIX socket '%s': %s " , tmp , strerror ( errno ) ) ;
2006-03-07 16:02:34 +00:00
goto fail ;
2004-07-06 00:08:44 +00:00
}
2004-06-29 16:48:37 +00:00
2004-07-11 22:20:08 +00:00
if ( r )
2004-11-11 21:18:33 +00:00
pa_log ( __FILE__ " : Removed stale UNIX socket '%s'. " , tmp ) ;
2004-07-11 22:20:08 +00:00
2004-11-11 21:18:33 +00:00
if ( ! ( s = pa_socket_server_new_unix ( c - > mainloop , tmp ) ) )
2006-03-07 16:02:34 +00:00
goto fail ;
2004-07-11 22:20:08 +00:00
# endif
2006-03-07 16:02:34 +00:00
u = pa_xmalloc0 ( sizeof ( struct userdata ) ) ;
2004-07-11 22:20:08 +00:00
2006-03-07 16:02:34 +00:00
# if defined(USE_TCP_SOCKETS)
if ( s_ipv4 ) {
u - > protocol_ipv4 = protocol_new ( c , s_ipv4 , m , ma ) ;
if ( ! u - > protocol_ipv4 )
pa_socket_server_unref ( s_ipv4 ) ;
2004-06-29 16:48:37 +00:00
}
2004-06-08 23:54:24 +00:00
2006-03-07 16:02:34 +00:00
if ( s_ipv6 ) {
u - > protocol_ipv6 = protocol_new ( c , s_ipv4 , m , ma ) ;
if ( ! u - > protocol_ipv6 )
pa_socket_server_unref ( s_ipv6 ) ;
2004-07-06 00:08:44 +00:00
}
2006-03-07 16:02:34 +00:00
if ( ! u - > protocol_ipv4 & & ! u - > protocol_ipv6 )
goto fail ;
# else
if ( ! ( u - > protocol_unix = protocol_new ( c , s , m , ma ) ) )
goto fail ;
# endif
2004-07-15 17:33:56 +00:00
ret = 0 ;
finish :
if ( ma )
pa_modargs_free ( ma ) ;
return ret ;
2006-03-07 16:02:34 +00:00
fail :
if ( u ) {
# if defined(USE_TCP_SOCKETS)
if ( u - > protocol_ipv4 )
protocol_free ( u - > protocol_ipv4 ) ;
if ( u - > protocol_ipv6 )
protocol_free ( u - > protocol_ipv6 ) ;
# else
if ( u - > protocol_unix )
protocol_free ( u - > protocol_unix ) ;
# endif
pa_xfree ( u ) ;
} else {
# if defined(USE_TCP_SOCKETS)
if ( s_ipv4 )
pa_socket_server_unref ( s_ipv4 ) ;
if ( s_ipv6 )
pa_socket_server_unref ( s_ipv6 ) ;
# else
if ( s )
pa_socket_server_unref ( s ) ;
# endif
}
goto finish ;
2004-06-08 23:54:24 +00:00
}
2006-01-11 01:17:39 +00:00
void pa__done ( pa_core * c , pa_module * m ) {
2006-03-07 16:02:34 +00:00
struct userdata * u ;
2004-06-08 23:54:24 +00:00
assert ( c & & m ) ;
2006-02-21 01:08:53 +00:00
# if defined(USE_PROTOCOL_ESOUND) && !defined(USE_TCP_SOCKETS)
if ( remove ( ESD_UNIX_SOCKET_NAME ) ! = 0 )
2006-02-23 02:27:19 +00:00
pa_log ( " %s: Failed to remove %s : %s. " , __FILE__ , ESD_UNIX_SOCKET_NAME , strerror ( errno ) ) ;
2006-02-21 01:08:53 +00:00
if ( remove ( ESD_UNIX_SOCKET_DIR ) ! = 0 )
2006-02-23 02:27:19 +00:00
pa_log ( " %s: Failed to remove %s : %s. " , __FILE__ , ESD_UNIX_SOCKET_DIR , strerror ( errno ) ) ;
2005-09-15 23:48:09 +00:00
# endif
2006-03-07 16:02:34 +00:00
u = m - > userdata ;
assert ( u ) ;
# if defined(USE_TCP_SOCKETS)
if ( u - > protocol_ipv4 )
protocol_free ( u - > protocol_ipv4 ) ;
if ( u - > protocol_ipv6 )
protocol_free ( u - > protocol_ipv6 ) ;
# else
if ( u - > protocol_unix )
protocol_free ( u - > protocol_unix ) ;
# endif
pa_xfree ( u ) ;
2004-06-08 23:54:24 +00:00
}