using System.IO;\r
using System.Linq;\r
using System.Reflection;\r
+using System.Runtime.InteropServices;\r
\r
namespace FreeSWITCH\r
{\r
return File.Exists(path) ? Assembly.LoadFile(path) : null;\r
};\r
\r
+ InitManagedDelegates(_run, _execute, _executeBackground);\r
+\r
// This is a simple one-time loader to get things in memory\r
// Some day we should allow reloading of modules or something\r
loadAssemblies(managedDir)\r
return true;\r
}\r
\r
+ delegate bool ExecuteDelegate(string cmd, IntPtr streamH, IntPtr eventH);\r
+ delegate bool ExecuteBackgroundDelegate(string cmd);\r
+ delegate bool RunDelegate(string cmd, IntPtr session);\r
+ static readonly ExecuteDelegate _execute = Execute;\r
+ static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground;\r
+ static readonly RunDelegate _run = Run;\r
+ //SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) \r
+ [DllImport("mod_managed")]\r
+ static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground);\r
+\r
// Be rather lenient in finding the Load and Unload methods\r
static readonly BindingFlags methodBindingFlags =\r
BindingFlags.Static | // Required\r
\r
public static bool ExecuteBackground(string command)\r
{\r
- var parsed = parseCommand(command);\r
- if (parsed == null) return false;\r
- var fullName = parsed[0];\r
- var args = parsed[1];\r
+ try {\r
+ var parsed = parseCommand(command);\r
+ if (parsed == null) return false;\r
+ var fullName = parsed[0];\r
+ var args = parsed[1];\r
\r
- var fType = getFunctionType<ApiFunction>(fullName);\r
- if (fType == null) return false;\r
+ var fType = getFunctionType<ApiFunction>(fullName);\r
+ if (fType == null) return false;\r
\r
- new System.Threading.Thread(() => {\r
- try {\r
- var f = (ApiFunction)Activator.CreateInstance(fType);\r
- f.ExecuteBackground(args);\r
- Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);\r
- }\r
- catch (Exception ex) {\r
- logException("ExecuteBackground", fullName, ex);\r
- }\r
- }).Start();\r
- return true;\r
+ new System.Threading.Thread(() => {\r
+ try {\r
+ var f = (ApiFunction)Activator.CreateInstance(fType);\r
+ f.ExecuteBackground(args);\r
+ Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);\r
+ } catch (Exception ex) {\r
+ logException("ExecuteBackground", fullName, ex);\r
+ }\r
+ }).Start();\r
+ return true;\r
+ } catch (Exception ex) {\r
+ Log.WriteLine(LogLevel.Error, "Exception in ExecuteBackground({0}): {1}", command, ex.ToString());\r
+ return false;\r
+ }\r
}\r
\r
public static bool Execute(string command, IntPtr streamHandle, IntPtr eventHandle)\r
\r
mod_managed_globals globals = { 0 };\r
\r
+// Global delegates to call managed functions\r
+typedef int (*runFunction)(const char *data, void *sessionPtr);\r
+typedef int (*executeFunction)(const char *cmd, void *stream, void *Event);\r
+typedef int (*executeBackgroundFunction)(const char* cmd);\r
+static runFunction runDelegate;\r
+static executeFunction executeDelegate;\r
+static executeBackgroundFunction executeBackgroundDelegate;\r
+\r
+SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) \r
+{\r
+ runDelegate = run;\r
+ executeDelegate = execute;\r
+ executeBackgroundDelegate = executeBackground;\r
+}\r
+\r
// Sets up delegates (and anything else needed) on the ManagedSession object\r
// Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC\r
// Exported method.\r
return method;\r
}\r
\r
+\r
switch_status_t findLoader() \r
{\r
/* Find loader class and methods */ \r
return SWITCH_STATUS_FALSE;\r
}\r
\r
- if (!(globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass))) {\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-\r
- if (!(globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass))) {\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-\r
- if (!(globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass))) {\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");\r
return SWITCH_STATUS_SUCCESS;\r
}\r
try {\r
FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load");\r
FreeSwitchManaged::unloadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Unload");\r
- FreeSwitchManaged::runMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Run");\r
- FreeSwitchManaged::executeMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Execute");\r
- FreeSwitchManaged::executeBackgroundMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("ExecuteBackground");\r
} catch(Exception^ ex) {\r
IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not load FreeSWITCH.Loader class: %s\n", static_cast<const char*>(msg.ToPointer()));\r
stream->write_function(stream, "-ERR no args specified!\n"); \r
return SWITCH_STATUS_SUCCESS;\r
}\r
-#ifdef _MANAGED\r
- Object ^objResult;\r
- try {\r
- objResult = FreeSwitchManaged::executeBackgroundMethod->Invoke(nullptr, gcnew array<Object^> { gcnew String(cmd) } );\r
- success = *reinterpret_cast<bool^>(objResult);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");\r
- } catch(Exception^ ex) {\r
- IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
- stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception: %s\n", static_cast<const char*>(msg.ToPointer()));\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true: %s\n", static_cast<const char*>(msg.ToPointer()));\r
- Marshal::FreeHGlobal(msg);\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-#else\r
- mono_thread_attach(globals.domain);\r
- void *args[1];\r
-\r
- args[0] = mono_string_new(globals.domain, cmd);\r
- MonoObject * exception = NULL;\r
- MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);\r
- success = *(int *) mono_object_unbox(objResult);\r
-\r
- if (exception) {\r
- stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");\r
- mono_print_unhandled_exception(exception);\r
- return SWITCH_STATUS_SUCCESS;\r
- }\r
-#endif\r
+ success = executeBackgroundDelegate(cmd);\r
if (success) {\r
stream->write_function(stream, "+OK\n");\r
} else { \r
- stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n");\r
+ stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module or exception?).\n");\r
}\r
-\r
return SWITCH_STATUS_SUCCESS;\r
}\r
\r
stream->write_function(stream, "-ERR no args specified!\n"); \r
return SWITCH_STATUS_SUCCESS;\r
}\r
-#ifdef _MANAGED\r
- Object ^objResult;\r
- try {\r
- objResult = FreeSwitchManaged::executeMethod->Invoke(nullptr, gcnew array<Object^>{gcnew String(cmd),gcnew IntPtr(stream), gcnew IntPtr(stream->param_event)});\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute completed successfully.\n");\r
- success = *reinterpret_cast<bool^>(objResult);\r
- } catch(Exception ^ex) {\r
- IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute cli %s: %s\n", cmd, static_cast<const char*>(msg.ToPointer()));\r
- Marshal::FreeHGlobal(msg);\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-#else\r
- mono_thread_attach(globals.domain);\r
- void *args[3];\r
-\r
- args[0] = mono_string_new(globals.domain, cmd);\r
- args[1] = &stream; // Address of the arguments\r
- args[2] = &(stream->param_event);\r
-\r
- MonoObject * exception = NULL;\r
- MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception);\r
- success = *(int *) mono_object_unbox(objResult);\r
-\r
- if (exception) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);\r
- mono_print_unhandled_exception(exception);\r
- }\r
-#endif\r
+ success = executeDelegate(cmd, stream, stream->param_event);\r
if (!success) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);\r
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module or exception).\n", cmd); \r
}\r
return SWITCH_STATUS_SUCCESS;\r
}\r
int success;\r
if (switch_strlen_zero(data)) {\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");\r
- }\r
-#ifdef _MANAGED\r
- Object ^objResult;\r
- try {\r
- objResult = FreeSwitchManaged::runMethod->Invoke(nullptr, gcnew array<Object^>{gcnew String(data),gcnew IntPtr(session)});\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RunMethod completed successfully.\n");\r
- success = *reinterpret_cast<bool^>(objResult);\r
- }\r
- catch(Exception ^ex) {\r
- IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s %s.\n", data, static_cast<const char*>(msg.ToPointer()));\r
- Marshal::FreeHGlobal(msg);\r
return;\r
}\r
-#else\r
- mono_thread_attach(globals.domain);\r
- void *args[2];\r
-\r
- args[0] = mono_string_new(globals.domain, data);\r
- args[1] = &session;\r
-\r
- MonoObject * exception = NULL;\r
- MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception);\r
- success = *(int *) mono_object_unbox(objResult);\r
-\r
- if (exception) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);\r
- mono_print_unhandled_exception(exception);\r
- }\r
-#endif\r
+ success = runDelegate(data, session);\r
if (!success) {\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);\r
}\r
}\r
\r
\r
+\r
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown) \r
{\r
#ifdef _MANAGED\r