diff --git a/Freeswitch.2012.sln b/Freeswitch.2012.sln index fb5771a136..7223a3dc9d 100644 --- a/Freeswitch.2012.sln +++ b/Freeswitch.2012.sln @@ -604,6 +604,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_opus", "src\mod\codecs\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_t43_gray_code_tables", "libs\spandsp\src\msvc\make_t43_gray_code_tables.2012.vcxproj", "{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "winFailToBan", "src\mod\languages\mod_managed\managed\examples\winFailToBan\winFailToBan.csproj", "{5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 @@ -4056,6 +4058,18 @@ Global {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64.Build.0 = All|Win32 {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64 Setup.ActiveCfg = All|Win32 {EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x86 Setup.ActiveCfg = All|Win32 + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.All|Win32.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.All|x64.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.All|x64 Setup.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.All|x86 Setup.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Debug|Win32.ActiveCfg = Debug|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Debug|x64 Setup.ActiveCfg = Debug|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Debug|x86 Setup.ActiveCfg = Debug|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Release|Win32.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Release|x64.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Release|x64 Setup.ActiveCfg = Release|Any CPU + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}.Release|x86 Setup.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -4188,6 +4202,7 @@ Global {7B077E7F-1BE7-4291-AB86-55E527B25CAC} = {0C808854-54D1-4230-BFF5-77B5FD905000} {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E} = {0C808854-54D1-4230-BFF5-77B5FD905000} {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0} = {0C808854-54D1-4230-BFF5-77B5FD905000} + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0} = {0C808854-54D1-4230-BFF5-77B5FD905000} {692F6330-4D87-4C82-81DF-40DB5892636E} = {4CF6A6AC-07DE-4B9E-ABE1-7F98B64E0BB0} {2286DA73-9FC5-45BC-A508-85994C3317AB} = {4CF6A6AC-07DE-4B9E-ABE1-7F98B64E0BB0} {66444AEE-554C-11DD-A9F0-8C5D56D89593} = {4CF6A6AC-07DE-4B9E-ABE1-7F98B64E0BB0} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/BanTracker.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/BanTracker.cs new file mode 100644 index 0000000000..dd5c950e0d --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/BanTracker.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FreeSWITCH; +using FreeSWITCH.Native; + +namespace winFailToBan +{ + public static class BanTracker + { + public static int MaxFails = 3; + public static int FailMinutes = 1; + public static int BanMinutes = 1; + public static String BanApi = @"system netsh adv fire add rule name={0} dir=in action=block remoteip={1}"; + public static String UnBanApi = @"system netsh adv fire delete rule name={0}"; + + // Tracker object + public static Dictionary> MainTracker = + new Dictionary>(); + + // Active Ban list Key=IP val=baninfo + public static Dictionary ActiveBans = + new Dictionary(); + + + public static void Startup() + { + LoadSettings(); + } + + private static void LoadSettings() + { + using (var a = new Api(null)) + { + var setting = a.ExecuteString("global_getvar ban_maxfails"); + if (!String.IsNullOrEmpty(setting)) + MaxFails = int.Parse(setting); + + setting = a.ExecuteString("global_getvar ban_failminutes"); + if (!String.IsNullOrEmpty(setting)) + FailMinutes = int.Parse(setting); + + setting = a.ExecuteString("global_getvar ban_banminutes"); + if (!String.IsNullOrEmpty(setting)) + BanMinutes = int.Parse(setting); + } + } + + private static void CleanOld(List l) + { + var expiretime = DateTime.Now.Subtract(new TimeSpan(0, FailMinutes, 0)); + var expired = l.Where(x => x < expiretime).ToList(); + expired.ForEach(x => l.Remove(x)); + } + + public static void CleanUp() + { + var templist = new List(); + foreach (var kvp in MainTracker) + { + CleanOld(kvp.Value); + if (kvp.Value.Count == 0) + templist.Add(kvp.Key); + } + + templist.ForEach(i => + { + MainTracker.Remove(i); + Log.WriteLine(LogLevel.Critical, "FTB: Removed tracker entry for {0}", i); + }); // remove all the dictinoary entries that are old + + templist.Clear(); + + // now unban the expired bans + templist.AddRange(from kvp in ActiveBans where kvp.Value.Expires < DateTime.Now select kvp.Key); + templist.ForEach(Unban); + } + + public static void TrackFailure(String ipAddress) + { + LoadSettings(); // just in case they've changed... + if (ActiveBans.ContainsKey(ipAddress)) + return; // don't process again, some delay may happen between the ban, and it taking effect by external system + + if (!MainTracker.ContainsKey(ipAddress)) + MainTracker.Add(ipAddress, new List()); + var l = MainTracker[ipAddress]; + CleanOld(l); // clean out the old ones + l.Add(DateTime.Now); // add the failure to the list + Log.WriteLine(LogLevel.Critical, "Fail to ban logging attempt from {0} count is {1}", ipAddress, l.Count); + if (l.Count > MaxFails) + { + // do the ban here + l.Clear(); + MainTracker.Remove(ipAddress); + Ban(ipAddress); + } + } + + public static void Ban(String ipAddress) + { + Log.WriteLine(LogLevel.Critical, "FTP Banning IP Address {0}", ipAddress); + if (ActiveBans.ContainsKey(ipAddress)) + return; // it's already banned so f-it + + var bi = new BanInfo(); + ActiveBans.Add(ipAddress, bi); + // Execute the ban API callback here + var acmd = String.Format(BanApi, bi.FirewallRuleName, ipAddress); + Log.WriteLine(LogLevel.Critical, "FTB: api command: {0}", acmd); + using (var a = new Api(null)) + a.ExecuteString(acmd); + } + + public static void Unban(String ipAddress) + { + Log.WriteLine(LogLevel.Critical, "FTB: Unbanning ip address {0}", ipAddress); + if (!ActiveBans.ContainsKey(ipAddress)) + return; // nothing to do, it's not banned + + var bi = ActiveBans[ipAddress]; // get the ban info + // Execute the unban API + var acmd = String.Format(UnBanApi, bi.FirewallRuleName); + Log.WriteLine(LogLevel.Critical, "FTB: api command: {0}", acmd); + using (var a = new Api(null)) + a.ExecuteString(acmd); + + ActiveBans.Remove(ipAddress); + } + } + + public class BanInfo + { + public String FirewallRuleName { get; set; } + public DateTime Expires { get; set; } + + public BanInfo() + { + FirewallRuleName = "ftb-" + Guid.NewGuid().ToString("N"); + Expires = DateTime.Now.AddMinutes(BanTracker.BanMinutes); + } + } +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/EventLoop.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/EventLoop.cs new file mode 100644 index 0000000000..7f96f4a534 --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/EventLoop.cs @@ -0,0 +1,87 @@ +using System; +using System.Threading; +using FreeSWITCH.Native; +using winFailToBan.Internal; +using FreeSWITCH; + +namespace winFailToBan +{ + public static class EventLoop + { + public static Boolean Running = true; + private static Thread _eventThread; + + public static void StartEvents() + { + if (_eventThread != null) + return; + _eventThread = new Thread(EventMainLoop); + Running = true; + _eventThread.Start(); + } + + public static void StopEvents() + { + Running = false; + } + + public static void EventMainLoop() + { + EventConsumer ec = null; + try + { + + ec = new EventConsumer("CUSTOM", "sofia::register_attempt", 100); + ec.bind("SHUTDOWN", String.Empty); + ec.bind("HEARTBEAT", String.Empty); + while (Running) + { + var evt = ec.pop(0, 0); + if (evt == null) + continue; + + var en = evt.InternalEvent.GetValueOfHeader("Event-Name"); + if (en == "CUSTOM") + en = evt.InternalEvent.GetValueOfHeader("Event-SubClass"); + switch (en) + { + case @"sofia::register_attempt": + { + var iev = evt.InternalEvent; + var ar = iev.GetValueOfHeader("auth-result"); // get the value of the result to see if it's the case we want + var ip = iev.GetValueOfHeader("network-ip"); // and the ip address the register came from + + if (ar == "FORBIDDEN") + { + BanTracker.TrackFailure(ip); + } + } + break; + + case "SHUTDOWN": + Log.WriteLine(LogLevel.Critical,"FTB: Processing Shutdown event"); + Running = false; + break; + + case "HEARTBEAT": + BanTracker.CleanUp(); + break; + + default: + break; + } + } + } + catch (Exception exx) + { + Log.WriteLine(LogLevel.Critical, "FailToBan -- Exception in event loop {0}", exx.Message); + } + finally + { + if(ec != null) + ec.Dispose(); + _eventThread = null; + } + } + } +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/Fail2Ban.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Fail2Ban.cs new file mode 100644 index 0000000000..789fec152e --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Fail2Ban.cs @@ -0,0 +1,45 @@ +using FreeSWITCH; + +namespace winFailToBan +{ + public class Fail2Ban : IApiPlugin , ILoadNotificationPlugin + { + public void Execute(ApiContext context) + { + var cmds = context.Arguments.Split(" ".ToCharArray()); + var cmd = cmds[0].ToLower(); + switch (cmd) + { + case "shutdown": + Shutdown(); + break; + + default: + context.Stream.Write("\n\nInvalid Command\n\n"); + break; + } + } + + public void ExecuteBackground(ApiBackgroundContext context) + { + return; + } + + public static void Startup() + { + BanTracker.Startup(); + EventLoop.StartEvents(); + } + + public static void Shutdown() + { + EventLoop.StopEvents(); + } + + public bool Load() + { + Startup(); + return true; + } + } +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHandler.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHandler.cs new file mode 100644 index 0000000000..65da2972ea --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHandler.cs @@ -0,0 +1,83 @@ +using System; +using FreeSWITCH; +using FreeSWITCH.Native; + +namespace winFailToBan.Internal +{ + + public class ConfigurationEventArgs : EventArgs + { + public SwitchXmlSearchBinding.XmlBindingArgs FsArgs { get; private set; } + public fsConfigDocument Result { get; set; } + public Boolean DontProcess { get; set; } + + public ConfigurationEventArgs(SwitchXmlSearchBinding.XmlBindingArgs args) + { + DontProcess = false; + FsArgs = args; + Result = null; + } + } + + // Bind XML search function turned into CLR events for ease use + public class ConfigHandler : IDisposable + { + public event EventHandler DirectoryRequest; + public event EventHandler DialPlanRequest; + + private IDisposable _binder; // object to bind to + + public void Dispose() + { + if(_binder != null) + _binder.Dispose(); + _binder = null; + } + + public String XmlCallback(SwitchXmlSearchBinding.XmlBindingArgs args) + { + String rv = null; // return value + switch (args.Section.ToLower()) + { + case "directory": + var dargs = new ConfigurationEventArgs(args); + if (DirectoryRequest != null) + { + var temp = DirectoryRequest; + temp(this, dargs); + if (dargs.DontProcess) + return null; + if (dargs.Result != null) + rv = dargs.Result.ToXMLString(); + } + break; + + case "dialplan": + var dialargs = new ConfigurationEventArgs(args); + if(DialPlanRequest != null) + { + var temp = DialPlanRequest; + temp(this, dialargs); + if (dialargs.Result != null) + rv = dialargs.Result.ToXMLString(); + } + break; + } + + return rv ?? new fsNotFoundDocument().ToXMLString(); + } + + ~ConfigHandler() + { + Dispose(); + } + + public ConfigHandler() + { + _binder = SwitchXmlSearchBinding.Bind(XmlCallback, + switch_xml_section_enum_t.SWITCH_XML_SECTION_DIRECTORY | + switch_xml_section_enum_t.SWITCH_XML_SECTION_DIALPLAN); + + } + } +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHelper.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHelper.cs new file mode 100644 index 0000000000..bc0e039497 --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Internal/ConfigHelper.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using FreeSWITCH.Native; +using Stream = System.IO.Stream; + +namespace winFailToBan.Internal +{ + public abstract class fsConfigDocument + { + public XElement xmldoc; + public XElement main; + + protected fsConfigDocument(String SectionName) + { + main = new XElement("wtf", + new XElement("document", + new XAttribute("type", "freeswitch/xml"), + new XElement("section", + new XAttribute("name", SectionName), + new XAttribute("description", "Auto generated") + ))); + xmldoc = main.Descendants("document").Single(); + } + + public Int64 Length() + { + return xmldoc.ToString().Length + 2; + } + + public String ToXMLString() + { + return xmldoc.ToString(); + } + + public Int64 WriteXML(Stream outStream) + { + var wr = new StreamWriter(outStream); + wr.WriteLine(xmldoc.ToString()); + wr.Flush(); + return xmldoc.ToString().Length + 2; + } + + public void WriteXML(TextWriter outText) + { + outText.Write(xmldoc.ToString()); + } + + + protected void SectionChild(XElement Node) + { + // ReSharper disable PossibleNullReferenceException + if (xmldoc != null) xmldoc.Element("section").Add(Node); + // ReSharper restore PossibleNullReferenceException + } + } + + public class fsNotFoundDocument : fsConfigDocument + { + public fsNotFoundDocument() + : base("result") + { + SectionChild(new XElement("result", + new XAttribute("status", "not found"))); + } + } + + public class fsDomainGatewayDirectoryDocument : fsConfigDocument + { + public fsDomainGatewayDirectoryDocument(Dictionary>> domainGatewayList) + : base("directory") + { + if (xmldoc == null) + return; + foreach (var v in + (from d in domainGatewayList + select new XElement("domain", + new XAttribute("name", d.Key), + new XElement("user", + new XAttribute("id", "gatewaydummyser"), + new XElement("gateways", + from g in d.Value + select new XElement("gateway", + new XAttribute("name", g.Key), + from p in g.Value + select new XElement("param", + new XAttribute( + "name", p.Key), + new XAttribute( + "value", p.Value)))))))) + xmldoc.Element("section").Add(v); + } + } + + public class fsDirectoryDocument : fsConfigDocument + { + public fsDirectoryDocument(String Domain, String User, String Password) + : base("directory") + { + SectionChild(new XElement("domain", + new XAttribute("name", Domain), + new XElement("user", + new XAttribute("id", User), + new XElement("params", + new XElement("param", + new XAttribute("name", "password"), + new XAttribute("value", Password) + ) + ) + ) + )); + } + public fsDirectoryDocument(String Domain, String User, String Password, Dictionary Params) + : this(Domain, User, Password) + { + if (Params == null) + return; + // ReSharper disable PossibleNullReferenceException + xmldoc.Element("section").Element("domain").Element("user").Element("params").Add( + // ReSharper restore PossibleNullReferenceException + from par in Params + select new XElement("param", + new XAttribute("name", par.Key), + new XAttribute("value", par.Value))); + } + + public fsDirectoryDocument(String Domain, String User, String Password, Dictionary Params, Dictionary Variables) + : this(Domain, User, Password, Params) + { + if (Variables == null) + return; + // ReSharper disable PossibleNullReferenceException + xmldoc.Element("section").Element("domain").Element("user").Add( + // ReSharper restore PossibleNullReferenceException + new XElement("variables", from v in Variables + select new XElement("variable", + new XAttribute("name", v.Key), + new XAttribute("value", v.Value)))); + } + } + + public class fsDialPlanDocument : fsConfigDocument + { + + private static XElement MakeActionNode(String ActionString) + { + var p = ActionString.Split(",".ToCharArray(), 2); + var rv = new XElement("action", + new XAttribute("application", p[0])); + if (p.Length > 1) + rv.Add(new XAttribute("data", p[1])); + return rv; + } + + public fsDialPlanDocument(String Context, IEnumerable Actions) + : base("dialplan") + { + SectionChild(new XElement("context", + new XAttribute("name", Context), + new XElement("extension", + new XAttribute("name", "extension"), + new XElement("condition", + from act in Actions + select MakeActionNode(act))))); + } + } + + public static class ConfigExtensions + { + public static switch_event_header GetHeader(this switch_event e, String HeaderName) + { + for (var x = e.headers; x != null; x = x.next) + { + if (HeaderName.ToLower() == x.name.ToLower()) + return x; + } + return null; + } + + public static String GetValueOfHeader(this switch_event e, String headerName, String defaultValue = "") + { + var head = e.GetHeader(headerName); + return (head == null ? defaultValue : head.value); + } + + public static Boolean GetBooleanHeader(this switch_event e, String headerName) + { + var hv = e.GetValueOfHeader(headerName); + hv = (String.IsNullOrEmpty(hv) ? "false" : hv); + Boolean rv = false; + Boolean.TryParse(hv, out rv); + return rv; + } + + public static Guid GetUUID(this Event e) + { + var idfld = e.GetHeader("Unique-ID"); + return String.IsNullOrEmpty(idfld) ? Guid.Empty : new Guid(idfld); + } + + public static void ForEach(this switch_event e, Action action) + { + for (var x = e.headers; x != null; x = x.next) + { + action(x.name, x.value); + } + } + + public static Guid GetGuid(this switch_event e) + { + return e.GetHeader("Unique-ID") == null ? Guid.Empty : Guid.Parse(e.GetHeader("Unique-ID").value); + } + + public static void Dump(this switch_event e) + { + e.ForEach((n, v) => Console.WriteLine("{0}={1}", n, v)); + } + + public static Dictionary ExtractVars(this switch_event e) + { + var r = new Dictionary(); + for (var x = e.headers; x != null; x = x.next) + { + if (x.name.StartsWith("variable_")) + { + r.Add(x.name.ToLower().Replace("variable_", String.Empty), + x.value); + } + } + return r; + } + + public static String ModDigits(this String Orig, int qdel, String Prefix) + { + var rv = Orig; + rv = qdel > Orig.Length ? String.Empty : rv.Substring(qdel); + if (!String.IsNullOrEmpty(Prefix)) + rv = Prefix + rv; + return rv; + } + + //public static String RoutingReplace(this String Orig, String Orignal, String Modified) + //{ + // var rv = Orig; + // rv = rv.Replace("%d", Modified); + // rv = rv.Replace("%o", Orignal); + // return rv; + //} + + public static void MergeFrom( + this Dictionary dict, + Dictionary src + ) + { + foreach (var entry in src) + { + if (!dict.ContainsKey(entry.Key)) + dict.Add(entry.Key, entry.Value); + } + } + + public static void RemoveKeysIn( + this Dictionary dict, + IEnumerable keys + ) + { + foreach (var k in keys) + if (dict.ContainsKey(k)) + dict.Remove(k); + } + + public static void AddVariableTextList(this Dictionary d, String varslist) + { + if (d == null || String.IsNullOrEmpty(varslist)) + return; + foreach (var vardef in varslist.Split(",".ToCharArray())) + { + var args = vardef.Split("=".ToCharArray(), 2); + if (!d.ContainsKey(args[0])) + { + d.Add(args[0], args[1]); + } + else + { + d[args[0]] = args[1]; + } + } + } + + public static String ToParamString(this Dictionary d) + { + var firstPart = new List(); + foreach (var e in d) + { + firstPart.Add(String.Format("{0}={1}", e.Key, e.Value)); + } + var rv = String.Join(",", firstPart.ToArray()); + return rv; + } + + public static String ToChannelVars(this Dictionary d, Boolean bLocal) + { + if (d == null || d.Count == 0) + return String.Empty; + String fmt; + if (bLocal) + fmt = "[{0}]"; + else + fmt = "{{{0}}}"; + return String.Format(fmt, d.ToParamString()); + } + + public static void AddActions(this List l, params String[] strings) + { + String seperator = "^"; + foreach (var s in strings) + { + if (String.IsNullOrEmpty(s)) + continue; + l.AddRange(s.Split(seperator.ToCharArray())); + } + } + } + +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/Properties/AssemblyInfo.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..6036cbd3aa --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 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("winFailToBan")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("winFailToBan")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a171cab9-d773-4070-9993-26a581c6f243")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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")] diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/packages.config b/src/mod/languages/mod_managed/managed/examples/winFailToBan/packages.config new file mode 100644 index 0000000000..8412e6360d --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/skel.cs b/src/mod/languages/mod_managed/managed/examples/winFailToBan/skel.cs new file mode 100644 index 0000000000..ca622b75cf --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/skel.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FreeSWITCH; +using winFailToBan.Internal; + +namespace winFailToBan +{ + public class SampleApp : IAppPlugin + { + // example class for a dialplan APP just implment the run method + public void Run(AppContext context) + { + var s = context.Session; + var args = context.Arguments; + // Do something with them here + } + } + + // Example class to implment an API command + public class SampleApi : IApiPlugin + { + public void Execute(ApiContext context) + { + throw new NotImplementedException(); + } + + public void ExecuteBackground(ApiBackgroundContext context) + { + throw new NotImplementedException(); + } + } + + // This examle class can be used to handle XML config lookups for dialplan and directory + + public class SampleConfigHandler : ILoadNotificationPlugin + { + private static ConfigHandler MyConfigHandler; + + static void HandleDirectoryLookups(Object sender, ConfigurationEventArgs e) + { + e.Result = null; // not found example just return after this + // return; // uncomment to just return not-fouond + + // return a directory object that will work + var evt = e.FsArgs.Parameters; // Get the raw event that generated the userDir lookup + var eventName = evt.GetHeader("Event-Name").value; // Find the event name + + // If your module handles voicemail authorization then implment the following + // to update the voicemail password, when they change their voicemail password using TUI + if (eventName == "CUSTOM") + { + var subClass = evt.GetValueOfHeader("Event-Subclass"); + if (subClass == "vm::maintenance") + { + var vmaction = evt.GetValueOfHeader("VM-Actoun"); + var username = evt.GetValueOfHeader("VM-User"); + var newPassword = evt.GetValueOfHeader("VM-User-Password"); + if (vmaction == "change-password" && !string.IsNullOrEmpty(username) && + !String.IsNullOrEmpty(newPassword)) + { + // implment your code to update the users vm password in your database + return; // No more processing we don't actually do an auth just a notification + } + } + } + + // to make sure we don't have some future events messing us up... + if (eventName != "REQUEST_PARAMS" && eventName != "GENERAL") + return; + + // implment the following if you want to handle gateway lookup from directory when a profile loads + if (evt.GetValueOfHeader("purpose") == "gateways") + { + var profileName = evt.GetValueOfHeader("profile"); + // implment your gateway lookup + //e.Result = new fsDomainGatewayDirectoryDocument(myGwStructure); + return; + } + + var action = evt.GetValueOfHeader("action", "none"); // get the action + + // If you want to handle ESL Logins implment the following + if (action == "event_socket_auth") + { + // preform your stuff here + // e.result = ... + return; + } + + // Normal lookup processing + if (evt.GetHeader("user") == null || evt.GetHeader("domain") == null) + return; // does't have required fields + var method = evt.GetValueOfHeader("sip_auth_method", "unknown"); + var user = evt.GetValueOfHeader("user"); + var domain = evt.GetValueOfHeader("domain"); + + // Some variables to return the params and variables section of the user record + var variables = new Dictionary(); + var uparams = new Dictionary(); + + + // if you're implmenting reverse-auth of devices + if (action == "reverse-auth-lookup") + { + // lookup stuff in your db + uparams.Add("reverse-auth-user", "device uername"); + uparams.Add("reverse-auth-pass", "device password"); + } + + // if you handle voicemail passwords ... + if (true /*check for voicemail box */) + { + uparams.Add("vm-password", "theirvmpassword"); + // the following is optional + uparams.Add("MWI-Account", "registrationstring"); + } + // add more parameters here + uparams.Add("anyotherparameters", "value"); + + // add variables here for example + variables.Add("user_context", "theuserscontext"); + + e.Result = new fsDirectoryDocument( + domain, + user, + "theirpassword", + uparams, + variables); + + return; + } + + // Example dialplan handler + static void HandleDialPlanRequest(object sender, ConfigurationEventArgs e) + { + var evt = e.FsArgs.Parameters; // get the native event that caused this dialplan lookup + + // extract the minimum variables you will need + var context = evt.GetValueOfHeader("Hunt-Context"); // the context + var destination = evt.GetValueOfHeader("Hunt-Destination-Number"); // the dialed number or "DID" + var ani = evt.GetValueOfHeader("Hunt-ANI"); // The ANI/CallerID number + + // A place to return the dialplan actions you want + var actions = new List(); // format is "app,data" + + // add the actions for your code they shouldn't be static this is just an example + actions.Add("set,continue_on_fail=true"); + actions.Add("brige,sofia/mygateway/" + destination); + actions.Add("transfer,fialedDest XML failedcontext"); + e.Result = new fsDialPlanDocument(context, actions); + return; // Isn't this easy? + } + + public bool Load() + { + // Start any threads doing event consumer loops + MyConfigHandler = new ConfigHandler(); // init a config handler + MyConfigHandler.DirectoryRequest += HandleDirectoryLookups; + MyConfigHandler.DialPlanRequest += HandleDialPlanRequest; + return true; + } + } + +} diff --git a/src/mod/languages/mod_managed/managed/examples/winFailToBan/winFailToBan.csproj b/src/mod/languages/mod_managed/managed/examples/winFailToBan/winFailToBan.csproj new file mode 100644 index 0000000000..664b2212eb --- /dev/null +++ b/src/mod/languages/mod_managed/managed/examples/winFailToBan/winFailToBan.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0} + Library + Properties + winFailToBan + winFailToBan + v4.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + {834e2b2f-5483-4b80-8fe3-fe48ff76e5c0} + FreeSWITCH.Managed.2012 + + + + + \ No newline at end of file