+++ /dev/null
-/*
- * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- * Copyright (C) 2006, James Martelletti <james@nerdc0re.com>
- *
- * Version: MPL 1.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
- *
- * The Initial Developer of the Original Code is
- * James Martelletti <james@nerdc0re.com>
- * Portions created by the Initial Developer are Copyright (C)
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * James Martelletti <james@nerdc0re.com>
- *
- *
- * mod_mono.c -- Embedded mono runtime.
- *
- */
-#include <mono/jit/jit.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/environment.h>
-#include <mono/metadata/tokentype.h>
-#include <mono/metadata/debug-helpers.h>
-#include <mono/metadata/image.h>
-#include <mono/metadata/threads.h>
-//#include <gc/gc.h>
-#include <switch.h>
-
-#define SWITCH_MONO_MODULES "mono/"
-#define SWITCH_MONO_LIBDIR "lib/"
-#define SWITCH_MONO_ASSEMBLY "FreeSwitch.dll"
-
-/* Module functions */
-switch_status_t mod_mono_load_modules(const char *module_dir);
-MonoClass *mod_mono_find_assembly_class(MonoImage * image);
-
-/* Managed functions */
-void mod_mono_switch_console_printf(switch_text_channel_t channel, char *file, const char *func, int line, char *fmt, char *msg);
-
-SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load);
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown);
-SWITCH_MODULE_DEFINITION(mod_mono, mod_mono_load, mod_mono_shutdown, NULL);
-
-static switch_memory_pool_t *mono_pool = NULL;
-
-static struct {
- MonoDomain *domain;
- switch_hash_t *plugins;
-} globals;
-
-typedef struct {
- MonoAssembly *assembly;
- MonoClass *class;
- MonoObject *object;
-} mono_plugin;
-
-static switch_loadable_module_interface_t mono_module_interface = {
- /*.module_name */ modname,
-};
-
-/*
- * Load mod_mono module and initialise domain
- *
- * This function will initialise the memory pool and plugin hash for this module,
- * it will then initialise a new mono domain.
- */
-SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load)
-{
- *module_interface = mono_module_interface;
-
- /* Initialise memory pool */
- if (switch_core_new_memory_pool(&mono_pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate memory pool\n");
- return SWITCH_STATUS_FALSE;
- }
-
- /* Initialise plugin hash */
- if (switch_core_hash_init(&globals.plugins, mono_pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not initialise plugins hash\n");
- return SWITCH_STATUS_FALSE;
- }
-
- /* Construct the path to the FreeSwitch assembly, then check to make sure it exists */
- switch_size_t assembly_dir_len = strlen(SWITCH_GLOBAL_dirs.base_dir) + strlen(SWITCH_MONO_LIBDIR) + 2; /* Account for / and \0 */
- switch_size_t assembly_file_len = assembly_dir_len + strlen(SWITCH_MONO_ASSEMBLY);
- char *assembly_dir = (char *) switch_core_alloc(mono_pool, assembly_dir_len);
- char *assembly_file = (char *) switch_core_alloc(mono_pool, assembly_file_len);
-
- snprintf(assembly_dir, assembly_dir_len, "%s%s%s", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR, SWITCH_MONO_LIBDIR);
- snprintf(assembly_file, assembly_file_len, "%s%s%s%s", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR, SWITCH_MONO_LIBDIR, SWITCH_MONO_ASSEMBLY);
-
- if (switch_file_exists(assembly_file, mono_pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Could not find FreeSwitch.NET assembly\n");
- return SWITCH_STATUS_FALSE;
- }
-
- /* Mono wants to know where it will be able to find the FreeSwitch assembly if it's not in the GAC */
- if (getenv("MONO_PATH") != NULL) {
- switch_size_t mono_path_len = strlen(getenv("MONO_PATH")) + strlen(assembly_dir) + 2; /* Account for : and \0 */
- char *mono_path = (char *) switch_core_alloc(mono_pool, mono_path_len);
-
- snprintf(mono_path, mono_path_len, "%s:%s", getenv("MONO_PATH"), assembly_dir);
-
- setenv("MONO_PATH", mono_path, 1);
- } else
- setenv("MONO_PATH", assembly_dir, 1);
-
- /* Now find where our managed modules are */
- switch_size_t module_dir_len = strlen(SWITCH_GLOBAL_dirs.mod_dir) + strlen(SWITCH_MONO_MODULES) + 2; /* Account for / and \0 */
- char *module_dir = (char *) switch_core_alloc(mono_pool, module_dir_len);
-
- snprintf(module_dir, module_dir_len, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, SWITCH_MONO_MODULES);
-
- /* Initialise the mono domain */
- if (!(globals.domain = mono_jit_init("freeswitch"))) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initialising mono runtime\n");
- return SWITCH_STATUS_FALSE;
- }
-
- /* Let user know everything initialised fine */
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initialised mono runtime\n");
-
- /* Load our modules */
- if (mod_mono_load_modules(module_dir) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error loading modules\n");
- return SWITCH_STATUS_FALSE;
- }
-
- /* Finally, go through and initialise each plugin before returning SUCCESS */
- switch_hash_index_t *p = NULL;
-
- for (p = switch_hash_first(NULL, globals.plugins); p; p = switch_hash_next(p)) {
- mono_plugin *plugin = (mono_plugin *) switch_core_alloc(mono_pool, sizeof(*plugin));
- switch_ssize_t *key_length = NULL;
- const void *key = NULL;
- void *value = NULL;
-
- switch_hash_this(p, &key, key_length, &value);
- plugin = (mono_plugin *) value;
-
- mono_runtime_object_init(plugin->object);
- }
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*
- * Function for cleanly shutting down mod_mono
- *
- */
-SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown)
-{
- if (globals.domain) {
- mono_jit_cleanup(globals.domain);
- globals.domain = NULL;
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deallocated mono runtime.\n");
- }
- switch_core_hash_destroy(&globals.plugins);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*
- * This function will load the managed modules
- *
- */
-switch_status_t mod_mono_load_modules(const char *module_dir)
-{
- if (switch_file_exists(module_dir, mono_pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not access module dir!.\n");
- return SWITCH_STATUS_FALSE;
- }
-
- switch_dir_t *module_dir_handle;
- char *file;
- size_t len;
- const char *ext = ".dll";
- const char *EXT = ".DLL";
- MonoAssembly *assembly;
- MonoImage *image;
- gpointer iter;
- iter = NULL;
- mono_plugin *plugin = NULL;
- const char *fname = NULL;
- char buf[512] = "";
-
- if (switch_dir_open(&module_dir_handle, module_dir, mono_pool) != SWITCH_STATUS_SUCCESS)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Could not open directory: %s\n", module_dir);
-
- /* Read the modules directory */
- while ((fname = switch_dir_next_file(module_dir_handle, buf, sizeof(buf)))) {
- assembly = (MonoAssembly *) switch_core_alloc(mono_pool, sizeof(assembly));
- image = (MonoImage *) switch_core_alloc(mono_pool, sizeof(image));
-
- if (!strstr(fname, ext) && !strstr(fname, EXT))
- continue;
-
- len = strlen(module_dir) + strlen(fname) + 2;
- file = (char *) switch_core_alloc(mono_pool, len);
- snprintf(file, len, "%s%s", module_dir, fname);
-
- /* Attempt to open the assembly */
- assembly = mono_domain_assembly_open(globals.domain, file);
-
- if (!assembly) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Not a valid assembly\n");
- continue;
- }
-
- /* Get the image from assembly */
- image = mono_assembly_get_image(assembly);
-
- plugin = (mono_plugin *) switch_core_alloc(mono_pool, sizeof(*plugin));
-
- plugin->assembly = assembly;
- plugin->class = mod_mono_find_assembly_class(mono_assembly_get_image(plugin->assembly));
-
- if (!plugin->class)
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No plugin class\n");
-
- plugin->object = mono_object_new(globals.domain, plugin->class);
-
- switch_core_hash_insert(globals.plugins, (char *) mono_image_get_name(mono_assembly_get_image(assembly)), plugin);
-
- plugin = NULL;
- }
- return SWITCH_STATUS_SUCCESS;
-}
-
-/*
- *
- */
-MonoClass *mod_mono_find_assembly_class(MonoImage * image)
-{
- MonoClass *class, *parent_class = NULL;
- int i, total;
-
- total = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
-
- for (i = 1; i <= total; ++i) {
- class = mono_class_get(image, MONO_TOKEN_TYPE_DEF | i);
- parent_class = mono_class_get_parent(class);
-
- if (parent_class)
- if (!strcmp("Module", mono_class_get_name(parent_class)))
- return class;
- }
-
- return NULL;
-}
-
-/*
- *
- */
-void mono_switch_console_printf(switch_text_channel_t channel, char *file, const char *func, int line, char *fmt, char *msg)
-{
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, msg);
-}
-
-/* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:nil
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
- */