No more dynamic invoke for run/execute[bg]
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9841 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
6854eb5dae
commit
b0be67090c
|
@ -41,6 +41,7 @@ SWITCH_BEGIN_EXTERN_C
|
||||||
typedef void (*hangupFunction)(void);
|
typedef void (*hangupFunction)(void);
|
||||||
typedef char* (*inputFunction)(void*, switch_input_type_t);
|
typedef char* (*inputFunction)(void*, switch_input_type_t);
|
||||||
|
|
||||||
|
|
||||||
#ifndef _MANAGED
|
#ifndef _MANAGED
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <mono/jit/jit.h>
|
#include <mono/jit/jit.h>
|
||||||
|
@ -60,9 +61,6 @@ struct mod_managed_globals {
|
||||||
|
|
||||||
MonoMethod *loadMethod;
|
MonoMethod *loadMethod;
|
||||||
MonoMethod *unloadMethod;
|
MonoMethod *unloadMethod;
|
||||||
MonoMethod *runMethod;
|
|
||||||
MonoMethod *executeMethod;
|
|
||||||
MonoMethod *executeBackgroundMethod;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
typedef struct mod_managed_globals mod_managed_globals;
|
typedef struct mod_managed_globals mod_managed_globals;
|
||||||
|
@ -124,9 +122,6 @@ public:
|
||||||
static Assembly^ mod_dotnet_managed;
|
static Assembly^ mod_dotnet_managed;
|
||||||
static MethodInfo^ loadMethod;
|
static MethodInfo^ loadMethod;
|
||||||
static MethodInfo^ unloadMethod;
|
static MethodInfo^ unloadMethod;
|
||||||
static MethodInfo^ runMethod;
|
|
||||||
static MethodInfo^ executeMethod;
|
|
||||||
static MethodInfo^ executeBackgroundMethod;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,6 +36,7 @@ using System.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace FreeSWITCH
|
namespace FreeSWITCH
|
||||||
{
|
{
|
||||||
|
@ -65,6 +66,8 @@ namespace FreeSWITCH
|
||||||
return File.Exists(path) ? Assembly.LoadFile(path) : null;
|
return File.Exists(path) ? Assembly.LoadFile(path) : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
InitManagedDelegates(_run, _execute, _executeBackground);
|
||||||
|
|
||||||
// This is a simple one-time loader to get things in memory
|
// This is a simple one-time loader to get things in memory
|
||||||
// Some day we should allow reloading of modules or something
|
// Some day we should allow reloading of modules or something
|
||||||
loadAssemblies(managedDir)
|
loadAssemblies(managedDir)
|
||||||
|
@ -77,6 +80,16 @@ namespace FreeSWITCH
|
||||||
return true;
|
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
|
// Be rather lenient in finding the Load and Unload methods
|
||||||
static readonly BindingFlags methodBindingFlags =
|
static readonly BindingFlags methodBindingFlags =
|
||||||
BindingFlags.Static | // Required
|
BindingFlags.Static | // Required
|
||||||
|
@ -181,6 +194,7 @@ namespace FreeSWITCH
|
||||||
|
|
||||||
public static bool ExecuteBackground(string command)
|
public static bool ExecuteBackground(string command)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
var parsed = parseCommand(command);
|
var parsed = parseCommand(command);
|
||||||
if (parsed == null) return false;
|
if (parsed == null) return false;
|
||||||
var fullName = parsed[0];
|
var fullName = parsed[0];
|
||||||
|
@ -194,12 +208,15 @@ namespace FreeSWITCH
|
||||||
var f = (ApiFunction)Activator.CreateInstance(fType);
|
var f = (ApiFunction)Activator.CreateInstance(fType);
|
||||||
f.ExecuteBackground(args);
|
f.ExecuteBackground(args);
|
||||||
Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);
|
Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex) {
|
|
||||||
logException("ExecuteBackground", fullName, ex);
|
logException("ExecuteBackground", fullName, ex);
|
||||||
}
|
}
|
||||||
}).Start();
|
}).Start();
|
||||||
return true;
|
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)
|
public static bool Execute(string command, IntPtr streamHandle, IntPtr eventHandle)
|
||||||
|
|
|
@ -63,6 +63,21 @@ SWITCH_STANDARD_APP(managed_app_function); /* Run */
|
||||||
|
|
||||||
mod_managed_globals globals = { 0 };
|
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
|
// 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
|
// Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC
|
||||||
// Exported method.
|
// Exported method.
|
||||||
|
@ -222,6 +237,7 @@ MonoMethod * getMethod(const char *name, MonoClass * klass)
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch_status_t findLoader()
|
switch_status_t findLoader()
|
||||||
{
|
{
|
||||||
/* Find loader class and methods */
|
/* Find loader class and methods */
|
||||||
|
@ -241,18 +257,6 @@ switch_status_t findLoader()
|
||||||
return SWITCH_STATUS_FALSE;
|
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");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -288,9 +292,6 @@ switch_status_t findLoader()
|
||||||
try {
|
try {
|
||||||
FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load");
|
FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load");
|
||||||
FreeSwitchManaged::unloadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Unload");
|
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) {
|
} catch(Exception^ ex) {
|
||||||
IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());
|
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<const char*>(msg.ToPointer()));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not load FreeSWITCH.Loader class: %s\n", static_cast<const char*>(msg.ToPointer()));
|
||||||
|
@ -372,40 +373,12 @@ SWITCH_STANDARD_API(managedrun_api_function)
|
||||||
stream->write_function(stream, "-ERR no args specified!\n");
|
stream->write_function(stream, "-ERR no args specified!\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
#ifdef _MANAGED
|
success = executeBackgroundDelegate(cmd);
|
||||||
Object ^objResult;
|
|
||||||
try {
|
|
||||||
objResult = FreeSwitchManaged::executeBackgroundMethod->Invoke(nullptr, gcnew array<Object^> { gcnew String(cmd) } );
|
|
||||||
success = *reinterpret_cast<bool^>(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<const char*>(msg.ToPointer()));
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true: %s\n", static_cast<const char*>(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
|
|
||||||
if (success) {
|
if (success) {
|
||||||
stream->write_function(stream, "+OK\n");
|
stream->write_function(stream, "+OK\n");
|
||||||
} else {
|
} 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;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,37 +390,9 @@ SWITCH_STANDARD_API(managed_api_function)
|
||||||
stream->write_function(stream, "-ERR no args specified!\n");
|
stream->write_function(stream, "-ERR no args specified!\n");
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
#ifdef _MANAGED
|
success = executeDelegate(cmd, stream, stream->param_event);
|
||||||
Object ^objResult;
|
|
||||||
try {
|
|
||||||
objResult = FreeSwitchManaged::executeMethod->Invoke(nullptr, gcnew array<Object^>{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<bool^>(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<const char*>(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
|
|
||||||
if (!success) {
|
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;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -458,42 +403,16 @@ SWITCH_STANDARD_APP(managed_app_function)
|
||||||
int success;
|
int success;
|
||||||
if (switch_strlen_zero(data)) {
|
if (switch_strlen_zero(data)) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");
|
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<Object^>{gcnew String(data),gcnew IntPtr(session)});
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RunMethod completed successfully.\n");
|
|
||||||
success = *reinterpret_cast<bool^>(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<const char*>(msg.ToPointer()));
|
|
||||||
Marshal::FreeHGlobal(msg);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
success = runDelegate(data, session);
|
||||||
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
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);
|
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)
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown)
|
||||||
{
|
{
|
||||||
#ifdef _MANAGED
|
#ifdef _MANAGED
|
||||||
|
|
Loading…
Reference in New Issue