2006-09-10 23:20:44 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
* Copyright ( C ) 2005 / 2006 , Anthony Minessale II < anthmct @ yahoo . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II < anthmct @ yahoo . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Brian Fertig < brian . fertig @ convergencetek . com >
2006-12-21 17:11:43 +00:00
* Johny Kadarisman < jkr888 @ gmail . com >
2006-09-10 23:20:44 +00:00
*
* mod_python . c - - Python Module
*
*/
2006-09-17 21:28:31 +00:00
# include <Python.h>
2006-09-10 23:20:44 +00:00
# ifndef _REENTRANT
# define _REENTRANT
# endif
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include <switch.h>
2007-05-07 21:27:42 +00:00
2006-11-14 06:13:04 +00:00
void init_freeswitch ( void ) ;
2006-12-21 17:11:43 +00:00
static switch_api_interface_t python_run_interface ;
2006-09-10 23:20:44 +00:00
2006-11-14 06:13:04 +00:00
const char modname [ ] = " mod_python " ;
2006-09-10 23:20:44 +00:00
2007-05-07 21:27:42 +00:00
static void eval_some_python ( char * uuid , char * args )
{
PyThreadState * tstate ;
FILE * pythonfile = NULL ;
char * dupargs = NULL ;
char * argv [ 128 ] = { 0 } ;
int argc ;
int lead = 0 ;
2007-05-08 15:44:44 +00:00
char * script = NULL , * script_path = NULL , * path = NULL ;
2007-05-07 21:27:42 +00:00
if ( args ) {
dupargs = strdup ( args ) ;
} else {
return ;
}
assert ( dupargs ! = NULL ) ;
if ( ! ( argc = switch_separate_string ( dupargs , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ) ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " No script name specified! \n " ) ;
goto done ;
}
script = argv [ 0 ] ;
if ( uuid ) {
argv [ 0 ] = uuid ;
} else {
lead = 1 ;
}
2007-05-08 15:44:44 +00:00
if ( switch_is_file_path ( script ) ) {
script_path = script ;
if ( ( script = strrchr ( script_path , * SWITCH_PATH_SEPARATOR ) ) ) {
script + + ;
} else {
script = script_path ;
}
} else if ( ( path = switch_mprintf ( " %s%s%s " , SWITCH_GLOBAL_dirs . script_dir , SWITCH_PATH_SEPARATOR , script ) ) ) {
script_path = path ;
}
if ( script_path ) {
if ( ! switch_file_exists ( script_path , NULL ) = = SWITCH_STATUS_SUCCESS ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " Cannot Open File: %s \n " , script_path ) ;
goto done ;
}
}
2007-05-07 21:27:42 +00:00
2007-05-08 15:44:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " running %s \n " , script_path ) ;
if ( ( pythonfile = fopen ( script_path , " r " ) ) ) {
2007-05-07 21:27:42 +00:00
tstate = Py_NewInterpreter ( ) ;
if ( ! tstate ) {
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " error acquiring tstate \n " ) ;
goto done ;
}
2007-05-08 15:44:44 +00:00
2007-05-07 21:27:42 +00:00
2007-05-08 15:44:44 +00:00
PyThreadState_Clear ( tstate ) ;
2007-05-07 21:27:42 +00:00
init_freeswitch ( ) ;
2007-05-08 15:44:44 +00:00
PyRun_SimpleString ( " from freeswitch import * " ) ;
2007-05-07 21:27:42 +00:00
PySys_SetArgv ( argc - lead , & argv [ lead ] ) ;
2007-05-08 15:44:44 +00:00
PyRun_SimpleFile ( pythonfile , script ) ;
2007-05-07 21:27:42 +00:00
Py_EndInterpreter ( tstate ) ;
} else {
2007-05-08 15:44:44 +00:00
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_ERROR , " error running %s \n " , script_path ) ;
2007-05-07 21:27:42 +00:00
}
done :
if ( pythonfile ) {
fclose ( pythonfile ) ;
}
switch_safe_free ( dupargs ) ;
2007-05-08 15:44:44 +00:00
switch_safe_free ( path ) ;
2007-05-07 21:27:42 +00:00
}
2006-09-10 23:20:44 +00:00
static void python_function ( switch_core_session_t * session , char * data )
{
2007-05-07 21:27:42 +00:00
eval_some_python ( switch_core_session_get_uuid ( session ) , ( char * ) data ) ;
}
struct switch_py_thread {
char * args ;
switch_memory_pool_t * pool ;
} ;
static void * SWITCH_THREAD_FUNC py_thread_run ( switch_thread_t * thread , void * obj )
{
switch_memory_pool_t * pool ;
struct switch_py_thread * pt = ( struct switch_py_thread * ) obj ;
eval_some_python ( NULL , strdup ( pt - > args ) ) ;
2006-09-10 23:20:44 +00:00
2007-05-07 21:27:42 +00:00
pool = pt - > pool ;
switch_core_destroy_memory_pool ( & pool ) ;
2006-09-10 23:20:44 +00:00
2007-05-07 21:27:42 +00:00
return NULL ;
2006-09-10 23:20:44 +00:00
}
2006-12-21 17:11:43 +00:00
static switch_status_t launch_python ( char * text , switch_core_session_t * session , switch_stream_handle_t * stream )
{
2007-05-07 21:27:42 +00:00
switch_thread_t * thread ;
switch_threadattr_t * thd_attr = NULL ;
switch_memory_pool_t * pool ;
struct switch_py_thread * pt ;
2006-12-21 17:11:43 +00:00
2007-03-29 22:31:56 +00:00
if ( switch_strlen_zero ( text ) ) {
stream - > write_function ( stream , " USAGE: %s \n " , python_run_interface . syntax ) ;
return SWITCH_STATUS_SUCCESS ;
}
2007-05-07 21:27:42 +00:00
switch_core_new_memory_pool ( & pool ) ;
assert ( pool ! = NULL ) ;
2006-12-21 17:11:43 +00:00
2007-05-07 21:27:42 +00:00
pt = switch_core_alloc ( pool , sizeof ( * pt ) ) ;
assert ( pt ! = NULL ) ;
2006-12-21 17:11:43 +00:00
2007-05-07 21:27:42 +00:00
pt - > pool = pool ;
pt - > args = switch_core_strdup ( pt - > pool , text ) ;
switch_threadattr_create ( & thd_attr , pt - > pool ) ;
switch_threadattr_detach_set ( thd_attr , 1 ) ;
switch_threadattr_stacksize_set ( thd_attr , SWITCH_THREAD_STACKSIZE ) ;
switch_thread_create ( & thread , thd_attr , py_thread_run , pt , pt - > pool ) ;
2006-12-21 17:11:43 +00:00
2007-03-29 22:31:56 +00:00
stream - > write_function ( stream , " OK \n " ) ;
return SWITCH_STATUS_SUCCESS ;
2006-12-21 17:11:43 +00:00
}
2006-09-10 23:20:44 +00:00
static const switch_application_interface_t python_application_interface = {
/*.interface_name */ " python " ,
2007-02-26 21:38:10 +00:00
/*.application_function */ python_function ,
NULL , NULL , NULL ,
2007-03-29 22:31:56 +00:00
/* flags */ SAF_NONE ,
/* should we support no media mode here? If so, we need to detect the mode, and either disable the media functions or indicate media if/when we need */
/*.next */ NULL
2006-09-10 23:20:44 +00:00
} ;
2006-12-21 17:11:43 +00:00
static switch_api_interface_t python_run_interface = {
2007-03-29 22:31:56 +00:00
/*.interface_name */ " python " ,
/*.desc */ " run a python script " ,
/*.function */ launch_python ,
/*.syntax */ " python </path/to/script> " ,
/*.next */ NULL
2006-12-21 17:11:43 +00:00
} ;
2006-09-10 23:20:44 +00:00
static switch_loadable_module_interface_t python_module_interface = {
/*.module_name */ modname ,
/*.endpoint_interface */ NULL ,
/*.timer_interface */ NULL ,
/*.dialplan_interface */ NULL ,
/*.codec_interface */ NULL ,
/*.application_interface */ & python_application_interface ,
2006-12-21 17:11:43 +00:00
/*.api_interface */ & python_run_interface ,
2006-09-10 23:20:44 +00:00
/*.file_interface */ NULL ,
/*.speech_interface */ NULL ,
/*.directory_interface */ NULL
} ;
2007-05-07 21:27:42 +00:00
//static PyThreadState *gtstate;
static PyThreadState * mainThreadState ;
2007-03-30 00:13:31 +00:00
SWITCH_MOD_DECLARE ( switch_status_t ) switch_module_load ( const switch_loadable_module_interface_t * * module_interface , char * filename )
2006-09-10 23:20:44 +00:00
{
/* connect my internal structure to the blank pointer passed to me */
* module_interface = & python_module_interface ;
switch_log_printf ( SWITCH_CHANNEL_LOG , SWITCH_LOG_NOTICE , " Python Framework Loading... \n " ) ;
2007-05-07 21:27:42 +00:00
Py_Initialize ( ) ;
PyEval_InitThreads ( ) ;
mainThreadState = PyThreadState_Get ( ) ;
PyEval_ReleaseLock ( ) ;
2006-09-10 23:20:44 +00:00
2007-05-08 15:44:44 +00:00
eval_some_python ( NULL , " init_python.py " ) ;
PyThreadState_Swap ( NULL ) ;
2006-09-10 23:20:44 +00:00
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS ;
}
/*
2007-05-07 21:27:42 +00:00
Called when the system shuts down */
SWITCH_MOD_DECLARE ( switch_status_t ) switch_module_shutdown ( void )
{
PyInterpreterState * mainInterpreterState ;
PyThreadState * myThreadState ;
PyEval_AcquireLock ( ) ;
mainInterpreterState = mainThreadState - > interp ;
myThreadState = PyThreadState_New ( mainInterpreterState ) ;
PyThreadState_Swap ( myThreadState ) ;
PyEval_ReleaseLock ( ) ;
Py_Finalize ( ) ;
PyEval_ReleaseLock ( ) ;
return SWITCH_STATUS_SUCCESS ;
}
2006-09-10 23:20:44 +00:00
/* Return the number of arguments of the application command line */