Move input and hangup delegates to reside on MonoSession instead of bound to app.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8791 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Giagnocavo 2008-06-10 03:09:14 +00:00
parent ce07c5b233
commit 9bc2dccc0a
6 changed files with 529 additions and 304 deletions

View File

@ -24139,7 +24139,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Originate(void * jarg1, void * jar
} }
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_speak(void * jarg1, char * jarg2) { SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Speak(void * jarg1, char * jarg2) {
int jresult ; int jresult ;
CoreSession *arg1 = (CoreSession *) 0 ; CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ; char *arg2 = (char *) 0 ;
@ -24153,7 +24153,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_speak(void * jarg1, char * jarg2)
} }
SWIGEXPORT void SWIGSTDCALL CSharp_CoreSession_set_tts_parms(void * jarg1, char * jarg2, char * jarg3) { SWIGEXPORT void SWIGSTDCALL CSharp_CoreSession_SetTtsParameters(void * jarg1, char * jarg2, char * jarg3) {
CoreSession *arg1 = (CoreSession *) 0 ; CoreSession *arg1 = (CoreSession *) 0 ;
char *arg2 = (char *) 0 ; char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ; char *arg3 = (char *) 0 ;
@ -24305,7 +24305,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_flushDigits(void * jarg1) {
} }
SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_setAutoHangup(void * jarg1, unsigned int jarg2) { SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_SetAutoHangup(void * jarg1, unsigned int jarg2) {
int jresult ; int jresult ;
CoreSession *arg1 = (CoreSession *) 0 ; CoreSession *arg1 = (CoreSession *) 0 ;
bool arg2 ; bool arg2 ;

View File

@ -33,7 +33,10 @@
*/ */
#include <switch.h> #include <switch.h>
SWITCH_BEGIN_EXTERN_C
SWITCH_BEGIN_EXTERN_C
#include "freeswitch_mono.h" #include "freeswitch_mono.h"
#include <glib.h> #include <glib.h>
#include <mono/jit/jit.h> #include <mono/jit/jit.h>
@ -47,272 +50,489 @@
#define EXPORT __declspec(dllexport) #define EXPORT __declspec(dllexport)
#elif #elif
#define EXPORT #define EXPORT
#endif /* */ #endif /*
*/
#define MOD_MONO_MANAGED_DLL "mod_mono_managed.dll" #define MOD_MONO_MANAGED_DLL "mod_mono_managed.dll"
mod_mono_globals globals = {
0}; mod_mono_globals globals = {
0};
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown);
SWITCH_MODULE_DEFINITION(mod_mono, mod_mono_load, mod_mono_shutdown, NULL);
SWITCH_STANDARD_API(monorun_api_function); /* ExecuteBackground */ SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load);
SWITCH_STANDARD_API(mono_api_function); /* Execute */
SWITCH_STANDARD_APP(mono_app_function); /* Run */ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown);
SWITCH_MODULE_DEFINITION(mod_mono, mod_mono_load, mod_mono_shutdown, NULL);
SWITCH_STANDARD_API(monorun_api_function); /* ExecuteBackground */
SWITCH_STANDARD_API(mono_api_function); /* Execute */
SWITCH_STANDARD_APP(mono_app_function); /* Run */
// Sets up delegates (and anything else needed) on the MonoSession object // Sets up delegates (and anything else needed) on the MonoSession object
// Called via internalcall // Called via internalcall
SWITCH_MOD_DECLARE(void) InitMonoSession(MonoSession * session, MonoObject * dtmfDelegate, MonoObject * hangupDelegate) SWITCH_MOD_DECLARE(void) InitMonoSession(MonoSession * session, MonoObject * dtmfDelegate, MonoObject * hangupDelegate)
{ {
switch_assert(session); switch_assert(session);
if (!session) if (!session) {
return; return;
session->setDTMFCallback(NULL, ""); }
session->setHangupHook(NULL); session->setDTMFCallback(NULL, "");
session->dtmfDelegateHandle = mono_gchandle_new(dtmfDelegate, FALSE); session->setHangupHook(NULL);
session->hangupDelegateHandle = mono_gchandle_new(hangupDelegate, FALSE); session->dtmfDelegateHandle = mono_gchandle_new(dtmfDelegate, FALSE);
} session->hangupDelegateHandle = mono_gchandle_new(hangupDelegate, FALSE);
switch_status_t setMonoDirs() }
{
switch_status_t setMonoDirs()
{
#ifdef WIN32 #ifdef WIN32
/* Win32 Mono installs can't figure out their own path /* Win32 Mono installs can't figure out their own path
// Guys in #mono say we should just deploy all the libs we need // Guys in #mono say we should just deploy all the libs we need
// I think it's much nicer to let the user deal with installing Mono // I think it's much nicer to let the user deal with installing Mono
// and we'll just look for it in program files. */ // and we'll just look for it in program files. */
HANDLE hFind; HANDLE hFind;
WIN32_FIND_DATA findData;
char progFilesPath[MAX_PATH]; WIN32_FIND_DATA findData;
char findPath[MAX_PATH];
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, progFilesPath); char progFilesPath[MAX_PATH];
switch_snprintf(findPath, MAX_PATH, "%s\\Mono-*", progFilesPath);
hFind = FindFirstFile(findPath, &findData); char findPath[MAX_PATH];
if (hFind == INVALID_HANDLE_VALUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error looking for Mono in Program Files.\n"); SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, progFilesPath);
return SWITCH_STATUS_FALSE;
} switch_snprintf(findPath, MAX_PATH, "%s\\Mono-*", progFilesPath);
while ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
if (FindNextFile(hFind, &findData) == 0) { hFind = FindFirstFile(findPath, &findData);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find Mono directory in Program Files.\n");
FindClose(hFind); if (hFind == INVALID_HANDLE_VALUE) {
return SWITCH_STATUS_FALSE;
} switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error looking for Mono in Program Files.\n");
}
return SWITCH_STATUS_FALSE;
}
while ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
if (FindNextFile(hFind, &findData) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find Mono directory in Program Files.\n");
FindClose(hFind);
return SWITCH_STATUS_FALSE;
}
}
/* Got it */ /* Got it */
{ {
char libPath[MAX_PATH];
char etcPath[MAX_PATH]; char libPath[MAX_PATH];
switch_snprintf(libPath, MAX_PATH, "%s\\%s\\lib", progFilesPath, findData.cFileName);
switch_snprintf(etcPath, MAX_PATH, "%s\\%s\\etc", progFilesPath, findData.cFileName); char etcPath[MAX_PATH];
FindClose(hFind);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Using Mono paths '%s' and '%s'.\n", libPath, etcPath); switch_snprintf(libPath, MAX_PATH, "%s\\%s\\lib", progFilesPath, findData.cFileName);
mono_set_dirs(libPath, etcPath);
return SWITCH_STATUS_SUCCESS; switch_snprintf(etcPath, MAX_PATH, "%s\\%s\\etc", progFilesPath, findData.cFileName);
}
FindClose(hFind);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Using Mono paths '%s' and '%s'.\n", libPath, etcPath);
mono_set_dirs(libPath, etcPath);
return SWITCH_STATUS_SUCCESS;
}
#elif #elif
// On other platforms, it should just work if it hasn't been relocated // On other platforms, it should just work if it hasn't been relocated
mono_set_dirs(NULL, NULL); mono_set_dirs(NULL, NULL);
return SWITCH_STATUS_SUCCESS;
#endif /* */ return SWITCH_STATUS_SUCCESS;
}
switch_status_t loadModMonoManaged() #endif /*
{ */
}
switch_status_t loadModMonoManaged()
{
/* Find and load mod_mono_managed.exe */ /* Find and load mod_mono_managed.exe */
char filename[256]; char filename[256];
switch_snprintf(filename, 256, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, MOD_MONO_MANAGED_DLL);
globals.domain = mono_jit_init(filename); switch_snprintf(filename, 256, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, MOD_MONO_MANAGED_DLL);
if (!globals.domain) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n"); globals.domain = mono_jit_init(filename);
return SWITCH_STATUS_FALSE;
}
if (!globals.domain) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n");
return SWITCH_STATUS_FALSE;
}
/* Open the assembly */ /* Open the assembly */
globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename);
if (!globals.mod_mono_asm) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n"); if (!globals.mod_mono_asm) {
return SWITCH_STATUS_FALSE;
} switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n");
return SWITCH_STATUS_SUCCESS;
} return SWITCH_STATUS_FALSE;
MonoMethod * getMethod(const char *name, MonoClass * klass) }
{
MonoMethodDesc * desc; return SWITCH_STATUS_SUCCESS;
MonoMethod * method;
desc = mono_method_desc_new(name, TRUE); }
method = mono_method_desc_search_in_class(desc, klass);
if (!method) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find %s method.\n", name);
return NULL; MonoMethod * getMethod(const char *name, MonoClass * klass)
} {
return method;
} MonoMethodDesc * desc;
switch_status_t findLoader()
{ MonoMethod * method;
desc = mono_method_desc_new(name, TRUE);
method = mono_method_desc_search_in_class(desc, klass);
if (!method) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find %s method.\n", name);
return NULL;
}
return method;
}
switch_status_t findLoader()
{
/* Find loader class and methods */ /* Find loader class and methods */
MonoImage * img; MonoImage * img;
MonoClass * loaderClass;
img = mono_assembly_get_image(globals.mod_mono_asm); MonoClass * loaderClass;
loaderClass = mono_class_from_name(img, "FreeSWITCH", "Loader");
if (!loaderClass) { img = mono_assembly_get_image(globals.mod_mono_asm);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find FreeSWITCH.Loader class.\n");
return SWITCH_STATUS_FALSE; loaderClass = mono_class_from_name(img, "FreeSWITCH", "Loader");
}
globals.loadMethod = getMethod("FreeSWITCH.Loader:Load()", loaderClass); if (!loaderClass) {
if (!globals.loadMethod)
return SWITCH_STATUS_FALSE; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find FreeSWITCH.Loader class.\n");
globals.unloadMethod = getMethod("FreeSWITCH.Loader:Unload()", loaderClass);
if (!globals.unloadMethod) return SWITCH_STATUS_FALSE;
return SWITCH_STATUS_FALSE;
globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass); }
if (!globals.runMethod)
return SWITCH_STATUS_FALSE;
globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass); globals.loadMethod = getMethod("FreeSWITCH.Loader:Load()", loaderClass);
if (!globals.executeMethod)
return SWITCH_STATUS_FALSE; if (!globals.loadMethod)
globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass); return SWITCH_STATUS_FALSE;
if (!globals.executeBackgroundMethod)
return SWITCH_STATUS_FALSE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n"); globals.unloadMethod = getMethod("FreeSWITCH.Loader:Unload()", loaderClass);
return SWITCH_STATUS_SUCCESS;
} if (!globals.unloadMethod)
return SWITCH_STATUS_FALSE;
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load)
{
globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass);
if (!globals.runMethod)
return SWITCH_STATUS_FALSE;
globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass);
if (!globals.executeMethod)
return SWITCH_STATUS_FALSE;
globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass);
if (!globals.executeBackgroundMethod)
return SWITCH_STATUS_FALSE;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load)
{
/* connect my internal structure to the blank pointer passed to me */ /* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname); *module_interface = switch_loadable_module_create_module_interface(pool, modname);
globals.pool = pool;
if (setMonoDirs() != SWITCH_STATUS_SUCCESS) { globals.pool = pool;
return SWITCH_STATUS_FALSE;
}
if (loadModMonoManaged() != SWITCH_STATUS_SUCCESS) { if (setMonoDirs() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
} return SWITCH_STATUS_FALSE;
if (findLoader() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE; }
}
if (loadModMonoManaged() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
if (findLoader() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
/* Not sure if this is necesary on the loading thread */ /* Not sure if this is necesary on the loading thread */
mono_thread_attach(globals.domain); mono_thread_attach(globals.domain);
mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", InitMonoSession);
mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", InitMonoSession);
/* Run loader */ /* Run loader */
MonoObject * objResult; MonoObject * objResult;
MonoObject * exception = NULL;
objResult = mono_runtime_invoke(globals.loadMethod, NULL, NULL, &exception); MonoObject * exception = NULL;
if (exception) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load threw an exception.\n"); objResult = mono_runtime_invoke(globals.loadMethod, NULL, NULL, &exception);
mono_print_unhandled_exception(exception);
return SWITCH_STATUS_FALSE; if (exception) {
}
if (*(int *) mono_object_unbox(objResult)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load threw an exception.\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");
} else { mono_print_unhandled_exception(exception);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true.\n");
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_FALSE;
}
}
if (*(int *) mono_object_unbox(objResult)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true.\n");
return SWITCH_STATUS_FALSE;
}
/* We're good to register */ /* We're good to register */
switch_api_interface_t *api_interface; switch_api_interface_t *api_interface;
switch_application_interface_t *app_interface;
SWITCH_ADD_API(api_interface, "monorun", "Run a module (ExecuteBackground)", monorun_api_function, "<module> [<args>]"); switch_application_interface_t *app_interface;
SWITCH_ADD_API(api_interface, "mono", "Run a module as an API function (Execute)", mono_api_function, "<module> [<args>]");
SWITCH_ADD_APP(app_interface, "mono", "Run Mono IVR", "Run a Mono IVR on a channel", mono_app_function, "<modulename> [<args>]", SAF_NONE);
return SWITCH_STATUS_SUCCESS; SWITCH_ADD_API(api_interface, "monorun", "Run a module (ExecuteBackground)", monorun_api_function, "<module> [<args>]");
}
SWITCH_ADD_API(api_interface, "mono", "Run a module as an API function (Execute)", mono_api_function, "<module> [<args>]");
SWITCH_STANDARD_API(monorun_api_function)
{ SWITCH_ADD_APP(app_interface, "mono", "Run Mono IVR", "Run a Mono IVR on a channel", mono_app_function, "<modulename> [<args>]", SAF_NONE);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(monorun_api_function)
{
// TODO: Should we be detaching after all this? // TODO: Should we be detaching after all this?
mono_thread_attach(globals.domain); mono_thread_attach(globals.domain);
if (switch_strlen_zero(cmd)) {
stream->write_function(stream, "-ERR no args specified!\n"); if (switch_strlen_zero(cmd)) {
return SWITCH_STATUS_SUCCESS;
} stream->write_function(stream, "-ERR no args specified!\n");
return SWITCH_STATUS_SUCCESS;
}
// ExecuteBackground(string command) // ExecuteBackground(string command)
void *args[1]; void *args[1];
args[0] = mono_string_new(globals.domain, cmd);
MonoObject * exception = NULL; args[0] = mono_string_new(globals.domain, cmd);
MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);
if (exception) { MonoObject * exception = NULL;
stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");
mono_print_unhandled_exception(exception); MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);
return SWITCH_STATUS_SUCCESS;
} if (exception) {
if (*(int *) mono_object_unbox(objResult)) {
stream->write_function(stream, "+OK\n"); stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");
} else {
stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n"); mono_print_unhandled_exception(exception);
}
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
}
}
SWITCH_STANDARD_API(mono_api_function)
{ if (*(int *) mono_object_unbox(objResult)) {
mono_thread_attach(globals.domain);
if (switch_strlen_zero(cmd)) { stream->write_function(stream, "+OK\n");
stream->write_function(stream, "-ERR no args specified!\n");
return SWITCH_STATUS_SUCCESS; } else {
}
stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n");
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(mono_api_function)
{
mono_thread_attach(globals.domain);
if (switch_strlen_zero(cmd)) {
stream->write_function(stream, "-ERR no args specified!\n");
return SWITCH_STATUS_SUCCESS;
}
// Method is: Execute(string command, IntPtr streamPtr, IntPtr eventPtr) // Method is: Execute(string command, IntPtr streamPtr, IntPtr eventPtr)
void *args[3]; void *args[3];
args[0] = mono_string_new(globals.domain, cmd);
args[1] = &stream; // Address of the arguments args[0] = mono_string_new(globals.domain, cmd);
args[2] = &(stream->param_event);
MonoObject * exception = NULL; args[1] = &stream; // Address of the arguments
MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception); args[2] = &(stream->param_event);
if (exception) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);
mono_print_unhandled_exception(exception); MonoObject * exception = NULL;
}
if (!(*(int *) mono_object_unbox(objResult))) { MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);
} if (exception) {
return SWITCH_STATUS_SUCCESS;
} switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);
SWITCH_STANDARD_APP(mono_app_function) mono_print_unhandled_exception(exception);
{
mono_thread_attach(globals.domain); }
if (switch_strlen_zero(data)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n"); if (!(*(int *) mono_object_unbox(objResult))) {
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_APP(mono_app_function)
{
mono_thread_attach(globals.domain);
if (switch_strlen_zero(data)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");
}
// bool Run(string command, IntPtr sessionHandle) // bool Run(string command, IntPtr sessionHandle)
void *args[2]; void *args[2];
args[0] = mono_string_new(globals.domain, data);
args[1] = &session; args[0] = mono_string_new(globals.domain, data);
MonoObject * exception = NULL;
MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception); args[1] = &session;
if (exception) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);
mono_print_unhandled_exception(exception); MonoObject * exception = NULL;
}
if (!(*(int *) mono_object_unbox(objResult))) { MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);
} if (exception) {
} SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown)
{ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);
mono_thread_attach(globals.domain);
MonoObject * ex; mono_print_unhandled_exception(exception);
mono_runtime_invoke(globals.unloadMethod, NULL, NULL, &ex);
if (ex) { }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception occurred in Loader::Unload.\n");
mono_print_unhandled_exception(ex); if (!(*(int *) mono_object_unbox(objResult))) {
}
mono_runtime_set_shutting_down(); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);
mono_runtime_cleanup(globals.domain);
mono_runtime_quit(); }
return SWITCH_STATUS_SUCCESS;
} }
SWITCH_END_EXTERN_C SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown)
{
mono_thread_attach(globals.domain);
MonoObject * ex;
mono_runtime_invoke(globals.unloadMethod, NULL, NULL, &ex);
if (ex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception occurred in Loader::Unload.\n");
mono_print_unhandled_exception(ex);
}
mono_runtime_set_shutting_down();
mono_runtime_cleanup(globals.domain);
mono_runtime_quit();
return SWITCH_STATUS_SUCCESS;
}
SWITCH_END_EXTERN_C

View File

@ -43,60 +43,6 @@ namespace FreeSWITCH
protected static void Unload() { } protected static void Unload() { }
void hangupCallback()
{
Log.WriteLine(LogLevel.Debug, "AppFunction is in hangupCallback.");
try {
abortRun();
var f = HangupFunction;
if (f != null) f();
}
catch (Exception ex) {
Log.WriteLine(LogLevel.Warning, "Exception in hangupCallback: {0}", ex.ToString());
throw;
}
}
protected Action HangupFunction { get; set; }
protected Func<Char, TimeSpan, string> DtmfReceivedFunction { get; set; }
protected Func<Native.Event, string> EventReceivedFunction { get; set; }
string inputCallback(IntPtr input, Native.switch_input_type_t inputType)
{
switch (inputType) {
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_DTMF:
using (var dtmf = new Native.switch_dtmf_t(input, false)) {
return dtmfCallback(dtmf);
}
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_EVENT:
using (var swevt = new Native.switch_event(input, false)) {
return eventCallback(swevt);
}
default:
return "";
}
}
string dtmfCallback(Native.switch_dtmf_t dtmf)
{
var f = DtmfReceivedFunction;
return f == null ?
"-ERR No DtmfReceivedFunction set." :
f(((char)(byte)dtmf.digit), TimeSpan.FromMilliseconds(dtmf.duration));
}
string eventCallback(Native.switch_event swevt)
{
using (var evt = new FreeSWITCH.Native.Event(swevt, 0)) {
var f = EventReceivedFunction;
return f == null ?
"-ERR No EventReceivedFunction set." :
f(evt);
}
}
protected Native.MonoSession Session { get; private set; } protected Native.MonoSession Session { get; private set; }
protected string Arguments { get; private set; } protected string Arguments { get; private set; }
@ -115,7 +61,7 @@ namespace FreeSWITCH
bool abortable = false; bool abortable = false;
readonly object abortLock = new object(); readonly object abortLock = new object();
Thread runThread; Thread runThread;
void abortRun() internal void AbortRun()
{ {
if (!AbortOnHangup) return; if (!AbortOnHangup) return;
if (runThread == Thread.CurrentThread) { if (runThread == Thread.CurrentThread) {
@ -136,7 +82,7 @@ namespace FreeSWITCH
{ {
this.Session = session; this.Session = session;
this.Arguments = args; this.Arguments = args;
Session.SetDelegates(this.inputCallback, this.hangupCallback); Session.AppToAbort = this;
try { this.Uuid = new Guid(Session.GetUuid()); } try { this.Uuid = new Guid(Session.GetUuid()); }
catch { } catch { }
try { try {

View File

@ -53,13 +53,12 @@ namespace FreeSWITCH.Demo
protected override void Run() protected override void Run()
{ {
HangupFunction = hangupHook;
Session.Answer(); Session.Answer();
this.DtmfReceivedFunction = (d, t) => { Session.DtmfReceivedFunction = (d, t) => {
Log.WriteLine(LogLevel.Info, "Received {0} for {1}.", d, t); Log.WriteLine(LogLevel.Info, "Received {0} for {1}.", d, t);
return ""; return "";
}; };
Log.WriteLine(LogLevel.Info, "Inside AppDemo.Run (args '{0}'); HookState is {1}.", Arguments, Session.HookState); Log.WriteLine(LogLevel.Info, "Inside AppDemo.Run (args '{0}'); HookState is {1}. Now will collect digits.", Arguments, Session.HookState);
Session.CollectDigits(5000); // Hanging up here will cause an abort and the next line won't be written Session.CollectDigits(5000); // Hanging up here will cause an abort and the next line won't be written
Log.WriteLine(LogLevel.Info, "AppDemo is finishing its run and will now hang up."); Log.WriteLine(LogLevel.Info, "AppDemo is finishing its run and will now hang up.");
Session.Hangup("USER_BUSY"); Session.Hangup("USER_BUSY");

View File

@ -227,6 +227,7 @@ namespace FreeSWITCH
if (fType == null) return false; if (fType == null) return false;
using (var session = new Native.MonoSession(new Native.SWIGTYPE_p_switch_core_session(sessionHandle, false))) { using (var session = new Native.MonoSession(new Native.SWIGTYPE_p_switch_core_session(sessionHandle, false))) {
session.Initialize();
session.SetAutoHangup(false); session.SetAutoHangup(false);
try { try {
var f = (AppFunction)Activator.CreateInstance(fType); var f = (AppFunction)Activator.CreateInstance(fType);

View File

@ -35,7 +35,7 @@ using System.Text;
namespace FreeSWITCH.Native namespace FreeSWITCH.Native
{ {
//switch_status_t MonoSession::run_dtmf_callback(void *input, switch_input_type_t itype) // switch_status_t MonoSession::run_dtmf_callback(void *input, switch_input_type_t itype)
// But, process_callback_result is used to turn a string into a switch_status_t // But, process_callback_result is used to turn a string into a switch_status_t
using DtmfCallback = Func<IntPtr, Native.switch_input_type_t, string>; using DtmfCallback = Func<IntPtr, Native.switch_input_type_t, string>;
public partial class MonoSession public partial class MonoSession
@ -44,9 +44,68 @@ namespace FreeSWITCH.Native
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)] [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
static extern void InitMonoSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, Action hangupDelegate); static extern void InitMonoSession(IntPtr sessionPtr, DtmfCallback dtmfDelegate, Action hangupDelegate);
internal void SetDelegates(DtmfCallback dtmfCallback, Action hangupHook) /// <summary>Initializes the native MonoSession. Must be called after Originate.</summary>
public void Initialize()
{ {
InitMonoSession(MonoSession.getCPtr(this).Handle, dtmfCallback, hangupHook); InitMonoSession(MonoSession.getCPtr(this).Handle, inputCallback, hangupCallback);
}
/// <summary>Function to execute when this session hangs up.</summary>
public Action HangupFunction { get; set; }
/// <summary>Sets the application that should have it's run thread aborted (if enabled) when this session is hungup.</summary>
internal AppFunction AppToAbort { get; set; }
void hangupCallback()
{
Log.WriteLine(LogLevel.Debug, "AppFunction is in hangupCallback.");
try {
if (AppToAbort != null) AppToAbort.AbortRun();
var f = HangupFunction;
if (f != null) f();
}
catch (Exception ex) {
Log.WriteLine(LogLevel.Warning, "Exception in hangupCallback: {0}", ex.ToString());
throw;
}
}
public Func<Char, TimeSpan, string> DtmfReceivedFunction { get; set; }
public Func<Native.Event, string> EventReceivedFunction { get; set; }
string inputCallback(IntPtr input, Native.switch_input_type_t inputType)
{
switch (inputType) {
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_DTMF:
using (var dtmf = new Native.switch_dtmf_t(input, false)) {
return dtmfCallback(dtmf);
}
case FreeSWITCH.Native.switch_input_type_t.SWITCH_INPUT_TYPE_EVENT:
using (var swevt = new Native.switch_event(input, false)) {
return eventCallback(swevt);
}
default:
return "";
}
}
string dtmfCallback(Native.switch_dtmf_t dtmf)
{
var f = DtmfReceivedFunction;
return f == null ?
"-ERR No DtmfReceivedFunction set." :
f(((char)(byte)dtmf.digit), TimeSpan.FromMilliseconds(dtmf.duration));
}
string eventCallback(Native.switch_event swevt)
{
using (var evt = new FreeSWITCH.Native.Event(swevt, 0)) {
var f = EventReceivedFunction;
return f == null ?
"-ERR No EventReceivedFunction set." :
f(evt);
}
} }
} }