]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Added managedload, more cleanup
authorMichael Giagnocavo <mgg@giagnocavo.net>
Sun, 5 Oct 2008 03:24:12 +0000 (03:24 +0000)
committerMichael Giagnocavo <mgg@giagnocavo.net>
Sun, 5 Oct 2008 03:24:12 +0000 (03:24 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9843 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/languages/mod_managed/freeswitch_managed.h
src/mod/languages/mod_managed/managed/ApiFunction.cs
src/mod/languages/mod_managed/managed/AppFunction.cs
src/mod/languages/mod_managed/managed/AssemblyInfo.cs
src/mod/languages/mod_managed/managed/Demo.cs
src/mod/languages/mod_managed/managed/Loader.cs
src/mod/languages/mod_managed/mod_managed.cpp

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