[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