mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-06-03 20:01:57 +00:00
FS-3588 --resolve thanks drk
This commit is contained in:
parent
5e0b3fa077
commit
aa7800690d
@ -604,6 +604,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_opus", "src\mod\codecs\
|
|||||||
EndProject
|
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}"
|
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
|
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
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
All|Win32 = All|Win32
|
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.Build.0 = All|Win32
|
||||||
{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64 Setup.ActiveCfg = All|Win32
|
{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x64 Setup.ActiveCfg = All|Win32
|
||||||
{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5}.Release|x86 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -4188,6 +4202,7 @@ Global
|
|||||||
{7B077E7F-1BE7-4291-AB86-55E527B25CAC} = {0C808854-54D1-4230-BFF5-77B5FD905000}
|
{7B077E7F-1BE7-4291-AB86-55E527B25CAC} = {0C808854-54D1-4230-BFF5-77B5FD905000}
|
||||||
{7B42BDA1-72C0-4378-A9B6-5C530F8CD61E} = {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}
|
{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}
|
{692F6330-4D87-4C82-81DF-40DB5892636E} = {4CF6A6AC-07DE-4B9E-ABE1-7F98B64E0BB0}
|
||||||
{2286DA73-9FC5-45BC-A508-85994C3317AB} = {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}
|
{66444AEE-554C-11DD-A9F0-8C5D56D89593} = {4CF6A6AC-07DE-4B9E-ABE1-7F98B64E0BB0}
|
||||||
|
@ -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<String, List<DateTime>> MainTracker =
|
||||||
|
new Dictionary<string, List<DateTime>>();
|
||||||
|
|
||||||
|
// Active Ban list Key=IP val=baninfo
|
||||||
|
public static Dictionary<String, BanInfo> ActiveBans =
|
||||||
|
new Dictionary<string, BanInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
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<DateTime> 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<String>();
|
||||||
|
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<DateTime>());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<ConfigurationEventArgs> DirectoryRequest;
|
||||||
|
public event EventHandler<ConfigurationEventArgs> 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<String, Dictionary<String, Dictionary<String, String>>> 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<String, String> 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<String, String> Params, Dictionary<String, String> 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<String> 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<String, String> 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<String, String> ExtractVars(this switch_event e)
|
||||||
|
{
|
||||||
|
var r = new Dictionary<String, String>();
|
||||||
|
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<TKey, TValue>(
|
||||||
|
this Dictionary<TKey, TValue> dict,
|
||||||
|
Dictionary<TKey, TValue> src
|
||||||
|
)
|
||||||
|
{
|
||||||
|
foreach (var entry in src)
|
||||||
|
{
|
||||||
|
if (!dict.ContainsKey(entry.Key))
|
||||||
|
dict.Add(entry.Key, entry.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveKeysIn<TKey, TValue>(
|
||||||
|
this Dictionary<TKey, TValue> dict,
|
||||||
|
IEnumerable<TKey> keys
|
||||||
|
)
|
||||||
|
{
|
||||||
|
foreach (var k in keys)
|
||||||
|
if (dict.ContainsKey(k))
|
||||||
|
dict.Remove(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddVariableTextList(this Dictionary<String, String> 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<String, String> d)
|
||||||
|
{
|
||||||
|
var firstPart = new List<String>();
|
||||||
|
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<String, String> 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<String> l, params String[] strings)
|
||||||
|
{
|
||||||
|
String seperator = "^";
|
||||||
|
foreach (var s in strings)
|
||||||
|
{
|
||||||
|
if (String.IsNullOrEmpty(s))
|
||||||
|
continue;
|
||||||
|
l.AddRange(s.Split(seperator.ToCharArray()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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")]
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="FreeSWITCHManaged.LibCS" version="1.0.1.10" targetFramework="net40" />
|
||||||
|
</packages>
|
@ -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<String, String>();
|
||||||
|
var uparams = new Dictionary<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
// 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<String>(); // 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{5BA0D5BD-330D-4EE2-B959-CAFEA04E50E0}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>winFailToBan</RootNamespace>
|
||||||
|
<AssemblyName>winFailToBan</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="BanTracker.cs" />
|
||||||
|
<Compile Include="EventLoop.cs" />
|
||||||
|
<Compile Include="Fail2Ban.cs" />
|
||||||
|
<Compile Include="Internal\ConfigHandler.cs" />
|
||||||
|
<Compile Include="Internal\ConfigHelper.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<None Include="skel.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\FreeSWITCH.Managed.2012.csproj">
|
||||||
|
<Project>{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}</Project>
|
||||||
|
<Name>FreeSWITCH.Managed.2012</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user