From b0be67090c398cabf7020d06028bcb870adf76be Mon Sep 17 00:00:00 2001 From: Michael Giagnocavo Date: Sat, 4 Oct 2008 21:29:32 +0000 Subject: [PATCH] No more dynamic invoke for run/execute[bg] git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9841 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- .../mod_managed/freeswitch_managed.h | 7 +- .../languages/mod_managed/managed/Loader.cs | 51 ++++--- src/mod/languages/mod_managed/mod_managed.cpp | 125 +++--------------- 3 files changed, 57 insertions(+), 126 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_managed.h b/src/mod/languages/mod_managed/freeswitch_managed.h index b1be25e314..2bbd0b80b6 100644 --- a/src/mod/languages/mod_managed/freeswitch_managed.h +++ b/src/mod/languages/mod_managed/freeswitch_managed.h @@ -41,6 +41,7 @@ SWITCH_BEGIN_EXTERN_C typedef void (*hangupFunction)(void); typedef char* (*inputFunction)(void*, switch_input_type_t); + #ifndef _MANAGED #include #include @@ -60,9 +61,6 @@ struct mod_managed_globals { MonoMethod *loadMethod; MonoMethod *unloadMethod; - MonoMethod *runMethod; - MonoMethod *executeMethod; - MonoMethod *executeBackgroundMethod; #endif }; typedef struct mod_managed_globals mod_managed_globals; @@ -124,9 +122,6 @@ public: static Assembly^ mod_dotnet_managed; static MethodInfo^ loadMethod; static MethodInfo^ unloadMethod; - static MethodInfo^ runMethod; - static MethodInfo^ executeMethod; - static MethodInfo^ executeBackgroundMethod; }; #endif diff --git a/src/mod/languages/mod_managed/managed/Loader.cs b/src/mod/languages/mod_managed/managed/Loader.cs index c49ad78954..00b5e54f97 100644 --- a/src/mod/languages/mod_managed/managed/Loader.cs +++ b/src/mod/languages/mod_managed/managed/Loader.cs @@ -36,6 +36,7 @@ using System.Text; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; namespace FreeSWITCH { @@ -65,6 +66,8 @@ namespace FreeSWITCH return File.Exists(path) ? Assembly.LoadFile(path) : null; }; + InitManagedDelegates(_run, _execute, _executeBackground); + // This is a simple one-time loader to get things in memory // Some day we should allow reloading of modules or something loadAssemblies(managedDir) @@ -77,6 +80,16 @@ namespace FreeSWITCH return true; } + delegate bool ExecuteDelegate(string cmd, IntPtr streamH, IntPtr eventH); + delegate bool ExecuteBackgroundDelegate(string cmd); + delegate bool RunDelegate(string cmd, IntPtr session); + static readonly ExecuteDelegate _execute = Execute; + static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground; + static readonly RunDelegate _run = Run; + //SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) + [DllImport("mod_managed")] + static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground); + // Be rather lenient in finding the Load and Unload methods static readonly BindingFlags methodBindingFlags = BindingFlags.Static | // Required @@ -181,25 +194,29 @@ namespace FreeSWITCH public static bool ExecuteBackground(string command) { - var parsed = parseCommand(command); - if (parsed == null) return false; - var fullName = parsed[0]; - var args = parsed[1]; + try { + var parsed = parseCommand(command); + if (parsed == null) return false; + var fullName = parsed[0]; + var args = parsed[1]; - var fType = getFunctionType(fullName); - if (fType == null) return false; + var fType = getFunctionType(fullName); + if (fType == null) return false; - new System.Threading.Thread(() => { - try { - var f = (ApiFunction)Activator.CreateInstance(fType); - f.ExecuteBackground(args); - Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName); - } - catch (Exception ex) { - logException("ExecuteBackground", fullName, ex); - } - }).Start(); - return true; + new System.Threading.Thread(() => { + try { + var f = (ApiFunction)Activator.CreateInstance(fType); + f.ExecuteBackground(args); + Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName); + } catch (Exception ex) { + logException("ExecuteBackground", fullName, ex); + } + }).Start(); + return true; + } catch (Exception ex) { + Log.WriteLine(LogLevel.Error, "Exception in ExecuteBackground({0}): {1}", command, ex.ToString()); + return false; + } } public static bool Execute(string command, IntPtr streamHandle, IntPtr eventHandle) diff --git a/src/mod/languages/mod_managed/mod_managed.cpp b/src/mod/languages/mod_managed/mod_managed.cpp index 1882c196ce..7233db8c2d 100644 --- a/src/mod/languages/mod_managed/mod_managed.cpp +++ b/src/mod/languages/mod_managed/mod_managed.cpp @@ -63,6 +63,21 @@ SWITCH_STANDARD_APP(managed_app_function); /* Run */ mod_managed_globals globals = { 0 }; +// Global delegates to call managed functions +typedef int (*runFunction)(const char *data, void *sessionPtr); +typedef int (*executeFunction)(const char *cmd, void *stream, void *Event); +typedef int (*executeBackgroundFunction)(const char* cmd); +static runFunction runDelegate; +static executeFunction executeDelegate; +static executeBackgroundFunction executeBackgroundDelegate; + +SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) +{ + runDelegate = run; + executeDelegate = execute; + executeBackgroundDelegate = executeBackground; +} + // Sets up delegates (and anything else needed) on the ManagedSession object // Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC // Exported method. @@ -222,6 +237,7 @@ MonoMethod * getMethod(const char *name, MonoClass * klass) return method; } + switch_status_t findLoader() { /* Find loader class and methods */ @@ -241,18 +257,6 @@ switch_status_t findLoader() return SWITCH_STATUS_FALSE; } - if (!(globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass))) { - return SWITCH_STATUS_FALSE; - } - - if (!(globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass))) { - return SWITCH_STATUS_FALSE; - } - - if (!(globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass))) { - return SWITCH_STATUS_FALSE; - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n"); return SWITCH_STATUS_SUCCESS; } @@ -288,9 +292,6 @@ switch_status_t findLoader() try { FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load"); FreeSwitchManaged::unloadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Unload"); - FreeSwitchManaged::runMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Run"); - FreeSwitchManaged::executeMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Execute"); - FreeSwitchManaged::executeBackgroundMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("ExecuteBackground"); } catch(Exception^ ex) { IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString()); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not load FreeSWITCH.Loader class: %s\n", static_cast(msg.ToPointer())); @@ -372,40 +373,12 @@ SWITCH_STANDARD_API(managedrun_api_function) stream->write_function(stream, "-ERR no args specified!\n"); return SWITCH_STATUS_SUCCESS; } -#ifdef _MANAGED - Object ^objResult; - try { - objResult = FreeSwitchManaged::executeBackgroundMethod->Invoke(nullptr, gcnew array { gcnew String(cmd) } ); - success = *reinterpret_cast(objResult); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n"); - } catch(Exception^ ex) { - IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString()); - stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception: %s\n", static_cast(msg.ToPointer())); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true: %s\n", static_cast(msg.ToPointer())); - Marshal::FreeHGlobal(msg); - return SWITCH_STATUS_FALSE; - } -#else - mono_thread_attach(globals.domain); - void *args[1]; - - args[0] = mono_string_new(globals.domain, cmd); - MonoObject * exception = NULL; - MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception); - success = *(int *) mono_object_unbox(objResult); - - if (exception) { - stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n"); - mono_print_unhandled_exception(exception); - return SWITCH_STATUS_SUCCESS; - } -#endif + success = executeBackgroundDelegate(cmd); if (success) { stream->write_function(stream, "+OK\n"); } else { - stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n"); + stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module or exception?).\n"); } - return SWITCH_STATUS_SUCCESS; } @@ -417,37 +390,9 @@ SWITCH_STANDARD_API(managed_api_function) stream->write_function(stream, "-ERR no args specified!\n"); return SWITCH_STATUS_SUCCESS; } -#ifdef _MANAGED - Object ^objResult; - try { - objResult = FreeSwitchManaged::executeMethod->Invoke(nullptr, gcnew array{gcnew String(cmd),gcnew IntPtr(stream), gcnew IntPtr(stream->param_event)}); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute completed successfully.\n"); - success = *reinterpret_cast(objResult); - } catch(Exception ^ex) { - IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString()); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute cli %s: %s\n", cmd, static_cast(msg.ToPointer())); - Marshal::FreeHGlobal(msg); - return SWITCH_STATUS_FALSE; - } -#else - mono_thread_attach(globals.domain); - void *args[3]; - - args[0] = mono_string_new(globals.domain, cmd); - args[1] = &stream; // Address of the arguments - args[2] = &(stream->param_event); - - MonoObject * exception = NULL; - MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception); - success = *(int *) mono_object_unbox(objResult); - - if (exception) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd); - mono_print_unhandled_exception(exception); - } -#endif + success = executeDelegate(cmd, stream, stream->param_event); if (!success) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module or exception).\n", cmd); } return SWITCH_STATUS_SUCCESS; } @@ -458,42 +403,16 @@ SWITCH_STANDARD_APP(managed_app_function) int success; if (switch_strlen_zero(data)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n"); - } -#ifdef _MANAGED - Object ^objResult; - try { - objResult = FreeSwitchManaged::runMethod->Invoke(nullptr, gcnew array{gcnew String(data),gcnew IntPtr(session)}); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RunMethod completed successfully.\n"); - success = *reinterpret_cast(objResult); - } - catch(Exception ^ex) { - IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString()); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s %s.\n", data, static_cast(msg.ToPointer())); - Marshal::FreeHGlobal(msg); return; } -#else - mono_thread_attach(globals.domain); - void *args[2]; - - args[0] = mono_string_new(globals.domain, data); - args[1] = &session; - - MonoObject * exception = NULL; - MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception); - success = *(int *) mono_object_unbox(objResult); - - 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); - } -#endif + success = runDelegate(data, session); if (!success) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data); } } + SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown) { #ifdef _MANAGED