Merge pull request #93 in FS/freeswitch from ~RAVENOX/freeswitch:mod_managed_improvements to master
* commit '889b678e58bf38eb86df7885b8f054d3d9d92d74': mod_managed: Added GetPtr to Util class for internal pointers extraction (very useful when using native api) mod_managed: Added pure CreateStateHandlerDelegate in ManagedSession for native api usage mod_managed: added console log level mod_managed: support per-module references directory mod_managed: not crash when cannot remove shadow directory (this sometimes happens when restarting from FS console) mod_managed: managedlist command must return value to api stream instead of log
This commit is contained in:
commit
2b4082c236
|
@ -26,6 +26,7 @@
|
|||
* Michael Giagnocavo <mgg@giagnocavo.net>
|
||||
* David Brazier <David.Brazier@360crm.co.uk>
|
||||
* Jeff Lenk <jeff@jefflenk.com>
|
||||
* Artur Kraev <ravenox@gmail.com>
|
||||
*
|
||||
* Loader.cs -- mod_managed loader
|
||||
*
|
||||
|
@ -33,7 +34,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
@ -47,15 +47,14 @@ namespace FreeSWITCH {
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ExecuteBackgroundDelegate(string cmd);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool RunDelegate(string cmd, IntPtr session);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ReloadDelegate(string cmd);
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate bool ListDelegate(string cmd);
|
||||
static readonly ExecuteDelegate _execute = Execute;
|
||||
static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground;
|
||||
static readonly RunDelegate _run = Run;
|
||||
static readonly ReloadDelegate _reload = Reload;
|
||||
static readonly ListDelegate _list = List;
|
||||
static readonly ExecuteDelegate _list = List;
|
||||
|
||||
[DllImport("mod_managed", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground, ReloadDelegate reload, ListDelegate list);
|
||||
static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground, ReloadDelegate reload, ExecuteDelegate list);
|
||||
|
||||
static readonly object loaderLock = new object();
|
||||
|
||||
|
@ -65,13 +64,23 @@ namespace FreeSWITCH {
|
|||
public static bool Load() {
|
||||
managedDir = Path.Combine(Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir, "managed");
|
||||
shadowDir = Path.Combine(managedDir, "shadow");
|
||||
if (Directory.Exists(shadowDir)) {
|
||||
if (Directory.Exists(shadowDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(shadowDir, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteLine(LogLevel.Warning, "Cannot delete shadow directory: {0}", ex);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(shadowDir);
|
||||
}
|
||||
|
||||
Log.WriteLine(LogLevel.Debug, "FreeSWITCH.Managed loader is starting with directory '{0}'.", managedDir);
|
||||
if (!Directory.Exists(managedDir)) {
|
||||
if (!Directory.Exists(managedDir))
|
||||
{
|
||||
Log.WriteLine(LogLevel.Error, "Managed directory not found: {0}", managedDir);
|
||||
return false;
|
||||
}
|
||||
|
@ -220,11 +229,38 @@ namespace FreeSWITCH {
|
|||
setup.ConfigurationFile = fileName + ".config";
|
||||
}
|
||||
setup.ApplicationBase = Native.freeswitch.SWITCH_GLOBAL_dirs.mod_dir;
|
||||
setup.ShadowCopyDirectories = managedDir + ";";
|
||||
setup.LoaderOptimization = LoaderOptimization.MultiDomainHost; // TODO: would MultiDomain work better since FreeSWITCH.Managed isn't gac'd?
|
||||
setup.CachePath = shadowDir;
|
||||
setup.ShadowCopyFiles = "true";
|
||||
setup.PrivateBinPath = "managed";
|
||||
|
||||
// computing private bin path
|
||||
var binPath = setup.PrivateBinPath ?? string.Empty;
|
||||
|
||||
var binPaths = binPath.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => x.Trim())
|
||||
.ToList();
|
||||
|
||||
// adding "managed" (modules) directory
|
||||
if (!binPaths.Contains("managed", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
binPaths.Add("managed");
|
||||
}
|
||||
|
||||
// adding "managed/<modulename>" directory for per-module references support
|
||||
var moduleRefsDir = Path.GetFileName(fileName);
|
||||
moduleRefsDir = Path.GetFileNameWithoutExtension(moduleRefsDir);
|
||||
|
||||
if (moduleRefsDir != null && moduleRefsDir.Trim() != "")
|
||||
{
|
||||
moduleRefsDir = Path.Combine("managed", moduleRefsDir);
|
||||
if (!binPaths.Contains(moduleRefsDir, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
binPaths.Add(moduleRefsDir);
|
||||
}
|
||||
}
|
||||
|
||||
// bringing all together
|
||||
setup.PrivateBinPath = string.Join(";", binPaths);
|
||||
|
||||
// Create domain and load PM inside
|
||||
System.Threading.Interlocked.Increment(ref appDomainCount);
|
||||
|
@ -408,18 +444,33 @@ namespace FreeSWITCH {
|
|||
}
|
||||
}
|
||||
|
||||
public static bool List(string command) {
|
||||
try {
|
||||
public static bool List(string command, IntPtr streamHandle, IntPtr eventHandle)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (streamHandle != IntPtr.Zero)
|
||||
{
|
||||
using (var stream = new Native.Stream(new Native.switch_stream_handle(streamHandle, false)))
|
||||
{
|
||||
stream.Write("Available APIs:\n");
|
||||
|
||||
getApiExecs().Values.ForEach(x => stream.Write(string.Format("{0}: {1}\n", x.Name, String.Join(",", x.Aliases.ToArray()))));
|
||||
|
||||
stream.Write("Available Apps:\n");
|
||||
getAppExecs().Values.ForEach(x => stream.Write(string.Format("{0}: {1}\n", x.Name, String.Join(",", x.Aliases.ToArray()))));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.WriteLine(LogLevel.Info, "Available APIs:");
|
||||
getApiExecs().Values.ForEach(x => {
|
||||
Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray()));
|
||||
});
|
||||
getApiExecs().Values.ForEach(x => Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())));
|
||||
Log.WriteLine(LogLevel.Info, "Available Apps:");
|
||||
getAppExecs().Values.ForEach(x => {
|
||||
Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray()));
|
||||
});
|
||||
getAppExecs().Values.ForEach(x => Log.WriteLine(LogLevel.Info, "{0}: {1}", x.Name, String.Join(",", x.Aliases.ToArray())));
|
||||
}
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.WriteLine(LogLevel.Error, "Exception listing managed modules: {0}", ex.ToString());
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace FreeSWITCH
|
|||
static string ToLogString(this LogLevel level)
|
||||
{
|
||||
switch (level) {
|
||||
case LogLevel.Console: return "CONSOLE";
|
||||
case LogLevel.Alert: return "ALERT";
|
||||
case LogLevel.Critical: return "CRIT";
|
||||
case LogLevel.Debug: return "DEBUG";
|
||||
|
@ -85,6 +86,7 @@ namespace FreeSWITCH
|
|||
};*/
|
||||
public enum LogLevel
|
||||
{
|
||||
Console,
|
||||
Debug,
|
||||
Info,
|
||||
Error,
|
||||
|
|
|
@ -149,6 +149,23 @@ namespace FreeSWITCH.Native
|
|||
};
|
||||
return del;
|
||||
}
|
||||
|
||||
/// <summary>Wraps a nice handler into a delegate suitable for reverse P/Invoke. For native api using</summary>
|
||||
public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action<ManagedSession> handler)
|
||||
{
|
||||
// We create a ManagedSession on top of the session so callbacks can use it "nicely"
|
||||
// Then we sort of dispose it.
|
||||
switch_state_handler_t_delegate del = ptr =>
|
||||
{
|
||||
using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false)))
|
||||
{
|
||||
handler(sess);
|
||||
return switch_status_t.SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
};
|
||||
return del;
|
||||
}
|
||||
|
||||
public static SWIGTYPE_p_f_p_switch_core_session__switch_status_t WrapStateHandlerDelegate(switch_state_handler_t_delegate del) {
|
||||
return new SWIGTYPE_p_f_p_switch_core_session__switch_status_t(Marshal.GetFunctionPointerForDelegate(del), false);
|
||||
}
|
||||
|
|
|
@ -46,5 +46,31 @@ namespace FreeSWITCH {
|
|||
if (cons == null) throw new ArgumentException(ty.Name + " constructor not found.");
|
||||
return (T)cons.Invoke(new object[] { cPtr, false });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getting IntPtr from wrapper
|
||||
/// </summary>
|
||||
/// <typeparam name="T">swig generated class</typeparam>
|
||||
/// <param name="obj">instance</param>
|
||||
/// <returns>Original pointer</returns>
|
||||
public static IntPtr GetPtr<T>(T obj)
|
||||
{
|
||||
// internal static HandleRef getCPtr(CoreSession obj)
|
||||
var ty = typeof(T);
|
||||
var bflags = BindingFlags.Static | BindingFlags.NonPublic;
|
||||
var getCPtr = ty.GetMethod("getCPtr", bflags, null, new[] { typeof(T) }, null);
|
||||
|
||||
if (getCPtr != null)
|
||||
{
|
||||
var handleRef = getCPtr.Invoke(null, new object[] { obj });
|
||||
|
||||
if (handleRef is HandleRef)
|
||||
{
|
||||
return ((HandleRef)handleRef).Handle;
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* Michael Giagnocavo <mgg@giagnocavo.net>
|
||||
* David Brazier <David.Brazier@360crm.co.uk>
|
||||
* Jeff Lenk <jlenk@frontiernet.net>
|
||||
* Artur Kraev <ravenox@gmail.com>
|
||||
*
|
||||
* mod_mono.cpp -- FreeSWITCH mod_mono main class
|
||||
*
|
||||
|
@ -73,14 +74,13 @@ 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 (*reloadFunction)(const char* cmd);
|
||||
typedef int (*listFunction)(const char* cmd);
|
||||
static runFunction runDelegate;
|
||||
static executeFunction executeDelegate;
|
||||
static executeBackgroundFunction executeBackgroundDelegate;
|
||||
static reloadFunction reloadDelegate;
|
||||
static listFunction listDelegate;
|
||||
static executeFunction listDelegate;
|
||||
|
||||
SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload, listFunction list)
|
||||
SWITCH_MOD_DECLARE_NONSTD(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground, reloadFunction reload, executeFunction list)
|
||||
{
|
||||
runDelegate = run;
|
||||
executeDelegate = execute;
|
||||
|
@ -451,7 +451,7 @@ SWITCH_STANDARD_API(managedlist_api_function)
|
|||
#ifndef _MANAGED
|
||||
mono_thread_attach(globals.domain);
|
||||
#endif
|
||||
listDelegate(cmd);
|
||||
listDelegate(cmd, stream, stream->param_event);
|
||||
#ifndef _MANAGED
|
||||
mono_thread_detach(mono_thread_current());
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue