[Freeswitch-svn] [commit] r9843 - in freeswitch/trunk/src/mod/languages/mod_managed: . managed
Freeswitch SVN
michaelgg at freeswitch.org
Sat Oct 4 23:24:13 EDT 2008
Author: michaelgg
Date: Sat Oct 4 23:24:12 2008
New Revision: 9843
Modified:
freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_managed.h
freeswitch/trunk/src/mod/languages/mod_managed/managed/ApiFunction.cs
freeswitch/trunk/src/mod/languages/mod_managed/managed/AppFunction.cs
freeswitch/trunk/src/mod/languages/mod_managed/managed/AssemblyInfo.cs
freeswitch/trunk/src/mod/languages/mod_managed/managed/Demo.cs
freeswitch/trunk/src/mod/languages/mod_managed/managed/Loader.cs
freeswitch/trunk/src/mod/languages/mod_managed/mod_managed.cpp
Log:
Added managedload, more cleanup
Modified: freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_managed.h
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_managed.h (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/freeswitch_managed.h Sat Oct 4 23:24:12 2008
@@ -60,7 +60,6 @@
switch_bool_t embedded;
MonoMethod *loadMethod;
- MonoMethod *unloadMethod;
#endif
};
typedef struct mod_managed_globals mod_managed_globals;
@@ -121,7 +120,6 @@
public:
static Assembly^ mod_dotnet_managed;
static MethodInfo^ loadMethod;
- static MethodInfo^ unloadMethod;
};
#endif
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/ApiFunction.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/ApiFunction.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/ApiFunction.cs Sat Oct 4 23:24:12 2008
@@ -40,8 +40,6 @@
{
protected static bool Load() { return true; }
- protected static void Unload() { }
-
public abstract void ExecuteBackground(string args);
public abstract void Execute(FreeSWITCH.Native.Stream stream, FreeSWITCH.Native.Event evt, string args);
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/AppFunction.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/AppFunction.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/AppFunction.cs Sat Oct 4 23:24:12 2008
@@ -41,8 +41,6 @@
{
protected static bool Load() { return true; }
- protected static void Unload() { }
-
protected Native.ManagedSession Session { get; private set; }
protected string Arguments { get; private set; }
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/AssemblyInfo.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/AssemblyInfo.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/AssemblyInfo.cs Sat Oct 4 23:24:12 2008
@@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
-[assembly: AssemblyTitle("mod_mono_managed")]
+[assembly: AssemblyTitle("mod_managed_lib")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("mod_mono_managed")]
+[assembly: AssemblyProduct("mod_managed_lib")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.0.2.0")]
+[assembly: AssemblyFileVersion("1.0.2.0")]
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/Demo.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/Demo.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/Demo.cs Sat Oct 4 23:24:12 2008
@@ -46,11 +46,6 @@
return true;
}
- new protected static void Unload()
- {
- Log.WriteLine(LogLevel.Info, "Inside AppDemo::Unload.");
- }
-
protected override void Run()
{
Session.Answer();
@@ -80,11 +75,6 @@
return true;
}
- new protected static void Unload()
- {
- Log.WriteLine(LogLevel.Debug, "Inside ApiDemo::Unload.");
- }
-
public override void ExecuteBackground(string args)
{
Log.WriteLine(LogLevel.Debug, "ApiDemo on a background thread #({0}), with args '{1}'.",
Modified: freeswitch/trunk/src/mod/languages/mod_managed/managed/Loader.cs
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/managed/Loader.cs (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/managed/Loader.cs Sat Oct 4 23:24:12 2008
@@ -43,15 +43,17 @@
internal static class Loader
{
// Stores a list of the loaded function types so we can instantiate them as needed
- static readonly Dictionary<string, Type> functions = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
+ static Dictionary<string, Type> functions = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
// Only class name. Last in wins.
- static readonly Dictionary<string, Type> shortFunctions = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase);
+ static Dictionary<string, Type> shortFunctions = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
#region Load/Unload
+ static string managedDir;
+
public static bool Load()
{
- string managedDir = Path.Combine(Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir, "managed");
+ managedDir = Path.Combine(Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir, "managed");
Log.WriteLine(LogLevel.Debug, "mod_managed_lib loader is starting with directory '{0}'.", managedDir);
if (!Directory.Exists(managedDir)) {
Log.WriteLine(LogLevel.Error, "Managed directory not found: {0}", managedDir);
@@ -66,29 +68,43 @@
return File.Exists(path) ? Assembly.LoadFile(path) : null;
};
- InitManagedDelegates(_run, _execute, _executeBackground);
+ InitManagedDelegates(_run, _execute, _executeBackground, _loadAssembly);
// This is a simple one-time loader to get things in memory
// Some day we should allow reloading of modules or something
- loadAssemblies(managedDir)
- .SelectMany(a => a.GetExportedTypes())
- .Where(t => !t.IsAbstract)
- .Where(t => t.IsSubclassOf(typeof(AppFunction)) || t.IsSubclassOf(typeof(ApiFunction)))
- .ToList()
- .loadFunctions();
+ var allTypes = loadAssemblies(managedDir).SelectMany(a => a.GetExportedTypes());
+ loadFunctions(allTypes);
return true;
}
+ public static bool LoadAssembly(string filename) {
+ try {
+ string path = Path.Combine(managedDir, filename);
+ if (!File.Exists(path)) {
+ Log.WriteLine(LogLevel.Error, "File not found: '{0}'.", path);
+ return false;
+ }
+ var asm = Assembly.LoadFile(path);
+ loadFunctions(asm.GetExportedTypes());
+ return true;
+ } catch (Exception ex) {
+ Log.WriteLine(LogLevel.Error, "Exception in LoadAssembly('{0}'): {1}", filename, ex.ToString());
+ return false;
+ }
+ }
+
delegate bool ExecuteDelegate(string cmd, IntPtr streamH, IntPtr eventH);
delegate bool ExecuteBackgroundDelegate(string cmd);
delegate bool RunDelegate(string cmd, IntPtr session);
+ delegate bool LoadAssemblyDelegate(string filename);
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);
+ static readonly LoadAssemblyDelegate _loadAssembly = LoadAssembly;
+ //SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, loadAssemblyFunction loadAssembly)
+ [DllImport("mod_managed", CharSet = CharSet.Ansi)]
+ static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground, LoadAssemblyDelegate loadAssembly);
// Be rather lenient in finding the Load and Unload methods
static readonly BindingFlags methodBindingFlags =
@@ -97,13 +113,18 @@
BindingFlags.IgnoreCase | // Some case insensitive languages?
BindingFlags.FlattenHierarchy; // Allow inherited methods for hierarchies
- static void loadFunctions(this List<Type> allTypes)
+ static void loadFunctions(IEnumerable<Type> allTypes)
{
- foreach (var t in allTypes) {
+ var functions = new Dictionary<string, Type>(Loader.functions, StringComparer.OrdinalIgnoreCase);
+ var shortFunctions = new Dictionary<string, Type>(Loader.shortFunctions, StringComparer.OrdinalIgnoreCase);
+ var filteredTypes = allTypes
+ .Where(t => !t.IsAbstract)
+ .Where(t => t.IsSubclassOf(typeof(AppFunction)) || t.IsSubclassOf(typeof(ApiFunction)));
+ foreach (var t in filteredTypes) {
try {
if (functions.ContainsKey(t.FullName)) {
- Log.WriteLine(LogLevel.Error, "Duplicate function {0}. Skipping.", t.FullName);
- continue;
+ functions.Remove(t.FullName);
+ Log.WriteLine(LogLevel.Warning, "Replacing function {0}.", t.FullName);
}
var loadMethod = t.GetMethod("Load", methodBindingFlags, null, Type.EmptyTypes, null);
var shouldLoad = Convert.ToBoolean(loadMethod.Invoke(null, null)); // We don't require the Load method to return a bool exactly
@@ -120,6 +141,8 @@
logException("Load", t.FullName, ex);
}
}
+ Loader.functions = functions;
+ Loader.shortFunctions = shortFunctions;
}
static Assembly[] loadAssemblies(string managedDir)
@@ -248,7 +271,7 @@
/// <summary>Runs an application function.</summary>
public static bool Run(string command, IntPtr sessionHandle)
{
- Log.WriteLine(LogLevel.Debug, "mod_mono attempting to run application '{0}'.", command);
+ Log.WriteLine(LogLevel.Debug, "mod_managed_lib: attempting to run application '{0}'.", command);
System.Diagnostics.Debug.Assert(sessionHandle != IntPtr.Zero, "sessionHandle is null.");
var parsed = parseCommand(command);
if (parsed == null) return false;
Modified: freeswitch/trunk/src/mod/languages/mod_managed/mod_managed.cpp
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_managed/mod_managed.cpp (original)
+++ freeswitch/trunk/src/mod/languages/mod_managed/mod_managed.cpp Sat Oct 4 23:24:12 2008
@@ -47,17 +47,17 @@
SWITCH_BEGIN_EXTERN_C
SWITCH_MODULE_LOAD_FUNCTION(mod_managed_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown);
-SWITCH_MODULE_DEFINITION(mod_managed, mod_managed_load, mod_managed_shutdown, NULL);
+SWITCH_MODULE_DEFINITION(mod_managed, mod_managed_load, NULL, NULL);
SWITCH_STANDARD_API(managedrun_api_function); /* ExecuteBackground */
SWITCH_STANDARD_API(managed_api_function); /* Execute */
SWITCH_STANDARD_APP(managed_app_function); /* Run */
+SWITCH_STANDARD_API(managed_loadassembly); /* Load assembly */
#define MOD_MANAGED_ASM_NAME "mod_managed_lib"
#define MOD_MANAGED_ASM_V1 1
#define MOD_MANAGED_ASM_V2 0
-#define MOD_MANAGED_ASM_V3 0
+#define MOD_MANAGED_ASM_V3 2
#define MOD_MANAGED_ASM_V4 0
#define MOD_MANAGED_DLL MOD_MANAGED_ASM_NAME ".dll"
@@ -67,15 +67,18 @@
typedef int (*runFunction)(const char *data, void *sessionPtr);
typedef int (*executeFunction)(const char *cmd, void *stream, void *Event);
typedef int (*executeBackgroundFunction)(const char* cmd);
+typedef int (*loadAssemblyFunction)(const char* filename);
static runFunction runDelegate;
static executeFunction executeDelegate;
static executeBackgroundFunction executeBackgroundDelegate;
+static loadAssemblyFunction loadAssemblyDelegate;
-SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground)
+SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, loadAssemblyFunction loadAssembly)
{
runDelegate = run;
executeDelegate = execute;
executeBackgroundDelegate = executeBackground;
+ loadAssemblyDelegate = loadAssembly;
}
// Sets up delegates (and anything else needed) on the ManagedSession object
@@ -253,10 +256,6 @@
return SWITCH_STATUS_FALSE;
}
- if (!(globals.unloadMethod = getMethod("FreeSWITCH.Loader:Unload()", loaderClass))) {
- return SWITCH_STATUS_FALSE;
- }
-
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");
return SWITCH_STATUS_SUCCESS;
}
@@ -291,7 +290,6 @@
{
try {
FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load");
- FreeSwitchManaged::unloadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Unload");
} 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<const char*>(msg.ToPointer()));
@@ -363,6 +361,7 @@
SWITCH_ADD_API(api_interface, "managedrun", "Run a module (ExecuteBackground)", managedrun_api_function, "<module> [<args>]");
SWITCH_ADD_API(api_interface, "managed", "Run a module as an API function (Execute)", managed_api_function, "<module> [<args>]");
SWITCH_ADD_APP(app_interface, "managed", "Run CLI App", "Run an App on a channel", managed_app_function, "<modulename> [<args>]", SAF_NONE);
+ SWITCH_ADD_API(api_interface, "managedload", "Load assembly", managed_loadassembly, "<filename>");
return SWITCH_STATUS_SUCCESS;
}
@@ -407,41 +406,23 @@
}
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_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module or exception).\n", data);
}
}
-
-
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown)
+SWITCH_STANDARD_API(managed_loadassembly)
{
-#ifdef _MANAGED
- Object ^objResult;
- try {
- objResult = FreeSwitchManaged::unloadMethod->Invoke(nullptr, nullptr);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "UnloadMethod completed successfully.\n");
- }
- catch(Exception^ ex) {
- IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception occurred in Loader::Unload: %s\n", static_cast<const char*>(msg.ToPointer()));
- Marshal::FreeHGlobal(msg);
- return SWITCH_STATUS_FALSE;;
- }
-#else
- MonoObject * ex;
-
- mono_thread_attach(globals.domain);
- 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);
+ int success;
+ if (switch_strlen_zero(cmd)) {
+ stream->write_function(stream, "-ERR no args specified!\n");
+ return SWITCH_STATUS_SUCCESS;
}
-
- if (!globals.embedded) {
- mono_jit_cleanup(globals.domain);
+ success = loadAssemblyDelegate(cmd);
+ if (success) {
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR LoadAssembly returned false (invalid file or exception).\n");
}
-#endif
return SWITCH_STATUS_SUCCESS;
}
More information about the Freeswitch-svn
mailing list