Welcome to your new home Asterisk .NET. Thanks to dnz2005, x893 for their great effort. Visit https://sourceforge.net/projects/asterisk-dotnet/ for more information.
This commit is contained in:
parent
f27c35ca1a
commit
f6d419aa39
43
Asterisk.2013/Asterisk.2013.sln
Normal file
43
Asterisk.2013/Asterisk.2013.sln
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{80ADC18F-2BFC-4B79-B264-5244E4F2FEED}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
ChangeLog.txt = ChangeLog.txt
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Asterisk.NET", "Asterisk.NET\Asterisk.NET.csproj", "{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Asterisk.NET.WinForm", "Asterisk.NET.WinForm\Asterisk.NET.WinForm.csproj", "{03687626-613A-4E41-8F60-7C7839D6DD5D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(TeamFoundationVersionControl) = preSolution
|
||||
SccNumberOfProjects = 3
|
||||
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
|
||||
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs33
|
||||
SccLocalPath0 = .
|
||||
SccProjectUniqueName1 = Asterisk.NET.WinForm\\Asterisk.NET.WinForm.csproj
|
||||
SccProjectName1 = Asterisk.NET.WinForm
|
||||
SccLocalPath1 = Asterisk.NET.WinForm
|
||||
SccProjectUniqueName2 = Asterisk.NET\\Asterisk.NET.csproj
|
||||
SccProjectName2 = Asterisk.NET
|
||||
SccLocalPath2 = Asterisk.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{03687626-613A-4E41-8F60-7C7839D6DD5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{03687626-613A-4E41-8F60-7C7839D6DD5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{03687626-613A-4E41-8F60-7C7839D6DD5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{03687626-613A-4E41-8F60-7C7839D6DD5D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
10
Asterisk.2013/Asterisk.2013.vssscc
Normal file
10
Asterisk.2013/Asterisk.2013.vssscc
Normal file
|
@ -0,0 +1,10 @@
|
|||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||
}
|
127
Asterisk.2013/Asterisk.NET.WinForm/Asterisk.NET.WinForm.csproj
Normal file
127
Asterisk.2013/Asterisk.NET.WinForm/Asterisk.NET.WinForm.csproj
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{03687626-613A-4E41-8F60-7C7839D6DD5D}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Asterisk.NET.WinForm</RootNamespace>
|
||||
<AssemblyName>Asterisk.NET.WinForm</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</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>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</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>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FormMain.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="FormMain.Designer.cs">
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="FormMain.resx">
|
||||
<SubType>Designer</SubType>
|
||||
<DependentUpon>FormMain.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Asterisk.NET\Asterisk.NET.csproj">
|
||||
<Project>{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}</Project>
|
||||
<Name>Asterisk.NET</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\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>
|
|
@ -0,0 +1,10 @@
|
|||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||
}
|
188
Asterisk.2013/Asterisk.NET.WinForm/FormMain.Designer.cs
generated
Normal file
188
Asterisk.2013/Asterisk.NET.WinForm/FormMain.Designer.cs
generated
Normal file
|
@ -0,0 +1,188 @@
|
|||
namespace Asterisk.NET.WinForm
|
||||
{
|
||||
partial class FormMain
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.lable1 = new System.Windows.Forms.Label();
|
||||
this.tbAddress = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.btnDisconnect = new System.Windows.Forms.Button();
|
||||
this.btnConnect = new System.Windows.Forms.Button();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.tbUser = new System.Windows.Forms.TextBox();
|
||||
this.tbPassword = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.tbPort = new System.Windows.Forms.TextBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// lable1
|
||||
//
|
||||
this.lable1.AutoSize = true;
|
||||
this.lable1.Location = new System.Drawing.Point(6, 24);
|
||||
this.lable1.Name = "lable1";
|
||||
this.lable1.Size = new System.Drawing.Size(29, 13);
|
||||
this.lable1.TabIndex = 0;
|
||||
this.lable1.Text = "Host";
|
||||
//
|
||||
// tbAddress
|
||||
//
|
||||
this.tbAddress.Location = new System.Drawing.Point(94, 19);
|
||||
this.tbAddress.Name = "tbAddress";
|
||||
this.tbAddress.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbAddress.TabIndex = 1;
|
||||
this.tbAddress.Text = "192.168.2.51";
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.btnDisconnect);
|
||||
this.groupBox1.Controls.Add(this.btnConnect);
|
||||
this.groupBox1.Controls.Add(this.label4);
|
||||
this.groupBox1.Controls.Add(this.label3);
|
||||
this.groupBox1.Controls.Add(this.tbUser);
|
||||
this.groupBox1.Controls.Add(this.tbPassword);
|
||||
this.groupBox1.Controls.Add(this.label2);
|
||||
this.groupBox1.Controls.Add(this.tbPort);
|
||||
this.groupBox1.Controls.Add(this.lable1);
|
||||
this.groupBox1.Controls.Add(this.tbAddress);
|
||||
this.groupBox1.Location = new System.Drawing.Point(1, 1);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(200, 150);
|
||||
this.groupBox1.TabIndex = 2;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Parameters connection";
|
||||
//
|
||||
// btnDisconnect
|
||||
//
|
||||
this.btnDisconnect.Enabled = false;
|
||||
this.btnDisconnect.Location = new System.Drawing.Point(94, 123);
|
||||
this.btnDisconnect.Name = "btnDisconnect";
|
||||
this.btnDisconnect.Size = new System.Drawing.Size(100, 23);
|
||||
this.btnDisconnect.TabIndex = 9;
|
||||
this.btnDisconnect.Text = "Disconnect";
|
||||
this.btnDisconnect.UseVisualStyleBackColor = true;
|
||||
this.btnDisconnect.Click += new System.EventHandler(this.btnDisconnect_Click);
|
||||
//
|
||||
// btnConnect
|
||||
//
|
||||
this.btnConnect.Location = new System.Drawing.Point(9, 123);
|
||||
this.btnConnect.Name = "btnConnect";
|
||||
this.btnConnect.Size = new System.Drawing.Size(75, 23);
|
||||
this.btnConnect.TabIndex = 8;
|
||||
this.btnConnect.Text = "Connect";
|
||||
this.btnConnect.UseVisualStyleBackColor = true;
|
||||
this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(6, 102);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(53, 13);
|
||||
this.label4.TabIndex = 6;
|
||||
this.label4.Text = "Password";
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(6, 76);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(29, 13);
|
||||
this.label3.TabIndex = 4;
|
||||
this.label3.Text = "User";
|
||||
//
|
||||
// tbUser
|
||||
//
|
||||
this.tbUser.Location = new System.Drawing.Point(94, 71);
|
||||
this.tbUser.Name = "tbUser";
|
||||
this.tbUser.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbUser.TabIndex = 5;
|
||||
this.tbUser.Text = "admin";
|
||||
//
|
||||
// tbPassword
|
||||
//
|
||||
this.tbPassword.Location = new System.Drawing.Point(94, 97);
|
||||
this.tbPassword.Name = "tbPassword";
|
||||
this.tbPassword.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbPassword.TabIndex = 7;
|
||||
this.tbPassword.Text = "123Test";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(6, 50);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(26, 13);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "Port";
|
||||
//
|
||||
// tbPort
|
||||
//
|
||||
this.tbPort.Location = new System.Drawing.Point(94, 45);
|
||||
this.tbPort.Name = "tbPort";
|
||||
this.tbPort.Size = new System.Drawing.Size(100, 20);
|
||||
this.tbPort.TabIndex = 3;
|
||||
this.tbPort.Text = "5038";
|
||||
//
|
||||
// FormMain
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(203, 155);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "FormMain";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Client for Asterisk";
|
||||
this.TopMost = true;
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Label lable1;
|
||||
private System.Windows.Forms.TextBox tbAddress;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox tbUser;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox tbPort;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TextBox tbPassword;
|
||||
private System.Windows.Forms.Button btnConnect;
|
||||
private System.Windows.Forms.Button btnDisconnect;
|
||||
|
||||
}
|
||||
}
|
||||
|
64
Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs
Normal file
64
Asterisk.2013/Asterisk.NET.WinForm/FormMain.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Asterisk.NET.Manager;
|
||||
using Asterisk.NET.Manager.Event;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Asterisk.NET.WinForm
|
||||
{
|
||||
public partial class FormMain : Form
|
||||
{
|
||||
public FormMain()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private ManagerConnection manager = null;
|
||||
private void btnConnect_Click(object sender, EventArgs e)
|
||||
{
|
||||
string address = this.tbAddress.Text;
|
||||
int port = int.Parse(this.tbPort.Text);
|
||||
string user = this.tbUser.Text;
|
||||
string password = this.tbPassword.Text;
|
||||
|
||||
btnConnect.Enabled = false;
|
||||
manager = new ManagerConnection(address, port, user, password);
|
||||
manager.UnhandledEvent += new ManagerEventHandler(manager_Events);
|
||||
try
|
||||
{
|
||||
// Uncomment next 2 line comments to Disable timeout (debug mode)
|
||||
// manager.DefaultResponseTimeout = 0;
|
||||
// manager.DefaultEventTimeout = 0;
|
||||
manager.Login();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error connect\n" + ex.Message);
|
||||
manager.Logoff();
|
||||
this.Close();
|
||||
}
|
||||
btnDisconnect.Enabled = true;
|
||||
}
|
||||
|
||||
void manager_Events(object sender, ManagerEvent e)
|
||||
{
|
||||
Debug.WriteLine("Event : " + e.GetType().Name);
|
||||
}
|
||||
|
||||
private void btnDisconnect_Click(object sender, EventArgs e)
|
||||
{
|
||||
btnConnect.Enabled = true;
|
||||
if (this.manager != null)
|
||||
{
|
||||
manager.Logoff();
|
||||
this.manager = null;
|
||||
}
|
||||
btnDisconnect.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
120
Asterisk.2013/Asterisk.NET.WinForm/FormMain.resx
Normal file
120
Asterisk.2013/Asterisk.NET.WinForm/FormMain.resx
Normal file
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
20
Asterisk.2013/Asterisk.NET.WinForm/Program.cs
Normal file
20
Asterisk.2013/Asterisk.NET.WinForm/Program.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Asterisk.NET.WinForm
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new FormMain());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
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("Asterisk.NET.WinForm")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("...")]
|
||||
[assembly: AssemblyProduct("Asterisk.NET.WinForm")]
|
||||
[assembly: AssemblyCopyright("Copyright © ... 2008")]
|
||||
[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("21011cfa-cef9-4bcb-8e71-e9ab2a16f81b")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
63
Asterisk.2013/Asterisk.NET.WinForm/Properties/Resources.Designer.cs
generated
Normal file
63
Asterisk.2013/Asterisk.NET.WinForm/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,63 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Asterisk.NET.WinForm.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Asterisk.NET.WinForm.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
Asterisk.2013/Asterisk.NET.WinForm/Properties/Resources.resx
Normal file
117
Asterisk.2013/Asterisk.NET.WinForm/Properties/Resources.resx
Normal file
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
26
Asterisk.2013/Asterisk.NET.WinForm/Properties/Settings.Designer.cs
generated
Normal file
26
Asterisk.2013/Asterisk.NET.WinForm/Properties/Settings.Designer.cs
generated
Normal file
|
@ -0,0 +1,26 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.17929
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Asterisk.NET.WinForm.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
3
Asterisk.2013/Asterisk.NET.WinForm/app.config
Normal file
3
Asterisk.2013/Asterisk.NET.WinForm/app.config
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
|
324
Asterisk.2013/Asterisk.NET/Asterisk.NET.csproj
Normal file
324
Asterisk.2013/Asterisk.NET/Asterisk.NET.csproj
Normal file
|
@ -0,0 +1,324 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{BC6E7DBA-C05A-45FE-A2A3-B1637CE16274}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Asterisk.NET</RootNamespace>
|
||||
<AssemblyName>Asterisk.NET</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;LOGGER</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</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>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Common.cs" />
|
||||
<Compile Include="FastAGI\AGIChannel.cs" />
|
||||
<Compile Include="FastAGI\AGIConnectionHandler.cs" />
|
||||
<Compile Include="FastAGI\Exceptions\AGIException.cs" />
|
||||
<Compile Include="FastAGI\Exceptions\AGIHangupException.cs" />
|
||||
<Compile Include="FastAGI\Exceptions\AGINetworkException.cs" />
|
||||
<Compile Include="FastAGI\AGIReader.cs" />
|
||||
<Compile Include="FastAGI\AGIReply.cs" />
|
||||
<Compile Include="FastAGI\AGIRequest.cs" />
|
||||
<Compile Include="FastAGI\AsteriskFastAGI.cs" />
|
||||
<Compile Include="FastAGI\Command\AGICommand.cs" />
|
||||
<Compile Include="FastAGI\Command\GetFullVariableCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\ReceiveTextCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayDateTimeCommand.cs" />
|
||||
<Compile Include="FastAGI\AGIWriter.cs" />
|
||||
<Compile Include="FastAGI\AGIScript.cs" />
|
||||
<Compile Include="FastAGI\Command\AnswerCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\ChannelStatusCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\ControlStreamFileCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\DatabaseDelCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\DatabaseDelTreeCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\DatabaseGetCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\DatabasePutCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\ExecCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\GetDataCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\GetOptionCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\GetVariableCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\HangupCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\NoopCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\ReceiveCharCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\RecordFileCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayAlphaCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayDigitsCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayNumberCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayPhoneticCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SayTimeCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SendImageCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SendTextCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetAutoHangupCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetCallerIdCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetContextCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetExtensionCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetMusicOffCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetMusicOnCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetPriorityCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\SetVariableCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\StreamFileCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\TDDModeCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\VerboseCommand.cs" />
|
||||
<Compile Include="FastAGI\Command\WaitForDigitCommand.cs" />
|
||||
<Compile Include="FastAGI\Exceptions\InvalidCommandSyntaxException.cs" />
|
||||
<Compile Include="FastAGI\Exceptions\InvalidOrUnknownCommandException.cs" />
|
||||
<Compile Include="FastAGI\MappingStrategy.cs" />
|
||||
<Compile Include="FastAGI\Script\AGINoAction.cs" />
|
||||
<Compile Include="IO\ServerSocket.cs" />
|
||||
<Compile Include="IO\SocketConnection.cs" />
|
||||
<Compile Include="IParseSupport.cs" />
|
||||
<Compile Include="Manager\Action\AbsoluteTimeoutAction.cs" />
|
||||
<Compile Include="Manager\Action\AgentCallbackLoginAction.cs" />
|
||||
<Compile Include="Manager\Action\AgentLogoffAction.cs" />
|
||||
<Compile Include="Manager\Action\AgentsAction.cs" />
|
||||
<Compile Include="Manager\Action\ChallengeAction.cs" />
|
||||
<Compile Include="Manager\Action\ChangeMonitorAction.cs" />
|
||||
<Compile Include="Manager\Action\CommandAction.cs" />
|
||||
<Compile Include="Manager\Action\DBGetAction.cs" />
|
||||
<Compile Include="Manager\Action\DBPutAction.cs" />
|
||||
<Compile Include="Manager\Action\EventsAction.cs" />
|
||||
<Compile Include="Manager\Action\ExtensionStateAction.cs" />
|
||||
<Compile Include="Manager\Action\GetConfigAction.cs" />
|
||||
<Compile Include="Manager\Action\GetVarAction.cs" />
|
||||
<Compile Include="Manager\Action\HangupAction.cs" />
|
||||
<Compile Include="Manager\Action\ManagerActionEvent.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Manager\Action\LoginAction.cs" />
|
||||
<Compile Include="Manager\Action\LogoffAction.cs" />
|
||||
<Compile Include="Manager\Action\MailboxCountAction.cs" />
|
||||
<Compile Include="Manager\Action\MailboxStatusAction.cs" />
|
||||
<Compile Include="Manager\Action\ManagerAction.cs" />
|
||||
<Compile Include="Manager\Action\ManagerActionResponse.cs" />
|
||||
<Compile Include="Manager\Action\MonitorAction.cs" />
|
||||
<Compile Include="Manager\Action\OriginateAction.cs" />
|
||||
<Compile Include="Manager\Action\ParkedCallsAction.cs" />
|
||||
<Compile Include="Manager\Action\PingAction.cs" />
|
||||
<Compile Include="Manager\Action\ProxyAction.cs" />
|
||||
<Compile Include="Manager\Action\QueueAddAction.cs" />
|
||||
<Compile Include="Manager\Action\QueuePauseAction.cs" />
|
||||
<Compile Include="Manager\Action\QueueRemoveAction.cs" />
|
||||
<Compile Include="Manager\Action\QueueStatusAction.cs" />
|
||||
<Compile Include="Manager\Action\RedirectAction.cs" />
|
||||
<Compile Include="Manager\Action\SetCDRUserFieldAction.cs" />
|
||||
<Compile Include="Manager\Action\SetVarAction.cs" />
|
||||
<Compile Include="Manager\Action\SIPPeersAction.cs" />
|
||||
<Compile Include="Manager\Action\SIPShowPeerAction.cs" />
|
||||
<Compile Include="Manager\Action\StatusAction.cs" />
|
||||
<Compile Include="Manager\Action\StopMonitorAction.cs" />
|
||||
<Compile Include="Manager\Action\UpdateConfigAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapDialOffhookAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapDNDOffAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapDNDOnAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapHangupAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapShowChannelsAction.cs" />
|
||||
<Compile Include="Manager\Action\ZapTransferAction.cs" />
|
||||
<Compile Include="Manager\AsteriskVersion.cs" />
|
||||
<Compile Include="Manager\Event\AbstractAgentVariables.cs" />
|
||||
<Compile Include="Manager\Event\ConnectionStateEvent.cs" />
|
||||
<Compile Include="Manager\Event\AGIExecEvent.cs" />
|
||||
<Compile Include="Manager\Event\AsyncAGIEvent.cs" />
|
||||
<Compile Include="Manager\Event\BridgeEvent.cs" />
|
||||
<Compile Include="Manager\Event\ChannelReloadEvent.cs" />
|
||||
<Compile Include="Manager\Event\ChannelUpdateEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeMuteEvent.cs" />
|
||||
<Compile Include="Manager\Event\DTMFEvent.cs" />
|
||||
<Compile Include="Manager\Event\FaxReceivedEvent.cs" />
|
||||
<Compile Include="Manager\Event\JabberEvent.cs" />
|
||||
<Compile Include="Manager\Event\JitterBufStatsEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeEndEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeTalkRequestEvent.cs" />
|
||||
<Compile Include="Manager\Event\MobileStatusEvent.cs" />
|
||||
<Compile Include="Manager\Event\ModuleLoadReportEvent.cs" />
|
||||
<Compile Include="Manager\Event\MonitorStartEvent.cs" />
|
||||
<Compile Include="Manager\Event\MonitorStopEvent.cs" />
|
||||
<Compile Include="Manager\Event\NewAccountCodeEvent.cs" />
|
||||
<Compile Include="Manager\Event\OriginateResponseEvent.cs" />
|
||||
<Compile Include="Manager\Event\PRIEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberPenaltyEvent.cs" />
|
||||
<Compile Include="Manager\Event\RTPReceiverStatEvent.cs" />
|
||||
<Compile Include="Manager\Event\RTCPSentEvent.cs" />
|
||||
<Compile Include="Manager\Event\RTCPReceivedEvent.cs" />
|
||||
<Compile Include="Manager\Event\RTPSenderStatEvent.cs" />
|
||||
<Compile Include="Manager\Event\ShowDialPlanCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\TransferEvent.cs" />
|
||||
<Compile Include="Manager\Event\UnknownEvent.cs" />
|
||||
<Compile Include="Manager\Event\VarSet.cs" />
|
||||
<Compile Include="Manager\Event\QueueCallerAbandonEvent.cs" />
|
||||
<Compile Include="Manager\Event\MasqueradeEvent.cs" />
|
||||
<Compile Include="Manager\Exceptions\AuthenticationFailedException.cs" />
|
||||
<Compile Include="Manager\Response\GetConfigResponse.cs" />
|
||||
<Compile Include="Manager\Response\OriginateResponse.cs" />
|
||||
<Compile Include="Manager\ManagerConnection.cs" />
|
||||
<Compile Include="Manager\Exceptions\EventTimeoutException.cs" />
|
||||
<Compile Include="Manager\Event\AbstractAgentEvent.cs" />
|
||||
<Compile Include="Manager\Event\AbstractParkedCallEvent.cs" />
|
||||
<Compile Include="Manager\Event\AbstractQueueMemberEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentCallbackLoginEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentCallbackLogoffEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentCalledEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentConnectEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentDumpEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentLoginEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentLogoffEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentsCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\AgentsEvent.cs" />
|
||||
<Compile Include="Manager\Event\AlarmClearEvent.cs" />
|
||||
<Compile Include="Manager\Event\AlarmEvent.cs" />
|
||||
<Compile Include="Manager\Event\CdrEvent.cs" />
|
||||
<Compile Include="Manager\Event\AbstractChannelEvent.cs" />
|
||||
<Compile Include="Manager\Event\ConnectEvent.cs" />
|
||||
<Compile Include="Manager\Event\DBGetResponseEvent.cs" />
|
||||
<Compile Include="Manager\Event\DialEvent.cs" />
|
||||
<Compile Include="Manager\Event\DisconnectEvent.cs" />
|
||||
<Compile Include="Manager\Event\DNDStateEvent.cs" />
|
||||
<Compile Include="Manager\Event\ExtensionStatusEvent.cs" />
|
||||
<Compile Include="Manager\Event\HangupEvent.cs" />
|
||||
<Compile Include="Manager\Event\HoldedCallEvent.cs" />
|
||||
<Compile Include="Manager\Event\HoldEvent.cs" />
|
||||
<Compile Include="Manager\Event\JoinEvent.cs" />
|
||||
<Compile Include="Manager\Event\LeaveEvent.cs" />
|
||||
<Compile Include="Manager\Event\LinkEvent.cs" />
|
||||
<Compile Include="Manager\Event\LogChannelEvent.cs" />
|
||||
<Compile Include="Manager\Event\ManagerEvent.cs" />
|
||||
<Compile Include="Manager\Event\AbstractMeetmeEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeJoinEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeLeaveEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeStopTalkingEvent.cs" />
|
||||
<Compile Include="Manager\Event\MeetmeTalkingEvent.cs" />
|
||||
<Compile Include="Manager\Event\MessageWaitingEvent.cs" />
|
||||
<Compile Include="Manager\Event\NewCallerIdEvent.cs" />
|
||||
<Compile Include="Manager\Event\NewChannelEvent.cs" />
|
||||
<Compile Include="Manager\Event\NewExtenEvent.cs" />
|
||||
<Compile Include="Manager\Event\NewStateEvent.cs" />
|
||||
<Compile Include="Manager\Event\ParkedCallEvent.cs" />
|
||||
<Compile Include="Manager\Event\ParkedCallGiveUpEvent.cs" />
|
||||
<Compile Include="Manager\Event\ParkedCallsCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\ParkedCallTimeOutEvent.cs" />
|
||||
<Compile Include="Manager\Event\PeerEntryEvent.cs" />
|
||||
<Compile Include="Manager\Event\PeerlistCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\PeerStatusEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueEntryEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberAddedEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberPausedEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberRemovedEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueMemberStatusEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueParamsEvent.cs" />
|
||||
<Compile Include="Manager\Event\QueueStatusCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\RegistryEvent.cs" />
|
||||
<Compile Include="Manager\Event\ReloadEvent.cs" />
|
||||
<Compile Include="Manager\Event\RenameEvent.cs" />
|
||||
<Compile Include="Manager\Event\ResponseEvent.cs" />
|
||||
<Compile Include="Manager\Event\ShutdownEvent.cs" />
|
||||
<Compile Include="Manager\Event\StatusCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\StatusEvent.cs" />
|
||||
<Compile Include="Manager\Event\UnholdEvent.cs" />
|
||||
<Compile Include="Manager\Event\UnlinkEvent.cs" />
|
||||
<Compile Include="Manager\Event\UnparkedCallEvent.cs" />
|
||||
<Compile Include="Manager\Event\UserEvent.cs" />
|
||||
<Compile Include="Manager\Event\ZapShowChannelsCompleteEvent.cs" />
|
||||
<Compile Include="Manager\Event\ZapShowChannelsEvent.cs" />
|
||||
<Compile Include="Manager\Exceptions\ManagerException.cs" />
|
||||
<Compile Include="Manager\ManagerReader.cs" />
|
||||
<Compile Include="Manager\Originate.cs" />
|
||||
<Compile Include="Manager\ResponseEventHandler.cs" />
|
||||
<Compile Include="Manager\ResponseEvents.cs" />
|
||||
<Compile Include="Manager\ResponseHandler.cs" />
|
||||
<Compile Include="Manager\Response\ChallengeResponse.cs" />
|
||||
<Compile Include="Manager\Response\CommandResponse.cs" />
|
||||
<Compile Include="Manager\Response\ExtensionStateResponse.cs" />
|
||||
<Compile Include="Manager\IResponseHandler.cs" />
|
||||
<Compile Include="Manager\Response\MailboxCountResponse.cs" />
|
||||
<Compile Include="Manager\Response\MailboxStatusResponse.cs" />
|
||||
<Compile Include="Manager\Response\ManagerError.cs" />
|
||||
<Compile Include="Manager\Response\ManagerResponse.cs" />
|
||||
<Compile Include="Manager\Exceptions\TimeoutException.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
<Compile Include="Util\MD5Support.cs" />
|
||||
<Compile Include="Util\ThreadClass.cs" />
|
||||
<Compile Include="Util\ThreadPool.cs" />
|
||||
<Compile Include="Helper.cs" />
|
||||
<Compile Include="Util\ThreadTask.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\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>
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
10
Asterisk.2013/Asterisk.NET/Asterisk.NET.csproj.vspscc
Normal file
10
Asterisk.2013/Asterisk.NET/Asterisk.NET.csproj.vspscc
Normal file
|
@ -0,0 +1,10 @@
|
|||
""
|
||||
{
|
||||
"FILE_VERSION" = "9237"
|
||||
"ENLISTMENT_CHOICE" = "NEVER"
|
||||
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||
}
|
55
Asterisk.2013/Asterisk.NET/Common.cs
Normal file
55
Asterisk.2013/Asterisk.NET/Common.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Asterisk.NET
|
||||
{
|
||||
public static class Common
|
||||
{
|
||||
#region Manager API Constants
|
||||
|
||||
/// <summary> The hostname to use if none is provided.</summary>
|
||||
public const string DEFAULT_HOSTNAME = "localhost";
|
||||
/// <summary> The port to use if none is provided.</summary>
|
||||
public const int DEFAULT_PORT = 5038;
|
||||
/// <summary>Line separator</summary>
|
||||
public const string LINE_SEPARATOR = "\r\n";
|
||||
|
||||
public static Regex ASTERISK_VERSION = new Regex("^Asterisk\\s+([0-9].[0-9]+.[0-9]+).*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
public static Regex SHOW_VERSION_FILES_PATTERN = new Regex("^([\\S]+)\\s+Revision: ([0-9\\.]+)");
|
||||
public static char[] RESPONSE_KEY_VALUE_SEPARATOR = new char[] { ':' };
|
||||
public static char[] MINUS_SEPARATOR = new char[] { '-' };
|
||||
public static char INTERNAL_ACTION_ID_DELIMITER = '#';
|
||||
/// <summary> Variables delimiter </summary>
|
||||
public static char[] VAR_DELIMITER = new char[] { '|' };
|
||||
public static IFormatProvider CultureInfoEn = new CultureInfo("en-US", false);
|
||||
|
||||
#endregion
|
||||
|
||||
#region AGI Constants
|
||||
|
||||
/// <summary> The default AGI bind port. </summary>
|
||||
public const int AGI_BIND_PORT = 4573;
|
||||
/// <summary> The default AGI thread pool size. </summary>
|
||||
public const int AGI_POOL_SIZE = 10;
|
||||
/// <summary> The default AGI bind address. </summary>
|
||||
public const string AGI_BIND_ADDRESS = "0.0.0.0";
|
||||
|
||||
public const string AGI_DEFAULT_RESOURCE_BUNDLE_NAME = "fastagi-mapping.resources";
|
||||
public const string AGI_END_OF_PROPER_USAGE = "520 End of proper usage.";
|
||||
|
||||
public const int AGI_DEFAULT_MAX_DIGITS = 1024;
|
||||
public const int AGI_DEFAULT_TIMEOUT = 0;
|
||||
|
||||
public static Regex AGI_STATUS_PATTERN = new Regex("^(\\d{3})[ -]", RegexOptions.Compiled);
|
||||
public static Regex AGI_RESULT_PATTERN = new Regex("^200 result= *(\\S+)", RegexOptions.Compiled);
|
||||
public static Regex AGI_PARENTHESIS_PATTERN = new Regex("^200 result=\\S* +\\((.*)\\)", RegexOptions.Compiled);
|
||||
public static Regex AGI_ADDITIONAL_ATTRIBUTES_PATTERN = new Regex("^200 result=\\S* +(\\(.*\\) )?(.+)$", RegexOptions.Compiled);
|
||||
public static Regex AGI_ADDITIONAL_ATTRIBUTE_PATTERN = new Regex("(\\S+)=(\\S+)", RegexOptions.Compiled);
|
||||
public static Regex AGI_SYNOPSIS_PATTERN = new Regex("^\\s*Usage:\\s*(.*)\\s*$", RegexOptions.Compiled);
|
||||
public static Regex AGI_SCRIPT_PATTERN = new Regex("^([^\\?]*)\\?(.*)$");
|
||||
public static Regex AGI_PARAMETER_PATTERN = new Regex("^(.*)=(.*)$");
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
44
Asterisk.2013/Asterisk.NET/FastAGI/AGIChannel.cs
Normal file
44
Asterisk.2013/Asterisk.NET/FastAGI/AGIChannel.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of the AGIChannel interface.
|
||||
/// </summary>
|
||||
public class AGIChannel
|
||||
{
|
||||
private AGIWriter agiWriter;
|
||||
private AGIReader agiReader;
|
||||
private AGIReply agiReply;
|
||||
|
||||
public AGIChannel(IO.SocketConnection socket)
|
||||
{
|
||||
this.agiWriter = new AGIWriter(socket);
|
||||
this.agiReader = new AGIReader(socket);
|
||||
}
|
||||
|
||||
public AGIChannel(AGIWriter agiWriter, AGIReader agiReader)
|
||||
{
|
||||
this.agiWriter = agiWriter;
|
||||
this.agiReader = agiReader;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get last AGI Reply.
|
||||
/// </summary>
|
||||
public AGIReply LastReply
|
||||
{
|
||||
get { return agiReply; }
|
||||
}
|
||||
|
||||
public AGIReply SendCommand(Command.AGICommand command)
|
||||
{
|
||||
agiWriter.SendCommand(command);
|
||||
agiReply = agiReader.ReadReply();
|
||||
int status = agiReply.GetStatus();
|
||||
if (status == (int)AGIReplyStatuses.SC_INVALID_OR_UNKNOWN_COMMAND)
|
||||
throw new InvalidOrUnknownCommandException(command.BuildCommand());
|
||||
else if (status == (int)AGIReplyStatuses.SC_INVALID_COMMAND_SYNTAX)
|
||||
throw new InvalidCommandSyntaxException(agiReply.GetSynopsis(), agiReply.GetUsage());
|
||||
return agiReply;
|
||||
}
|
||||
}
|
||||
}
|
118
Asterisk.2013/Asterisk.NET/FastAGI/AGIConnectionHandler.cs
Normal file
118
Asterisk.2013/Asterisk.NET/FastAGI/AGIConnectionHandler.cs
Normal file
|
@ -0,0 +1,118 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// An AGIConnectionHandler is created and run by the AGIServer whenever a new
|
||||
/// socket connection from an Asterisk Server is received.<br/>
|
||||
/// It reads the request using an AGIReader and runs the AGIScript configured to
|
||||
/// handle this type of request. Finally it closes the socket connection.
|
||||
/// </summary>
|
||||
public class AGIConnectionHandler
|
||||
{
|
||||
#if LOGGER
|
||||
private Logger logger = Logger.Instance();
|
||||
#endif
|
||||
private static readonly LocalDataStoreSlot channel = Thread.AllocateDataSlot();
|
||||
private IO.SocketConnection socket;
|
||||
private MappingStrategy mappingStrategy;
|
||||
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Returns the AGIChannel associated with the current thread.
|
||||
/// </summary>
|
||||
/// <returns>the AGIChannel associated with the current thread or <code>null</code> if none is associated.</returns>
|
||||
internal static AGIChannel Channel
|
||||
{
|
||||
get
|
||||
{
|
||||
return (AGIChannel) Thread.GetData(AGIConnectionHandler.channel);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AGIConnectionHandler(socket, mappingStrategy)
|
||||
/// <summary>
|
||||
/// Creates a new AGIConnectionHandler to handle the given socket connection.
|
||||
/// </summary>
|
||||
/// <param name="socket">the socket connection to handle.</param>
|
||||
/// <param name="mappingStrategy">the strategy to use to determine which script to run.</param>
|
||||
public AGIConnectionHandler(IO.SocketConnection socket, MappingStrategy mappingStrategy)
|
||||
{
|
||||
this.socket = socket;
|
||||
this.mappingStrategy = mappingStrategy;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
AGIReader reader = new AGIReader(socket);
|
||||
AGIWriter writer = new AGIWriter(socket);
|
||||
AGIRequest request = reader.ReadRequest();
|
||||
AGIChannel channel = new AGIChannel(writer, reader);
|
||||
AGIScript script = mappingStrategy.DetermineScript(request);
|
||||
Thread.SetData(AGIConnectionHandler.channel, channel);
|
||||
|
||||
if (script != null)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Info("Begin AGIScript " + script.GetType().FullName + " on " + Thread.CurrentThread.Name);
|
||||
#endif
|
||||
script.Service(request, channel);
|
||||
#if LOGGER
|
||||
logger.Info("End AGIScript " + script.GetType().FullName + " on " + Thread.CurrentThread.Name);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
string error;
|
||||
error = "No script configured for URL '" + request.RequestURL + "' (script '" + request.Script + "')";
|
||||
channel.SendCommand(new Command.VerboseCommand(error, 1));
|
||||
#if LOGGER
|
||||
logger.Error(error);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (AGIHangupException)
|
||||
{
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
catch (AGIException ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("AGIException while handling request", ex);
|
||||
#else
|
||||
throw ex;
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unexpected Exception while handling request", ex);
|
||||
#else
|
||||
throw ex;
|
||||
#endif
|
||||
}
|
||||
|
||||
Thread.SetData(AGIConnectionHandler.channel, null);
|
||||
try
|
||||
{
|
||||
socket.Close();
|
||||
}
|
||||
#if LOGGER
|
||||
catch(IOException ex)
|
||||
{
|
||||
logger.Error("Error on close socket", ex);
|
||||
}
|
||||
#else
|
||||
catch { }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
89
Asterisk.2013/Asterisk.NET/FastAGI/AGIReader.cs
Normal file
89
Asterisk.2013/Asterisk.NET/FastAGI/AGIReader.cs
Normal file
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
public class AGIReader
|
||||
{
|
||||
#if LOGGER
|
||||
private Logger logger = Logger.Instance();
|
||||
#endif
|
||||
private IO.SocketConnection socket;
|
||||
public AGIReader(IO.SocketConnection socket)
|
||||
{
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public AGIRequest ReadRequest()
|
||||
{
|
||||
string line;
|
||||
List<string> lines = new List<string>();
|
||||
try
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Info("AGIReader.ReadRequest():");
|
||||
#endif
|
||||
while ((line = socket.ReadLine()) != null)
|
||||
{
|
||||
if (line.Length == 0)
|
||||
break;
|
||||
lines.Add(line);
|
||||
#if LOGGER
|
||||
logger.Info(line);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new AGINetworkException("Unable to read request from Asterisk: " + ex.Message, ex);
|
||||
}
|
||||
|
||||
AGIRequest request = new AGIRequest(lines);
|
||||
|
||||
request.LocalAddress = socket.LocalAddress;
|
||||
request.LocalPort = socket.LocalPort;
|
||||
request.RemoteAddress = socket.RemoteAddress;
|
||||
request.RemotePort = socket.RemotePort;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public AGIReply ReadReply()
|
||||
{
|
||||
string line;
|
||||
string badSyntax = ((int)AGIReplyStatuses.SC_INVALID_COMMAND_SYNTAX).ToString();
|
||||
|
||||
List<string> lines = new List<string>();
|
||||
try
|
||||
{
|
||||
line = socket.ReadLine();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new AGINetworkException("Unable to read reply from Asterisk: " + ex.Message, ex);
|
||||
}
|
||||
if (line == null)
|
||||
throw new AGIHangupException();
|
||||
|
||||
lines.Add(line);
|
||||
// read synopsis and usage if statuscode is 520
|
||||
if (line.StartsWith(badSyntax))
|
||||
try
|
||||
{
|
||||
while ((line = socket.ReadLine()) != null)
|
||||
{
|
||||
lines.Add(line);
|
||||
if (line.StartsWith(badSyntax))
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new AGINetworkException("Unable to read reply from Asterisk: " + ex.Message, ex);
|
||||
}
|
||||
return new AGIReply(lines);
|
||||
}
|
||||
}
|
||||
}
|
315
Asterisk.2013/Asterisk.NET/FastAGI/AGIReply.cs
Normal file
315
Asterisk.2013/Asterisk.NET/FastAGI/AGIReply.cs
Normal file
|
@ -0,0 +1,315 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
#region Enum - AGIReplyStatuses
|
||||
public enum AGIReplyStatuses
|
||||
{
|
||||
/// <summary>
|
||||
/// Status code (200) indicating Asterisk successfully processed the AGICommand.
|
||||
/// </summary>
|
||||
SC_SUCCESS = 200,
|
||||
/// <summary>
|
||||
/// Status code (510) indicating Asterisk was unable to process the
|
||||
/// AGICommand because there is no command with the given name available.
|
||||
/// </summary>
|
||||
SC_INVALID_OR_UNKNOWN_COMMAND = 510,
|
||||
/// <summary>
|
||||
/// Status code (520) indicating Asterisk was unable to process the
|
||||
/// AGICommand because the syntax used was not correct. This is most likely
|
||||
/// due to missing required parameters or additional parameters sent that are
|
||||
/// not understood.<br/>
|
||||
/// Ensure proper quoting of the parameters when you receive this status
|
||||
/// code.
|
||||
/// </summary>
|
||||
SC_INVALID_COMMAND_SYNTAX = 520
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Default implementation of the AGIReply interface.
|
||||
/// </summary>
|
||||
public class AGIReply
|
||||
{
|
||||
#region Variables
|
||||
private Match matcher;
|
||||
private List<string> lines;
|
||||
private string firstLine;
|
||||
/// <summary> The result, that is the part directly following the "result=" string.</summary>
|
||||
private string result;
|
||||
/// <summary> The status code.</summary>
|
||||
private int status;
|
||||
/// <summary>Additional attributes contained in this reply, for example endpos.</summary>
|
||||
private Dictionary<string, string> attributes;
|
||||
/// <summary> The contents of the parenthesis.</summary>
|
||||
private string extra;
|
||||
/// <summary> In case of status == 520 (invalid command syntax) this attribute contains the synopsis of the command.</summary>
|
||||
private string synopsis;
|
||||
/// <summary> In case of status == 520 (invalid command syntax) this attribute contains the usage of the command.</summary>
|
||||
private string usage;
|
||||
private bool extraCreated;
|
||||
private bool synopsisCreated;
|
||||
private bool attributesCreated;
|
||||
private bool resultCreated;
|
||||
private bool statusCreated;
|
||||
#endregion
|
||||
|
||||
#region Constructor - AGIReply()
|
||||
public AGIReply()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - AGIReply(lines)
|
||||
public AGIReply(List<string> lines)
|
||||
{
|
||||
this.lines = lines;
|
||||
try
|
||||
{
|
||||
firstLine = lines[0];
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FirstLine
|
||||
public string FirstLine
|
||||
{
|
||||
get { return firstLine; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Lines
|
||||
public IList Lines
|
||||
{
|
||||
get { return lines; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ResultCode
|
||||
/// <summary>
|
||||
/// Returns the return code (the result as int).
|
||||
/// </summary>
|
||||
/// <returns>the return code or -1 if the result is not an int.</returns>
|
||||
public int ResultCode
|
||||
{
|
||||
get
|
||||
{
|
||||
string result;
|
||||
result = GetResult();
|
||||
if (result == null)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
return Int32.Parse(result);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ResultCodeAsChar
|
||||
/// <summary>
|
||||
/// Returns the return code as character.
|
||||
/// </summary>
|
||||
/// <returns>the return code as character.</returns>
|
||||
public char ResultCodeAsChar
|
||||
{
|
||||
get
|
||||
{
|
||||
int resultCode;
|
||||
resultCode = ResultCode;
|
||||
if (resultCode < 0)
|
||||
return (char)(0x0);
|
||||
return (char)resultCode;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extra
|
||||
/// <summary>
|
||||
/// Returns the text in parenthesis contained in this reply.<br/>
|
||||
/// The meaning of this property depends on the command sent. Sometimes it
|
||||
/// contains a flag like "timeout" or "hangup" or - in case of the
|
||||
/// GetVariableCommand - the value of the variable.
|
||||
/// </summary>
|
||||
/// <returns>the text in the parenthesis or <code>null</code> if not set.</returns>
|
||||
public string Extra
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GetStatus() != (int)AGIReplyStatuses.SC_SUCCESS)
|
||||
return null;
|
||||
|
||||
if (extraCreated)
|
||||
return extra;
|
||||
|
||||
matcher = Common.AGI_PARENTHESIS_PATTERN.Match(firstLine);
|
||||
if (matcher.Success)
|
||||
extra = matcher.Groups[1].Value;
|
||||
|
||||
extraCreated = true;
|
||||
return extra;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetResult()
|
||||
/// <summary>
|
||||
/// Returns the result, that is the part directly following the "result=" string.
|
||||
/// </summary>
|
||||
/// <returns>the result.</returns>
|
||||
public string GetResult()
|
||||
{
|
||||
if (resultCreated)
|
||||
return result;
|
||||
|
||||
matcher = Common.AGI_RESULT_PATTERN.Match(firstLine);
|
||||
if (matcher.Success)
|
||||
result = matcher.Groups[1].Value;
|
||||
|
||||
resultCreated = true;
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetStatus()
|
||||
/// <summary>
|
||||
/// Returns the status code.<br/>
|
||||
/// Supported status codes are:<br/>
|
||||
/// 200 Success<br/>
|
||||
/// 510 Invalid or unknown command<br/>
|
||||
/// 520 Invalid command syntax<br/>
|
||||
/// </summary>
|
||||
/// <returns>the status code.</returns>
|
||||
public int GetStatus()
|
||||
{
|
||||
if (statusCreated)
|
||||
return status;
|
||||
matcher = Common.AGI_STATUS_PATTERN.Match(firstLine);
|
||||
if (matcher.Success)
|
||||
status = Int32.Parse(matcher.Groups[1].Value);
|
||||
statusCreated = true;
|
||||
return status;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetAttribute(name)
|
||||
/// <summary>
|
||||
/// Returns an additional attribute contained in the reply.<br/>
|
||||
/// For example the reply to the StreamFileCommand contains an additional
|
||||
/// endpos attribute indicating the frame where the playback was stopped.
|
||||
/// This can be retrieved by calling getAttribute("endpos") on the corresponding reply.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the attribute to retrieve. The name is case insensitive.</param>
|
||||
/// <returns>the value of the attribute or <code>null</code> if it is not set.</returns>
|
||||
public string GetAttribute(string name)
|
||||
{
|
||||
if (GetStatus() != (int)AGIReplyStatuses.SC_SUCCESS)
|
||||
return null;
|
||||
|
||||
if ("result".ToUpper().Equals(name.ToUpper()))
|
||||
return GetResult();
|
||||
|
||||
if (!attributesCreated)
|
||||
{
|
||||
matcher = Common.AGI_ADDITIONAL_ATTRIBUTES_PATTERN.Match(firstLine);
|
||||
if (matcher.Success)
|
||||
{
|
||||
string s;
|
||||
Match attributeMatcher;
|
||||
|
||||
attributes = new Dictionary<string,string>();
|
||||
s = matcher.Groups[2].Value;
|
||||
attributeMatcher = Common.AGI_ADDITIONAL_ATTRIBUTE_PATTERN.Match(s);
|
||||
while (attributeMatcher.Success)
|
||||
{
|
||||
string key;
|
||||
string value_Renamed;
|
||||
|
||||
key = attributeMatcher.Groups[1].Value;
|
||||
value_Renamed = attributeMatcher.Groups[2].Value;
|
||||
attributes[key.ToLower(Helper.CultureInfo)] = value_Renamed;
|
||||
}
|
||||
}
|
||||
attributesCreated = true;
|
||||
}
|
||||
|
||||
if (attributes == null || (attributes.Count == 0))
|
||||
return null;
|
||||
|
||||
return (string)attributes[name.ToLower(Helper.CultureInfo)];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetSynopsis()
|
||||
/// <summary>
|
||||
/// Returns the synopsis of the command sent if Asterisk expected a different
|
||||
/// syntax (getStatus() == SC_INVALID_COMMAND_SYNTAX).
|
||||
/// </summary>
|
||||
/// <returns>the synopsis of the command sent, <code>null</code> if there were no syntax errors.</returns>
|
||||
public string GetSynopsis()
|
||||
{
|
||||
if (GetStatus() != (int)AGIReplyStatuses.SC_INVALID_COMMAND_SYNTAX)
|
||||
return null;
|
||||
|
||||
if (!synopsisCreated)
|
||||
{
|
||||
if (lines.Count > 1)
|
||||
{
|
||||
string secondLine;
|
||||
Match synopsisMatcher;
|
||||
|
||||
secondLine = ((string)lines[1]);
|
||||
synopsisMatcher = Common.AGI_SYNOPSIS_PATTERN.Match(secondLine);
|
||||
if (synopsisMatcher.Success)
|
||||
synopsis = synopsisMatcher.Groups[1].Value;
|
||||
}
|
||||
synopsisCreated = true;
|
||||
|
||||
StringBuilder sbUsage = new StringBuilder();
|
||||
string line;
|
||||
for (int i = 2; i < lines.Count; i++)
|
||||
{
|
||||
line = ((string)lines[i]);
|
||||
if (line == Common.AGI_END_OF_PROPER_USAGE)
|
||||
break;
|
||||
sbUsage.Append(line.Trim());
|
||||
sbUsage.Append(" ");
|
||||
}
|
||||
usage = sbUsage.ToString().Trim();
|
||||
}
|
||||
return synopsis;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetUsage()
|
||||
/// <summary>
|
||||
/// Returns the usage of the command sent if Asterisk expected a different
|
||||
/// syntax (getStatus() == SC_INVALID_COMMAND_SYNTAX).
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// the usage of the command sent,
|
||||
/// <code>null</code> if there were no syntax errors.
|
||||
/// </returns>
|
||||
public string GetUsage()
|
||||
{
|
||||
return usage;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString()
|
||||
public override string ToString()
|
||||
{
|
||||
return Helper.ToString(this);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
534
Asterisk.2013/Asterisk.NET/FastAGI/AGIRequest.cs
Normal file
534
Asterisk.2013/Asterisk.NET/FastAGI/AGIRequest.cs
Normal file
|
@ -0,0 +1,534 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of the AGIRequest interface.
|
||||
/// </summary>
|
||||
public class AGIRequest
|
||||
{
|
||||
#region Variables
|
||||
#if LOGGER
|
||||
private Logger logger = Logger.Instance();
|
||||
#endif
|
||||
private string rawCallerId;
|
||||
private Dictionary<string, string> request;
|
||||
|
||||
/// <summary> A map assigning the values of a parameter (an array of Strings) to the name of the parameter.</summary>
|
||||
private Dictionary<string, List<string>> parameterMap;
|
||||
|
||||
private string parameters;
|
||||
private string script;
|
||||
private bool callerIdCreated;
|
||||
private IPAddress localAddress;
|
||||
private int localPort;
|
||||
private IPAddress remoteAddress;
|
||||
private int remotePort;
|
||||
#endregion
|
||||
|
||||
#region Constructor - AGIRequest(ICollection environment)
|
||||
/// <summary>
|
||||
/// Creates a new AGIRequest.
|
||||
/// </summary>
|
||||
/// <param name="environment">the first lines as received from Asterisk containing the environment.</param>
|
||||
public AGIRequest(List<string> environment)
|
||||
{
|
||||
if (environment == null)
|
||||
throw new ArgumentException("Environment must not be null.");
|
||||
request = buildMap(environment);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Request
|
||||
public IDictionary Request
|
||||
{
|
||||
get { return request; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RequestURL
|
||||
/// <summary>
|
||||
/// Returns the full URL of the request in the form agi://host[:port][/script].
|
||||
/// </summary>
|
||||
public string RequestURL
|
||||
{
|
||||
get { return (string) request["request"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Returns the name of the channel.
|
||||
/// </summary>
|
||||
/// <returns>the name of the channel.</returns>
|
||||
public string Channel
|
||||
{
|
||||
get { return (string) request["channel"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UniqueId
|
||||
/// <summary>
|
||||
/// Returns the unqiue id of the channel.
|
||||
/// </summary>
|
||||
/// <returns>the unqiue id of the channel.</returns>
|
||||
public string UniqueId
|
||||
{
|
||||
get { return (string) request["uniqueid"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Type
|
||||
/// <summary>
|
||||
/// Returns the type of the channel, for example "SIP".
|
||||
/// </summary>
|
||||
/// <returns>the type of the channel, for example "SIP".</returns>
|
||||
public string Type
|
||||
{
|
||||
get { return (string) request["type"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Language
|
||||
/// <summary>
|
||||
/// Returns the language, for example "en".
|
||||
/// </summary>
|
||||
public string Language
|
||||
{
|
||||
get { return (string) request["language"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallerId
|
||||
public string CallerId
|
||||
{
|
||||
get
|
||||
{
|
||||
string callerIdName = (string)(request["calleridname"]);
|
||||
string callerId = (string)(request["callerid"]);
|
||||
if (callerIdName != null)
|
||||
{
|
||||
if (callerId == null || callerId.ToLower(Helper.CultureInfo) == "unknown")
|
||||
return null;
|
||||
return callerId;
|
||||
}
|
||||
else // Asterisk 1.0
|
||||
return callerId10();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallerIdName
|
||||
public string CallerIdName
|
||||
{
|
||||
get
|
||||
{
|
||||
string callerIdName = (string)(request["calleridname"]);
|
||||
if (callerIdName != null)
|
||||
{
|
||||
// Asterisk 1.2
|
||||
if (callerIdName.ToLower(Helper.CultureInfo) == "unknown")
|
||||
return null;
|
||||
return callerIdName;
|
||||
}
|
||||
else // Asterisk 1.0
|
||||
return callerIdName10();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Asterisk 1.0 CallerID and CallerIdName
|
||||
private string callerId10()
|
||||
{
|
||||
int lbPosition;
|
||||
int rbPosition;
|
||||
|
||||
if (!callerIdCreated)
|
||||
{
|
||||
rawCallerId = ((string) request["callerid"]);
|
||||
callerIdCreated = true;
|
||||
}
|
||||
|
||||
if (rawCallerId == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
lbPosition = rawCallerId.IndexOf('<');
|
||||
rbPosition = rawCallerId.IndexOf('>');
|
||||
|
||||
if (lbPosition < 0 || rbPosition < 0)
|
||||
{
|
||||
return rawCallerId;
|
||||
}
|
||||
|
||||
return rawCallerId.Substring(lbPosition + 1, (rbPosition) - (lbPosition + 1));
|
||||
}
|
||||
|
||||
private string callerIdName10()
|
||||
{
|
||||
int lbPosition;
|
||||
string callerIdName;
|
||||
|
||||
if (!callerIdCreated)
|
||||
{
|
||||
rawCallerId = ((string) request["callerid"]);
|
||||
callerIdCreated = true;
|
||||
}
|
||||
|
||||
if (rawCallerId == null)
|
||||
return null;
|
||||
|
||||
lbPosition = rawCallerId.IndexOf('<');
|
||||
|
||||
if (lbPosition < 0)
|
||||
return null;
|
||||
|
||||
callerIdName = rawCallerId.Substring(0, (lbPosition) - (0)).Trim();
|
||||
if (callerIdName.StartsWith("\"") && callerIdName.EndsWith("\""))
|
||||
callerIdName = callerIdName.Substring(1, (callerIdName.Length - 1) - (1));
|
||||
|
||||
if (callerIdName.Length == 0)
|
||||
return null;
|
||||
else
|
||||
return callerIdName;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Dnid
|
||||
public string Dnid
|
||||
{
|
||||
get
|
||||
{
|
||||
string dnid = (string)(request["dnid"]);
|
||||
if (dnid == null || dnid.ToLower(Helper.CultureInfo) == "unknown")
|
||||
return null;
|
||||
return dnid;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Rdnis
|
||||
public string Rdnis
|
||||
{
|
||||
get
|
||||
{
|
||||
string rdnis = (string)(request["rdnis"]);
|
||||
if (rdnis == null || rdnis.ToLower(Helper.CultureInfo) == "unknown")
|
||||
return null;
|
||||
return rdnis;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Context
|
||||
/// <summary>
|
||||
/// Returns the context in the dial plan from which the AGI script was called.
|
||||
/// </summary>
|
||||
public string Context
|
||||
{
|
||||
get { return (string) request["context"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Extension
|
||||
/// <summary>
|
||||
/// Returns the extension in the dial plan from which the AGI script was called.
|
||||
/// </summary>
|
||||
public string Extension
|
||||
{
|
||||
get { return (string) request["extension"]; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Priority
|
||||
/// <summary>
|
||||
/// Returns the priority in the dial plan from which the AGI script was called.
|
||||
/// </summary>
|
||||
public int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["priority"] != null)
|
||||
{
|
||||
return Int32.Parse((string) request["priority"]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Enhanced
|
||||
/// <summary>
|
||||
/// Returns wheather this agi is passed audio (EAGI - Enhanced AGI).<br/>
|
||||
/// Enhanced AGI is currently not supported on FastAGI.<br/>
|
||||
/// <code>true</code> if this agi is passed audio, <code>false</code> otherwise.
|
||||
/// </summary>
|
||||
public bool Enhanced
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["enhanced"] != null && (string)request["enhanced"] == "1.0")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AccountCode
|
||||
/// <summary>
|
||||
/// Returns the account code set for the call.
|
||||
/// </summary>
|
||||
public string AccountCode
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string) request["accountCode"];
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LocalAddress
|
||||
public IPAddress LocalAddress
|
||||
{
|
||||
get { return localAddress; }
|
||||
set { this.localAddress = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LocalPort
|
||||
public int LocalPort
|
||||
{
|
||||
get { return localPort; }
|
||||
set { this.localPort = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoteAddress
|
||||
public IPAddress RemoteAddress
|
||||
{
|
||||
get { return remoteAddress; }
|
||||
set { this.remoteAddress = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemotePort
|
||||
public int RemotePort
|
||||
{
|
||||
get { return remotePort; }
|
||||
set { this.remotePort = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Script()
|
||||
/// <summary>
|
||||
/// Returns the name of the script to execute.
|
||||
/// </summary>
|
||||
public string Script
|
||||
{
|
||||
get
|
||||
{
|
||||
if (script != null)
|
||||
return script;
|
||||
|
||||
script = ((string)request["network_script"]);
|
||||
if (script != null)
|
||||
{
|
||||
Match scriptMatcher = Common.AGI_SCRIPT_PATTERN.Match(script);
|
||||
if (scriptMatcher.Success)
|
||||
{
|
||||
script = scriptMatcher.Groups[1].Value;
|
||||
parameters = scriptMatcher.Groups[2].Value;
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallingAni2
|
||||
public int CallingAni2
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["callingani2"] == null)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
return Int32.Parse((string)(request["callingani2"]));
|
||||
}
|
||||
catch {}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallingPres
|
||||
public int CallingPres
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["callingpres"] == null)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
return Int32.Parse((string)(request["callingpres"]));
|
||||
}
|
||||
catch {}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallingTns
|
||||
public int CallingTns
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["callingtns"] == null)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
return Int32.Parse((string)(request["callingtns"]));
|
||||
}
|
||||
catch {}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallingTon
|
||||
public int CallingTon
|
||||
{
|
||||
get
|
||||
{
|
||||
if (request["callington"] == null)
|
||||
return -1;
|
||||
try
|
||||
{
|
||||
return Int32.Parse((String)(request["callington"]));
|
||||
}
|
||||
catch {}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Parameter(string name)
|
||||
public string Parameter(string name)
|
||||
{
|
||||
List<string> values;
|
||||
values = ParameterValues(name);
|
||||
if (values == null || values.Count == 0)
|
||||
return null;
|
||||
return values[0];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParameterValues(string name)
|
||||
public List<string> ParameterValues(string name)
|
||||
{
|
||||
if (ParameterMap().Count == 0)
|
||||
return null;
|
||||
|
||||
return parameterMap[name];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParameterMap()
|
||||
public Dictionary<string, List<string>> ParameterMap()
|
||||
{
|
||||
if (parameterMap == null)
|
||||
parameterMap = parseParameters(this.parameters);
|
||||
return parameterMap;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString()
|
||||
public override string ToString()
|
||||
{
|
||||
return Helper.ToString(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region buildMap(ICollection lines)
|
||||
/// <summary>
|
||||
/// Builds a map containing variable names as key (with the "agi_" prefix stripped) and the corresponding values.<br/>
|
||||
/// Syntactically invalid and empty variables are skipped.
|
||||
/// </summary>
|
||||
/// <param name="lines">the environment to transform.</param>
|
||||
/// <returns> a map with the variables set corresponding to the given environment.</returns>
|
||||
private Dictionary<string, string> buildMap(List<string> lines)
|
||||
{
|
||||
int colonPosition;
|
||||
string key;
|
||||
string value;
|
||||
|
||||
Dictionary<string, string> map = new Dictionary<string,string>(lines.Count);
|
||||
foreach (string line in lines)
|
||||
{
|
||||
colonPosition = line.IndexOf(':');
|
||||
if (colonPosition < 0 || !line.StartsWith("agi_") || line.Length < colonPosition + 2)
|
||||
continue;
|
||||
|
||||
key = line.Substring(4, colonPosition - 4).ToLower(Helper.CultureInfo);
|
||||
value = line.Substring(colonPosition + 2);
|
||||
if (value.Length != 0)
|
||||
map.Add(key, value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region parseParameters(string s)
|
||||
/// <summary>
|
||||
/// Parses the given parameter string and caches the result.
|
||||
/// </summary>
|
||||
/// <param name="s">the parameter string to parse</param>
|
||||
/// <returns> a Map made up of parameter names their values</returns>
|
||||
private Dictionary<string, List<string>> parseParameters(string parameters)
|
||||
{
|
||||
Dictionary<string, List<string>> result = new Dictionary<string, List<string>>();
|
||||
string name;
|
||||
string val;
|
||||
|
||||
if (string.IsNullOrEmpty(parameters))
|
||||
return result;
|
||||
|
||||
string[] pars = parameters.Split('&');
|
||||
if (pars.Length == 0)
|
||||
return result;
|
||||
|
||||
foreach (string parameter in pars)
|
||||
{
|
||||
val = string.Empty;
|
||||
int i = parameter.IndexOf('=');
|
||||
if (i > 0)
|
||||
{
|
||||
name = HttpUtility.UrlDecode(parameter.Substring(0, i));
|
||||
if (parameter.Length > i + 1)
|
||||
val = HttpUtility.UrlDecode(parameter.Substring(i + 1));
|
||||
}
|
||||
else if (i < 0)
|
||||
name = HttpUtility.UrlDecode(parameter);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (!result.ContainsKey(name))
|
||||
result.Add(name, new List<string>());
|
||||
result[name].Add(val);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
817
Asterisk.2013/Asterisk.NET/FastAGI/AGIScript.cs
Normal file
817
Asterisk.2013/Asterisk.NET/FastAGI/AGIScript.cs
Normal file
|
@ -0,0 +1,817 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// The BaseAGIScript provides some convinience methods to make it easier to
|
||||
/// write custom AGIScripts.<br/>
|
||||
/// Just extend it by your own AGIScripts.
|
||||
/// </summary>
|
||||
public abstract class AGIScript
|
||||
{
|
||||
#region Answer()
|
||||
/// <summary>
|
||||
/// Answers the channel.
|
||||
/// </summary>
|
||||
protected internal void Answer()
|
||||
{
|
||||
this.Channel.SendCommand(new Command.AnswerCommand());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hangup()
|
||||
/// <summary>
|
||||
/// Hangs the channel up.
|
||||
/// </summary>
|
||||
protected internal void Hangup()
|
||||
{
|
||||
this.Channel.SendCommand(new Command.HangupCommand());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetAutoHangup
|
||||
/// <summary>
|
||||
/// Cause the channel to automatically hangup at the given number of seconds in the future.<br/>
|
||||
/// 0 disables the autohangup feature.
|
||||
/// </summary>
|
||||
protected internal void SetAutoHangup(int time)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetAutoHangupCommand(time));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetCallerId
|
||||
/// <summary>
|
||||
/// Sets the caller id on the current channel.<br/>
|
||||
/// The raw caller id to set, for example "John Doe<1234>".
|
||||
/// </summary>
|
||||
protected internal void SetCallerId(string callerId)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetCallerIdCommand(callerId));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PlayMusicOnHold()
|
||||
/// <summary>
|
||||
/// Plays music on hold from the default music on hold class.
|
||||
/// </summary>
|
||||
protected internal void PlayMusicOnHold()
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetMusicOnCommand());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PlayMusicOnHold(string musicOnHoldClass)
|
||||
/// <summary>
|
||||
/// Plays music on hold from the given music on hold class.
|
||||
/// </summary>
|
||||
/// <param name="musicOnHoldClass">the music on hold class to play music from as configures in Asterisk's <code><musiconhold.conf/code>.</param>
|
||||
protected internal void PlayMusicOnHold(string musicOnHoldClass)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetMusicOnCommand(musicOnHoldClass));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StopMusicOnHold()
|
||||
/// <summary>
|
||||
/// Stops playing music on hold.
|
||||
/// </summary>
|
||||
protected internal void StopMusicOnHold()
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetMusicOffCommand());
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetChannelStatus
|
||||
/// <summary>
|
||||
/// Returns the status of the channel.<br/>
|
||||
/// Return values:
|
||||
/// <ul>
|
||||
/// <li>0 Channel is down and available
|
||||
/// <li>1 Channel is down, but reserved
|
||||
/// <li>2 Channel is off hook
|
||||
/// <li>3 Digits (or equivalent) have been dialed
|
||||
/// <li>4 Line is ringing
|
||||
/// <li>5 Remote end is ringing
|
||||
/// <li>6 Line is up
|
||||
/// <li>7 Line is busy
|
||||
/// </ul>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> the status of the channel.
|
||||
/// </returns>
|
||||
protected internal int GetChannelStatus()
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ChannelStatusCommand());
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetData(string file)
|
||||
/// <summary>
|
||||
/// Plays the given file and waits for the user to enter DTMF digits until he
|
||||
/// presses '#'. The user may interrupt the streaming by starting to enter
|
||||
/// digits.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to play</param>
|
||||
/// <returns> a String containing the DTMF the user entered</returns>
|
||||
protected internal string GetData(string file)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetDataCommand(file));
|
||||
return channel.LastReply.GetResult();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetData(string file, int timeout)
|
||||
/// <summary>
|
||||
/// Plays the given file and waits for the user to enter DTMF digits until he
|
||||
/// presses '#' or the timeout occurs. The user may interrupt the streaming
|
||||
/// by starting to enter digits.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to play</param>
|
||||
/// <param name="timeout">the timeout in milliseconds to wait for user input.<br/>
|
||||
/// 0 means standard timeout value, -1 means "ludicrous time"
|
||||
/// (essentially never times out).</param>
|
||||
/// <returns> a String containing the DTMF the user entered</returns>
|
||||
protected internal string GetData(string file, long timeout)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetDataCommand(file, timeout));
|
||||
return channel.LastReply.GetResult();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetData(string file, int timeout, int maxDigits)
|
||||
/// <summary>
|
||||
/// Plays the given file and waits for the user to enter DTMF digits until he
|
||||
/// presses '#' or the timeout occurs or the maximum number of digits has
|
||||
/// been entered. The user may interrupt the streaming by starting to enter
|
||||
/// digits.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to play</param>
|
||||
/// <param name="timeout">the timeout in milliseconds to wait for user input.<br/>
|
||||
/// 0 means standard timeout value, -1 means "ludicrous time"
|
||||
/// (essentially never times out).</param>
|
||||
/// <param name="maxDigits">the maximum number of digits the user is allowed to enter</param>
|
||||
/// <returns> a String containing the DTMF the user entered</returns>
|
||||
protected internal string GetData(string file, long timeout, int maxDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetDataCommand(file, timeout, maxDigits));
|
||||
return channel.LastReply.GetResult();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region GetOption(string file, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Plays the given file, and waits for the user to press one of the given
|
||||
/// digits. If none of the esacpe digits is pressed while streaming the file
|
||||
/// it waits for the default timeout of 5 seconds still waiting for the user
|
||||
/// to press a digit.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that the user is expected to press.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char GetOption(string file, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetOptionCommand(file, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetOption(string file, string escapeDigits, int timeout)
|
||||
/// <summary>
|
||||
/// Plays the given file, and waits for the user to press one of the given
|
||||
/// digits. If none of the esacpe digits is pressed while streaming the file
|
||||
/// it waits for the specified timeout still waiting for the user to press a
|
||||
/// digit.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that the user is expected to press.</param>
|
||||
/// <param name="timeout">the timeout in seconds to wait if none of the defined esacpe digits was presses while streaming.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char GetOption(string file, string escapeDigits, int timeout)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetOptionCommand(file, escapeDigits, timeout));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Exec(string application)
|
||||
/// <summary>
|
||||
/// Executes the given command.
|
||||
/// </summary>
|
||||
/// <param name="application">the name of the application to execute, for example "Dial".</param>
|
||||
/// <returns> the return code of the application of -2 if the application was not found.</returns>
|
||||
protected internal int Exec(string application)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ExecCommand(application));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Exec(string application, string options)
|
||||
/// <summary>
|
||||
/// Executes the given command.
|
||||
/// </summary>
|
||||
/// <param name="application">the name of the application to execute, for example "Dial".</param>
|
||||
/// <param name="options">the parameters to pass to the application, for example "SIP/123".</param>
|
||||
/// <returns> the return code of the application of -2 if the application was not found.</returns>
|
||||
protected internal int Exec(string application, string options)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ExecCommand(application, options));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetContext
|
||||
/// <summary>
|
||||
/// Sets the context for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
protected internal void SetContext(string context)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetContextCommand(context));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetExtension
|
||||
/// <summary>
|
||||
/// Sets the extension for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
protected internal void SetExtension(string extension)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetExtensionCommand(extension));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetPriority(int priority)
|
||||
/// <summary>
|
||||
/// Sets the priority for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
protected internal void SetPriority(int priority)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetPriorityCommand(priority));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetPriority(string label priority)
|
||||
/// <summary>
|
||||
/// Sets the label for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
protected internal void SetPriority(string label)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetPriorityCommand(label));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StreamFile(string file)
|
||||
/// <summary>
|
||||
/// Plays the given file.
|
||||
/// </summary>
|
||||
/// <param name="file">name of the file to play.</param>
|
||||
protected internal void StreamFile(string file)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.StreamFileCommand(file));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StreamFile(string file, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Plays the given file and allows the user to escape by pressing one of the given digit.
|
||||
/// </summary>
|
||||
/// <param name="file">name of the file to play.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char StreamFile(string file, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.StreamFileCommand(file, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayDigits(string digits)
|
||||
/// <summary>
|
||||
/// Says the given digit string.
|
||||
/// </summary>
|
||||
/// <param name="digits">the digit string to say.</param>
|
||||
protected internal void SayDigits(string digits)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayDigitsCommand(digits));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayDigits(string digits, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Says the given number, returning early if any of the given DTMF number
|
||||
/// are received on the channel.
|
||||
/// </summary>
|
||||
/// <param name="digits">the digit string to say.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayDigits(string digits, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayDigitsCommand(digits, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayNumber(string number)
|
||||
/// <summary>
|
||||
/// Says the given number.
|
||||
/// </summary>
|
||||
/// <param name="number">the number to say.</param>
|
||||
protected internal void SayNumber(string number)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayNumberCommand(number));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayNumber(string number, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Says the given number, returning early if any of the given DTMF number
|
||||
/// are received on the channel.
|
||||
/// </summary>
|
||||
/// <param name="number">the number to say.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayNumber(string number, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayNumberCommand(number, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayPhonetic(string text)
|
||||
/// <summary>
|
||||
/// Says the given character string with phonetics.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
protected internal void SayPhonetic(string text)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayPhoneticCommand(text));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayPhonetic(string text, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Says the given character string with phonetics, returning early if any of
|
||||
/// the given DTMF number are received on the channel.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayPhonetic(string text, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayPhoneticCommand(text, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayAlpha(string text)
|
||||
/// <summary>
|
||||
/// Says the given character string.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
protected internal void SayAlpha(string text)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayAlphaCommand(text));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayAlpha(string text, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Says the given character string, returning early if any of the given DTMF
|
||||
/// number are received on the channel.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayAlpha(string text, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayAlphaCommand(text, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayTime(long time)
|
||||
/// <summary>
|
||||
/// Says the given time.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds since 00:00:00 on January 1, 1970.</param>
|
||||
protected internal void SayTime(long time)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayTimeCommand(time));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayTime(long time, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Says the given time, returning early if any of the given DTMF number are
|
||||
/// received on the channel.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds since 00:00:00 on January 1, 1970.</param>
|
||||
/// <param name="escapeDigits">a String containing the DTMF digits that allow the user to escape.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayTime(long time, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayTimeCommand(time, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetVariable(string name)
|
||||
/// <summary>
|
||||
/// Returns the value of the given channel variable.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the variable to retrieve.</param>
|
||||
/// <returns> the value of the given variable or <code>null</code> if not set.</returns>
|
||||
protected internal string GetVariable(string name)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetVariableCommand(name));
|
||||
if (channel.LastReply.ResultCode != 1)
|
||||
return null;
|
||||
return channel.LastReply.Extra;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetVariable(string name, string value_Renamed)
|
||||
/// <summary>
|
||||
/// Sets the value of the given channel variable to a new value.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the variable to retrieve.</param>
|
||||
/// <param name="val">the new value to set.</param>
|
||||
protected internal void SetVariable(string name, string val)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SetVariableCommand(name, val));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region WaitForDigit(int timeout)
|
||||
/// <summary>
|
||||
/// Waits up to 'timeout' milliseconds to receive a DTMF digit.
|
||||
/// </summary>
|
||||
/// <param name="timeout">timeout the milliseconds to wait for the channel to receive a DTMF digit, -1 will wait forever.</param>
|
||||
/// <returns> the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char WaitForDigit(int timeout)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.WaitForDigitCommand(timeout));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFullVariable(string name)
|
||||
/// <summary>
|
||||
/// Returns the value of the current channel variable, unlike getVariable()
|
||||
/// this method understands complex variable names and builtin variables.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the variable to retrieve.</param>
|
||||
/// <returns>the value of the given variable or <code>null</code> if not et.</returns>
|
||||
protected internal string GetFullVariable(string name)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetFullVariableCommand(name));
|
||||
if (channel.LastReply.ResultCode != 1)
|
||||
return null;
|
||||
return channel.LastReply.Extra;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFullVariable(string name, string channel)
|
||||
/// <summary>
|
||||
/// Returns the value of the given channel variable.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="name">the name of the variable to retrieve.</param>
|
||||
/// <param name="channel">the name of the channel.</param>
|
||||
/// <returns>the value of the given variable or <code>null</code> if not set.</returns>
|
||||
protected internal string GetFullVariable(string name, string channelName)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.GetFullVariableCommand(name, channelName));
|
||||
if (channel.LastReply.ResultCode != 1)
|
||||
return null;
|
||||
return channel.LastReply.Extra;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SayDateTime(...)
|
||||
/// <summary>
|
||||
/// Says the given time.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
protected internal void SayDateTime(long time)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.SayDateTimeCommand(time));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Says the given time and allows interruption by one of the given escape digits.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
/// <returns>the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayDateTime(long time, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Says the given time in the given format and allows interruption by one of the given escape digits.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
/// <param name="format">the format the time should be said in</param>
|
||||
/// <returns>the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayDateTime(long time, string escapeDigits, string format)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits, format));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Says the given time in the given format and timezone and allows interruption by one of the given escape digits.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
/// <param name="format">the format the time should be said in</param>
|
||||
/// <param name="timezone">the timezone to use when saying the time, for example "UTC" or "Europe/Berlin".</param>
|
||||
/// <returns>the DTMF digit pressed or 0x0 if none was pressed.</returns>
|
||||
protected internal char SayDateTime(long time, string escapeDigits, string format, string timezone)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.SayDateTimeCommand(time, escapeDigits, format, timezone));
|
||||
return channel.LastReply.ResultCodeAsChar;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DatabaseGet(string family, string key)
|
||||
/// <summary>
|
||||
/// Retrieves an entry in the Asterisk database for a given family and key.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the entry to retrieve.</param>
|
||||
/// <param name="key">key the key of the entry to retrieve.</param>
|
||||
/// <return>the value of the given family and key or <code>null</code> if there is no such value.</return>
|
||||
protected internal string DatabaseGet(string family, string key)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.DatabaseGetCommand(family, key));
|
||||
if (channel.LastReply.ResultCode != 1)
|
||||
return null;
|
||||
return channel.LastReply.Extra;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DatabasePut(string family, string key, string value)
|
||||
/// <summary>
|
||||
/// Adds or updates an entry in the Asterisk database for a given family, key and value.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the entry to add or update.</param>
|
||||
/// <param name="key">the key of the entry to add or update.</param>
|
||||
/// <param name="value">the new value of the entry.</param>
|
||||
protected internal void DatabasePut(string family, string key, string value)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.DatabasePutCommand(family, key, value));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DatabaseDel(string family, string key)
|
||||
/// <summary>
|
||||
/// Deletes an entry in the Asterisk database for a given family and key.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the entry to delete.</param>
|
||||
/// <param name="key">the key of the entry to delete.</param>
|
||||
protected internal void DatabaseDel(string family, string key)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.DatabaseDelCommand(family, key));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DatabaseDelTree(String family)
|
||||
/// <summary>
|
||||
/// Deletes a whole family of entries in the Asterisk database.
|
||||
/// </summary>
|
||||
/// <param name="family">the family to delete.</param>
|
||||
protected internal void DatabaseDelTree(string family)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.DatabaseDelTreeCommand(family));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DatabaseDelTree(string family, string keytree)
|
||||
/// <summary>
|
||||
/// Deletes all entries of a given family in the Asterisk database that have a key that starts with a given prefix.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the entries to delete.</param>
|
||||
/// <param name="keytree">the prefix of the keys of the entries to delete.</param>
|
||||
protected internal void DatabaseDelTree(string family, string keytree)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.DatabaseDelTreeCommand(family, keytree));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Verbose(string message, int level)
|
||||
/// <summary>
|
||||
/// Sends a message to the Asterisk console via the verbose message system.
|
||||
/// </summary>
|
||||
/// <param name="message">the message to send</param>
|
||||
/// <param name="level">the verbosity level to use. Must be in [1..4]</param>
|
||||
public void Verbose(string message, int level)
|
||||
{
|
||||
this.Channel.SendCommand(new Command.VerboseCommand(message, level));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RecordFile(...)
|
||||
/// <summary>
|
||||
/// Record to a file until a given dtmf digit in the sequence is received.<br/>
|
||||
/// Returns -1 on hangup or error.<br/>
|
||||
/// The format will specify what kind of file will be recorded. The timeout is
|
||||
/// the maximum record time in milliseconds, or -1 for no timeout. Offset samples
|
||||
/// is optional, and if provided will seek to the offset without exceeding the
|
||||
/// end of the file. "maxSilence" is the number of seconds of maxSilence allowed
|
||||
/// before the function returns despite the lack of dtmf digits or reaching
|
||||
/// timeout.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="format">the format of the file to be recorded, for example "wav".</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to end recording.</param>
|
||||
/// <param name="timeout">the maximum record time in milliseconds, or -1 for no timeout.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int RecordFile(string file, string format, string escapeDigits, int timeout)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.RecordFileCommand(file, format, escapeDigits, timeout));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Record to a file until a given dtmf digit in the sequence is received.<br/>
|
||||
/// Returns -1 on hangup or error.<br/>
|
||||
/// The format will specify what kind of file will be recorded. The timeout is
|
||||
/// the maximum record time in milliseconds, or -1 for no timeout. Offset samples
|
||||
/// is optional, and if provided will seek to the offset without exceeding the
|
||||
/// end of the file. "maxSilence" is the number of seconds of maxSilence allowed
|
||||
/// before the function returns despite the lack of dtmf digits or reaching
|
||||
/// timeout.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="format">the format of the file to be recorded, for example "wav".</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to end recording.</param>
|
||||
/// <param name="timeout">the maximum record time in milliseconds, or -1 for no timeout.</param>
|
||||
/// <param name="offset">the offset samples to skip.</param>
|
||||
/// <param name="beep"><code>true</code> if a beep should be played before recording.</param>
|
||||
/// <param name="maxSilence">The amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int RecordFile(string file, string format, string escapeDigits, int timeout, int offset, bool beep, int maxSilence)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.RecordFileCommand(file, format, escapeDigits, timeout, offset, beep, maxSilence));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ControlStreamFile(...)
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given
|
||||
/// digits, if any, and allows the listner to control the stream.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play
|
||||
/// starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
/// <seealso cref="Command.ControlStreamFileCommand"/>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int ControlStreamFile(string file)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ControlStreamFileCommand(file));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given
|
||||
/// digits, if any, and allows the listner to control the stream.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play
|
||||
/// starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
/// <seealso cref="Command.ControlStreamFileCommand"/>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int ControlStreamFile(string file, string escapeDigits)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given
|
||||
/// digits, if any, and allows the listner to control the stream.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play
|
||||
/// starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
/// <seealso cref="Command.ControlStreamFileCommand"/>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
/// <param name="offset">the offset samples to skip before streaming.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int ControlStreamFile(string file, string escapeDigits, int offset)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits, offset));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given
|
||||
/// digits, if any, and allows the listner to control the stream.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play
|
||||
/// starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
/// <seealso cref="Command.ControlStreamFileCommand"/>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
/// <param name="offset">the offset samples to skip before streaming.</param>
|
||||
/// <param name="forwardDigit">the digit for fast forward.</param>
|
||||
/// <param name="rewindDigit">the digit for rewind.</param>
|
||||
/// <param name="pauseDigit">the digit for pause and unpause.</param>
|
||||
/// <returns>result code</returns>
|
||||
protected internal int ControlStreamFile(string file, string escapeDigits, int offset, string forwardDigit, string rewindDigit, string pauseDigit)
|
||||
{
|
||||
AGIChannel channel = this.Channel;
|
||||
channel.SendCommand(new Command.ControlStreamFileCommand(file, escapeDigits, offset, forwardDigit, rewindDigit, pauseDigit));
|
||||
return channel.LastReply.ResultCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SendCommand(Command.AGICommand command)
|
||||
/// <summary>
|
||||
/// Sends the given command to the channel attached to the current thread.
|
||||
/// </summary>
|
||||
/// <param name="command">the command to send to Asterisk</param>
|
||||
/// <returns> the reply received from Asterisk</returns>
|
||||
/// <throws> AGIException if the command could not be processed properly </throws>
|
||||
private AGIReply SendCommand(Command.AGICommand command)
|
||||
{
|
||||
return this.Channel.SendCommand(command);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Channel
|
||||
protected internal AGIChannel Channel
|
||||
{
|
||||
get
|
||||
{
|
||||
AGIChannel channel = AGIConnectionHandler.Channel;
|
||||
if (channel == null)
|
||||
throw new SystemException("Trying to send command from an invalid thread");
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Service(AGIRequest param1, AGIChannel param2);
|
||||
public abstract void Service(AGIRequest param1, AGIChannel param2);
|
||||
#endregion
|
||||
}
|
||||
}
|
31
Asterisk.2013/Asterisk.NET/FastAGI/AGIWriter.cs
Normal file
31
Asterisk.2013/Asterisk.NET/FastAGI/AGIWriter.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of the AGIWriter interface.
|
||||
/// </summary>
|
||||
public class AGIWriter
|
||||
{
|
||||
private IO.SocketConnection socket;
|
||||
|
||||
public AGIWriter(IO.SocketConnection socket)
|
||||
{
|
||||
lock (this)
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
public void SendCommand(Command.AGICommand command)
|
||||
{
|
||||
string buffer = command.BuildCommand() + "\n";
|
||||
try
|
||||
{
|
||||
socket.Write(buffer);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AGINetworkException("Unable to send command to Asterisk: " + e.Message, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
220
Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs
Normal file
220
Asterisk.2013/Asterisk.NET/FastAGI/AsteriskFastAGI.cs
Normal file
|
@ -0,0 +1,220 @@
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
public class AsteriskFastAGI
|
||||
{
|
||||
#region Variables
|
||||
#if LOGGER
|
||||
private Logger logger = Logger.Instance();
|
||||
#endif
|
||||
private IO.ServerSocket serverSocket;
|
||||
|
||||
/// <summary> The port to listen on.</summary>
|
||||
private int port;
|
||||
/// <summary> The address to listen on.</summary>
|
||||
private string address;
|
||||
/// <summary>The thread pool that contains the worker threads to process incoming requests.</summary>
|
||||
private Util.ThreadPool pool;
|
||||
/// <summary>The number of worker threads in the thread pool. This equals the maximum number of concurrent requests this AGIServer can serve.</summary>
|
||||
private int poolSize;
|
||||
/// <summary> True while this server is shut down. </summary>
|
||||
private bool stopped;
|
||||
/// <summary>
|
||||
/// The strategy to use for bind AGIRequests to AGIScripts that serve them.
|
||||
/// </summary>
|
||||
private MappingStrategy mappingStrategy;
|
||||
private Encoding socketEncoding = Encoding.ASCII;
|
||||
#endregion
|
||||
|
||||
#region PoolSize
|
||||
/// <summary>
|
||||
/// Sets the number of worker threads in the thread pool.<br/>
|
||||
/// This equals the maximum number of concurrent requests this AGIServer can serve.<br/>
|
||||
/// The default pool size is 10.
|
||||
/// </summary>
|
||||
public int PoolSize
|
||||
{
|
||||
set { this.poolSize = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BindPort
|
||||
/// <summary>
|
||||
/// Sets the TCP port to listen on for new connections.<br/>
|
||||
/// The default bind port is 4573.
|
||||
/// </summary>
|
||||
public int BindPort
|
||||
{
|
||||
set
|
||||
{
|
||||
this.port = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MappingStrategy
|
||||
/// <summary>
|
||||
/// Sets the strategy to use for mapping AGIRequests to AGIScripts that serve them.<br/>
|
||||
/// The default mapping is a MappingStrategy.
|
||||
/// </summary>
|
||||
/// <seealso cref="MappingStrategy" />
|
||||
public MappingStrategy MappingStrategy
|
||||
{
|
||||
set { this.mappingStrategy = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SocketEncoding
|
||||
public Encoding SocketEncoding
|
||||
{
|
||||
get { return this.socketEncoding; }
|
||||
set { this.socketEncoding = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - AsteriskFastAGI()
|
||||
/// <summary>
|
||||
/// Creates a new AsteriskFastAGI.
|
||||
/// </summary>
|
||||
public AsteriskFastAGI()
|
||||
{
|
||||
this.address = Common.AGI_BIND_ADDRESS;
|
||||
this.port = Common.AGI_BIND_PORT;
|
||||
this.poolSize = Common.AGI_POOL_SIZE;
|
||||
this.mappingStrategy = new MappingStrategy();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - AsteriskFastAGI()
|
||||
/// <summary>
|
||||
/// Creates a new AsteriskFastAGI.
|
||||
/// </summary>
|
||||
public AsteriskFastAGI(string mappingStrategy)
|
||||
{
|
||||
this.address = Common.AGI_BIND_ADDRESS;
|
||||
this.port = Common.AGI_BIND_PORT;
|
||||
this.poolSize = Common.AGI_POOL_SIZE;
|
||||
this.mappingStrategy = new MappingStrategy(mappingStrategy);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - AsteriskFastAGI(int port, int poolSize)
|
||||
/// <summary>
|
||||
/// Creates a new AsteriskFastAGI.
|
||||
/// </summary>
|
||||
/// <param name="port">The port to listen on.</param>
|
||||
/// <param name="poolSize">The number of worker threads in the thread pool.
|
||||
/// This equals the maximum number of concurrent requests this AGIServer can serve.</param>
|
||||
public AsteriskFastAGI(int port, int poolSize)
|
||||
{
|
||||
this.address = Common.AGI_BIND_ADDRESS;
|
||||
this.port = port;
|
||||
this.poolSize = poolSize;
|
||||
this.mappingStrategy = new MappingStrategy();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - AsteriskFastAGI(string address, int port, int poolSize)
|
||||
/// <summary>
|
||||
/// Creates a new AsteriskFastAGI.
|
||||
/// </summary>
|
||||
/// <param name="ipaddress">The address to listen on.</param>
|
||||
/// <param name="port">The port to listen on.</param>
|
||||
/// <param name="poolSize">The number of worker threads in the thread pool.
|
||||
/// This equals the maximum number of concurrent requests this AGIServer can serve.</param>
|
||||
public AsteriskFastAGI(string ipaddress, int port, int poolSize)
|
||||
{
|
||||
this.address = ipaddress;
|
||||
this.port = port;
|
||||
this.poolSize = poolSize;
|
||||
this.mappingStrategy = new MappingStrategy();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Start()
|
||||
public void Start()
|
||||
{
|
||||
stopped = false;
|
||||
mappingStrategy.Load();
|
||||
pool = new Util.ThreadPool("AGIServer", poolSize);
|
||||
#if LOGGER
|
||||
logger.Info("Thread pool started.");
|
||||
#endif
|
||||
try
|
||||
{
|
||||
IPAddress ipAddress = IPAddress.Parse(address);
|
||||
serverSocket = new IO.ServerSocket(port, ipAddress, this.SocketEncoding);
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable start AGI Server: cannot to bind to "+ address + ":" + port + ".", ex);
|
||||
#endif
|
||||
throw ex;
|
||||
}
|
||||
#if LOGGER
|
||||
logger.Info("Listening on "+ address + ":" + port + ".");
|
||||
#endif
|
||||
|
||||
AGIConnectionHandler connectionHandler;
|
||||
IO.SocketConnection socket;
|
||||
try
|
||||
{
|
||||
while ((socket = serverSocket.Accept()) != null)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Info("Received connection.");
|
||||
#endif
|
||||
connectionHandler = new AGIConnectionHandler(socket, mappingStrategy);
|
||||
pool.AddJob(connectionHandler);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
if (!stopped)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("IOException while waiting for connections (1).", ex);
|
||||
#endif
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (serverSocket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverSocket.Close();
|
||||
}
|
||||
#if LOGGER
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.Error("IOException while waiting for connections (2).", ex);
|
||||
}
|
||||
#else
|
||||
catch { }
|
||||
#endif
|
||||
}
|
||||
serverSocket = null;
|
||||
pool.Shutdown();
|
||||
#if LOGGER
|
||||
logger.Info("AGIServer shut down.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Stop()
|
||||
public void Stop()
|
||||
{
|
||||
stopped = true;
|
||||
if (serverSocket != null)
|
||||
serverSocket.Close();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
26
Asterisk.2013/Asterisk.NET/FastAGI/Command/AGICommand.cs
Normal file
26
Asterisk.2013/Asterisk.NET/FastAGI/Command/AGICommand.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
public abstract class AGICommand
|
||||
{
|
||||
public abstract string BuildCommand();
|
||||
|
||||
protected internal string EscapeAndQuote(string s)
|
||||
{
|
||||
string tmp;
|
||||
if (s == null)
|
||||
return "\"\"";
|
||||
|
||||
tmp = s;
|
||||
tmp = tmp.Replace("\\\"", "\\\\\""); // escape quotes
|
||||
tmp = tmp.Replace("\\\n", ""); // filter newline
|
||||
return "\"" + tmp + "\""; // add quotes
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Helper.ToString(this);
|
||||
}
|
||||
}
|
||||
}
|
14
Asterisk.2013/Asterisk.NET/FastAGI/Command/AnswerCommand.cs
Normal file
14
Asterisk.2013/Asterisk.NET/FastAGI/Command/AnswerCommand.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
public class AnswerCommand : AGICommand
|
||||
{
|
||||
public AnswerCommand()
|
||||
{
|
||||
}
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "ANSWER";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the status of the specified channel.
|
||||
/// If no channel name is given the returns the status of the current channel.<br/>
|
||||
/// Return values:
|
||||
/// <ul>
|
||||
/// <li>0 Channel is down and available
|
||||
/// <li>1 Channel is down, but reserved
|
||||
/// <li>2 Channel is off hook
|
||||
/// <li>3 Digits (or equivalent) have been dialed
|
||||
/// <li>4 Line is ringing
|
||||
/// <li>5 Remote end is ringing
|
||||
/// <li>6 Line is up
|
||||
/// <li>7 Line is busy
|
||||
/// </ul>
|
||||
/// </summary>
|
||||
public class ChannelStatusCommand : AGICommand
|
||||
{
|
||||
private string channel;
|
||||
public string Channel
|
||||
{
|
||||
get
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.channel = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ChannelStatusCommand()
|
||||
{
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ChannelStatusCommand that queries the given channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to query.</param>
|
||||
public ChannelStatusCommand(string channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "CHANNEL STATUS" + (channel == null ? "" : " " + EscapeAndQuote(channel));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given
|
||||
/// digits, if any, and allows the listner to control the stream.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play
|
||||
/// starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
public class ControlStreamFileCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the file to stream.</summary>
|
||||
private string file;
|
||||
/// <summary> When one of these digits is pressed while streaming the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
/// <summary> The offset samples to skip before streaming.</summary>
|
||||
private int offset;
|
||||
private string forwardDigit;
|
||||
private string rewindDigit;
|
||||
private string pauseDigit;
|
||||
|
||||
#region File
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to stream.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
#endregion
|
||||
#region EscapeDigits
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command or <code>null</code> for none.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Offset
|
||||
/// <summary>
|
||||
/// Get/Set the offset samples to skip before streaming.
|
||||
/// </summary>
|
||||
public int Offset
|
||||
{
|
||||
get { return offset; }
|
||||
set { this.offset = value; }
|
||||
}
|
||||
#endregion
|
||||
#region ForwardDigit
|
||||
/// <summary>
|
||||
/// Get the digit for fast forward.
|
||||
/// </summary>
|
||||
public string ForwardDigit
|
||||
{
|
||||
get { return forwardDigit; }
|
||||
}
|
||||
#endregion
|
||||
#region RewindDigit
|
||||
/// <summary>
|
||||
/// Get the digit for rewind.
|
||||
/// </summary>
|
||||
public string RewindDigit
|
||||
{
|
||||
get { return rewindDigit; }
|
||||
}
|
||||
#endregion
|
||||
#region PauseDigit
|
||||
/// <summary>
|
||||
/// Get the digit for pause and unpause.
|
||||
/// </summary>
|
||||
public string PauseDigit
|
||||
{
|
||||
get { return pauseDigit; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ControlStreamFileCommand(string file)
|
||||
/// <summary>
|
||||
/// Creates a new ControlStreamFileCommand, streaming from the beginning. It
|
||||
/// uses the default digit "#" for forward and "*" for rewind and does not
|
||||
/// support pausing.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
public ControlStreamFileCommand(string file)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = null;
|
||||
this.offset = - 1;
|
||||
}
|
||||
#endregion
|
||||
#region ControlStreamFileCommand(string file, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Creates a new ControlStreamFileCommand, streaming from the beginning. It
|
||||
/// uses the default digit "#" for forward and "*" for rewind and does not
|
||||
/// support pausing.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
public ControlStreamFileCommand(string file, string escapeDigits)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = - 1;
|
||||
}
|
||||
#endregion
|
||||
#region ControlStreamFileCommand(string file, string escapeDigits, int offset)
|
||||
/// <summary>
|
||||
/// Creates a new ControlStreamFileCommand, streaming from the given offset.
|
||||
/// It uses the default digit "#" for forward and "*" for rewind and does not
|
||||
/// support pausing.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">
|
||||
/// contains the digits that allow the user to interrupt this command.
|
||||
/// Maybe <code>null</code> if you don't want the user to interrupt.
|
||||
/// </param>
|
||||
/// <param name="offset">the offset samples to skip before streaming.</param>
|
||||
public ControlStreamFileCommand(string file, string escapeDigits, int offset)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = offset;
|
||||
}
|
||||
#endregion
|
||||
#region ControlStreamFileCommand(string file, string escapeDigits, int offset, string forwardDigit, string rewindDigit, string pauseDigit)
|
||||
/// <summary>
|
||||
/// Creates a new ControlStreamFileCommand, streaming from the given offset.
|
||||
/// It uses the default digit "#" for forward and "*" for rewind and does not
|
||||
/// support pausing.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command. Maybe <code>null</code> if you don't want the user to interrupt.</param>
|
||||
/// <param name="offset">the offset samples to skip before streaming.</param>
|
||||
/// <param name="forwardDigit">the digit for fast forward.</param>
|
||||
/// <param name="rewindDigit">the digit for rewind.</param>
|
||||
/// <param name="pauseDigit">the digit for pause and unpause.</param>
|
||||
public ControlStreamFileCommand(string file, string escapeDigits, int offset, string forwardDigit, string rewindDigit, string pauseDigit)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = offset;
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
this.pauseDigit = pauseDigit;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ControlDigits(string forwardDigit, string rewindDigit)
|
||||
/// <summary>
|
||||
/// Sets the control digits for fast forward and rewind.
|
||||
/// </summary>
|
||||
/// <param name="forwardDigit">the digit for fast forward.</param>
|
||||
/// <param name="rewindDigit">the digit for rewind.</param>
|
||||
public void ControlDigits(string forwardDigit, string rewindDigit)
|
||||
{
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
}
|
||||
#endregion
|
||||
#region ControlDigits(string forwardDigit, string rewindDigit, string pauseDigit)
|
||||
/// <summary>
|
||||
/// Sets the control digits for fast forward, rewind and pause.
|
||||
/// </summary>
|
||||
/// <param name="forwardDigit">the digit for fast forward.</param>
|
||||
/// <param name="rewindDigit">the digit for rewind.</param>
|
||||
/// <param name="pauseDigit">the digit for pause and unpause.</param>
|
||||
public void ControlDigits(string forwardDigit, string rewindDigit, string pauseDigit)
|
||||
{
|
||||
this.forwardDigit = forwardDigit;
|
||||
this.rewindDigit = rewindDigit;
|
||||
this.pauseDigit = pauseDigit;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildCommand()
|
||||
public override string BuildCommand()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("CONTROL STREAM FILE ");
|
||||
sb.Append(EscapeAndQuote(file) + " " + EscapeAndQuote(escapeDigits));
|
||||
if (offset >= 0)
|
||||
sb.Append(" " + offset.ToString());
|
||||
else if (forwardDigit != null || rewindDigit != null || pauseDigit != null)
|
||||
sb.Append(" 0");
|
||||
if (forwardDigit != null || rewindDigit != null || pauseDigit != null)
|
||||
sb.Append(" " + forwardDigit);
|
||||
if (rewindDigit != null || pauseDigit != null)
|
||||
sb.Append(" " + rewindDigit);
|
||||
if (pauseDigit != null)
|
||||
sb.Append(" " + pauseDigit);
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Deletes a family or specific keytree within a family in the Asterisk database.<br/>
|
||||
/// Returns 1 if successful, 0 otherwise.
|
||||
/// </summary>
|
||||
public class DatabaseDelCommand : AGICommand
|
||||
{
|
||||
/// <summary> The family (or family of the keytree) to delete.</summary>
|
||||
private string family;
|
||||
/// <summary> The keyTree to delete.</summary>
|
||||
private string keyTree;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the family (or family of the keytree) to delete.
|
||||
/// </summary>
|
||||
public string Family
|
||||
{
|
||||
get { return family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the the keytree to delete.
|
||||
/// </summary>
|
||||
public string KeyTree
|
||||
{
|
||||
get { return keyTree; }
|
||||
set { this.keyTree = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DatabaseDelCommand to delete a family.
|
||||
/// </summary>
|
||||
/// <param name="family">the family to delete.</param>
|
||||
public DatabaseDelCommand(string family)
|
||||
{
|
||||
this.family = family;
|
||||
this.keyTree = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DatabaseDelCommand to delete a keytree.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the keytree to delete.</param>
|
||||
/// <param name="keyTree">the keytree to delete.</param>
|
||||
public DatabaseDelCommand(string family, string keyTree)
|
||||
{
|
||||
this.family = family;
|
||||
this.keyTree = keyTree;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "DATABASE DELTREE " + EscapeAndQuote(family) + (keyTree == null?"":" " + EscapeAndQuote(keyTree));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Deletes an entry in the Asterisk database for a given family and key.<br/>
|
||||
/// Returns 1 if successful, 0 otherwise.
|
||||
/// </summary>
|
||||
public class DatabaseDelTreeCommand : AGICommand
|
||||
{
|
||||
/// <summary> The family of the key to delete.</summary>
|
||||
private string family;
|
||||
/// <summary> The key to delete.</summary>
|
||||
private string keyTree;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the family of the key to delete.
|
||||
/// </summary>
|
||||
public string Family
|
||||
{
|
||||
get { return family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the the key to delete.
|
||||
/// </summary>
|
||||
public string KeyTree
|
||||
{
|
||||
get { return keyTree; }
|
||||
set { this.keyTree = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new DatabaseDelCommand.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key to delete.</param>
|
||||
/// <param name="key">the key to delete.</param>
|
||||
public DatabaseDelTreeCommand(string family)
|
||||
{
|
||||
this.family = family;
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new DatabaseDelCommand.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key to delete.</param>
|
||||
/// <param name="keytree">the key to delete.</param>
|
||||
public DatabaseDelTreeCommand(string family, string keytree)
|
||||
{
|
||||
this.family = family;
|
||||
this.keyTree = keytree;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
if (family != null)
|
||||
{
|
||||
if (keyTree != null)
|
||||
{
|
||||
return "DATABASE DELTREE " + EscapeAndQuote(family) + " " + EscapeAndQuote(keyTree);
|
||||
}
|
||||
return "DATABASE DELTREE " + EscapeAndQuote(family);
|
||||
}
|
||||
throw new ArgumentNullException("Family");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves an entry in the Asterisk database for a given family and key.<br/>
|
||||
/// Returns 0 if is not set. Returns 1 if the variable is set and returns the
|
||||
/// value in parenthesis.<br/>
|
||||
/// Example return code: 200 result=1 (testvariable)
|
||||
/// </summary>
|
||||
public class DatabaseGetCommand : AGICommand
|
||||
{
|
||||
/// <summary> The family of the key to retrieve.</summary>
|
||||
private string family;
|
||||
/// <summary> The key to retrieve.</summary>
|
||||
private string varKey;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set
|
||||
/// </summary>
|
||||
public string Family
|
||||
{
|
||||
get { return family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the the key to retrieve.
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return varKey; }
|
||||
set { this.varKey = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DatabaseGetCommand.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key to retrieve.</param>
|
||||
/// <param name="key">the key to retrieve.</param>
|
||||
public DatabaseGetCommand(string family, string key)
|
||||
{
|
||||
this.family = family;
|
||||
this.varKey = key;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "DATABASE GET " + EscapeAndQuote(family) + " " + EscapeAndQuote(varKey);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds or updates an entry in the Asterisk database for a given family, key, and value.<br/>
|
||||
/// Returns 1 if successful, 0 otherwise.
|
||||
/// </summary>
|
||||
public class DatabasePutCommand : AGICommand
|
||||
{
|
||||
/// <summary> The family of the key to set.</summary>
|
||||
private string family;
|
||||
/// <summary> The key to set.</summary>
|
||||
private string varKey;
|
||||
/// <summary> The value to set.</summary>
|
||||
private string varValue;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the family of the key to set.
|
||||
/// </summary>
|
||||
public string Family
|
||||
{
|
||||
get { return family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the the key to set.
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return varKey; }
|
||||
set { this.varKey = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the value to set.
|
||||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get { return varValue; }
|
||||
set { this.varValue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DatabasePutCommand.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key to set.</param>
|
||||
/// <param name="key">the key to set.</param>
|
||||
/// <param name="value">the value to set.</param>
|
||||
public DatabasePutCommand(string family, string key, string value)
|
||||
{
|
||||
this.family = family;
|
||||
this.varKey = key;
|
||||
this.varValue = value;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "DATABASE PUT " + EscapeAndQuote(family) + " " + EscapeAndQuote(varKey) + " " + EscapeAndQuote(varValue);
|
||||
}
|
||||
}
|
||||
}
|
57
Asterisk.2013/Asterisk.NET/FastAGI/Command/ExecCommand.cs
Normal file
57
Asterisk.2013/Asterisk.NET/FastAGI/Command/ExecCommand.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes an application with the given options.<br/>
|
||||
/// Returns whatever the application returns, or -2 if the application was not found.
|
||||
/// </summary>
|
||||
public class ExecCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the application to execute.</summary>
|
||||
private string application;
|
||||
/// <summary> The options to pass to the application.</summary>
|
||||
private string options;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the application to execute.
|
||||
/// </summary>
|
||||
public string Application
|
||||
{
|
||||
get { return application; }
|
||||
set { this.application = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the options to pass to the application.
|
||||
/// </summary>
|
||||
public string Options
|
||||
{
|
||||
get { return options; }
|
||||
set { this.options = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ExecCommand.
|
||||
/// </summary>
|
||||
/// <param name="application">the name of the application to execute.</param>
|
||||
public ExecCommand(string application)
|
||||
{
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ExecCommand.
|
||||
/// </summary>
|
||||
/// <param name="application">the name of the application to execute.</param>
|
||||
/// <param name="options">the options to pass to the application.</param>
|
||||
public ExecCommand(string application, string options)
|
||||
{
|
||||
this.application = application;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "EXEC " + EscapeAndQuote(application) + " " + EscapeAndQuote(options);
|
||||
}
|
||||
}
|
||||
}
|
109
Asterisk.2013/Asterisk.NET/FastAGI/Command/GetDataCommand.cs
Normal file
109
Asterisk.2013/Asterisk.NET/FastAGI/Command/GetDataCommand.cs
Normal file
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Stream the given file, and recieve DTMF data. The user may interrupt the streaming by starting to enter digits.<br/>
|
||||
/// Returns the digits recieved from the channel at the other end.<br/>
|
||||
/// Input ends when the timeout is reached, the maximum number of digits is read or the user presses #.
|
||||
/// </summary>
|
||||
public class GetDataCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the file to stream.</summary>
|
||||
private string file;
|
||||
/// <summary> The timeout in milliseconds to wait for data.<br/>
|
||||
/// 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out).
|
||||
/// </summary>
|
||||
private long timeout;
|
||||
|
||||
/// <summary> The maximum number of digits to read.<br/>
|
||||
/// Must be in [1..1024].
|
||||
/// </summary>
|
||||
private int maxDigits;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to stream. Must not include extension.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the timeout in milliseconds to wait for data. 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out).
|
||||
/// </summary>
|
||||
public long Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the maximum number of digits to read. The maximum number of digits to read. Must be in [1..1024].
|
||||
/// </summary>
|
||||
/// <throws> IllegalArgumentException if maxDigits is not in [1..1024] </throws>
|
||||
public int MaxDigits
|
||||
{
|
||||
get { return maxDigits; }
|
||||
set
|
||||
{
|
||||
if (value < 1 || value > 1024)
|
||||
throw new ArgumentException("maxDigits must be in [1..1024]");
|
||||
this.maxDigits = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetDataCommand with default timeout and maxDigits set to 1024.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
public GetDataCommand(string file)
|
||||
{
|
||||
this.file = file;
|
||||
this.timeout = Common.AGI_DEFAULT_TIMEOUT;
|
||||
this.maxDigits = Common.AGI_DEFAULT_MAX_DIGITS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetDataCommand with the given timeout and maxDigits set to 1024.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="timeout">the timeout in milliseconds to wait for data.<br/>
|
||||
/// 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out).
|
||||
/// </param>
|
||||
public GetDataCommand(string file, long timeout)
|
||||
{
|
||||
this.file = file;
|
||||
this.timeout = timeout;
|
||||
this.maxDigits = Common.AGI_DEFAULT_MAX_DIGITS;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetDataCommand with the given timeout and maxDigits.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="timeout">the timeout in milliseconds to wait for data.<br/>
|
||||
/// 0 means standard timeout value, -1 means "ludicrous time" (essentially never times out).
|
||||
/// </param>
|
||||
/// <param name="maxDigits">the maximum number of digits to read.<br/>
|
||||
/// Must be in [1..1024].
|
||||
/// </param>
|
||||
/// <throws> IllegalArgumentException if maxDigits is not in [1..1024] </throws>
|
||||
public GetDataCommand(string file, long timeout, int maxDigits)
|
||||
{
|
||||
this.file = file;
|
||||
this.timeout = timeout;
|
||||
this.MaxDigits = maxDigits;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
if (maxDigits == Common.AGI_DEFAULT_MAX_DIGITS)
|
||||
{
|
||||
if (timeout == Common.AGI_DEFAULT_TIMEOUT)
|
||||
return "GET DATA " + EscapeAndQuote(file);
|
||||
else
|
||||
return "GET DATA " + EscapeAndQuote(file) + " " + timeout;
|
||||
}
|
||||
return "GET DATA " + EscapeAndQuote(file) + " " + timeout + " " + maxDigits;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the value of the given channel varible and understands complex
|
||||
/// variable names and builtin variables, unlike the GetVariableCommand.<br/>
|
||||
/// You can also use this command to use custom Asterisk functions. Syntax is "func(args)".<br/>
|
||||
/// Returns 0 if the variable is not set or channel does not exist. Returns 1 if
|
||||
/// the variable is set and returns the variable in parenthesis.<br/>
|
||||
/// Example return code: 200 result=1 (testvariable)
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
public class GetFullVariableCommand : AGICommand
|
||||
{
|
||||
private string varName;
|
||||
private string channel;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetFullVariableCommand.
|
||||
/// </summary>
|
||||
/// <param name="variable">the name of the variable to retrieve.</param>
|
||||
public GetFullVariableCommand(string variable)
|
||||
{
|
||||
this.varName = variable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetFullVariableCommand.
|
||||
/// </summary>
|
||||
/// <param name="variable">the name of the variable to retrieve.</param>
|
||||
/// <param name="channel">the name of the channel.</param>
|
||||
public GetFullVariableCommand(string variable, string channel)
|
||||
{
|
||||
this.varName = variable;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the variable to retrieve.
|
||||
/// </summary>
|
||||
public string Variable
|
||||
{
|
||||
get { return varName; }
|
||||
set { this.varName = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the channel.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
StringBuilder sb;
|
||||
|
||||
sb = new StringBuilder("GET FULL VARIABLE ");
|
||||
sb.Append(EscapeAndQuote(varName));
|
||||
|
||||
if (channel != null)
|
||||
{
|
||||
sb.Append(" ");
|
||||
sb.Append(EscapeAndQuote(channel));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Plays the given file, and waits for the user to press one of the given
|
||||
/// digits. If none of the esacpe digits is pressed while streaming the file this
|
||||
/// command waits for the specified timeout still waiting for the user to press a
|
||||
/// digit. Streaming always begins at the beginning.<br/>
|
||||
/// Returns 0 if no digit being pressed, or the ASCII numerical value of the
|
||||
/// digit if one was pressed, or -1 on error or if the channel was disconnected.
|
||||
/// <br/>
|
||||
/// Remember, the file extension must not be included in the filename.
|
||||
/// </summary>
|
||||
/// <seealso cref="FastAGI.Command.StreamFileCommand" />
|
||||
public class GetOptionCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the file to stream.</summary>
|
||||
private string file;
|
||||
/// <summary> When one of these digits is pressed while streaming the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
/// <summary> The timeout in seconds.</summary>
|
||||
private int timeout;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to stream.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digits that the user is expected to press.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the timeout to wait if none of the defined esacpe digits was presses while streaming.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetOptionCommand with a default timeout of 5 seconds.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that the user is expected to press.</param>
|
||||
public GetOptionCommand(string file, string escapeDigits)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.timeout = - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetOptionCommand with the given timeout.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that the user is expected to press.</param>
|
||||
/// <param name="timeout">the timeout in seconds to wait if none of the defined esacpe digits was presses while streaming.</param>
|
||||
public GetOptionCommand(string file, string escapeDigits, int timeout)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "GET OPTION " + EscapeAndQuote(file) + " " + EscapeAndQuote(escapeDigits) + (timeout < 0?"":" " + timeout);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the value of the given channel varible.<br/>
|
||||
/// Since Asterisk 1.2 you can also use this command to use custom Asterisk functions. Syntax is "func(args)".<br/>
|
||||
/// Returns 0 if the variable is not set. Returns 1 if the variable is set and returns the variable in parenthesis.<br/>
|
||||
/// Example return code: 200 result=1 (testvariable)
|
||||
/// </summary>
|
||||
public class GetVariableCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the variable to retrieve.</summary>
|
||||
private string varName;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the variable to retrieve.<br>
|
||||
/// Since Asterisk 1.2 you can also use custom dialplan functions (like "func(args)") as variable.
|
||||
/// </summary>
|
||||
public string Variable
|
||||
{
|
||||
get { return varName; }
|
||||
set { this.varName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetVariableCommand.
|
||||
/// </summary>
|
||||
/// <param name="variable">the name of the variable to retrieve.</param>
|
||||
public GetVariableCommand(string variable)
|
||||
{
|
||||
this.varName = variable;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "GET VARIABLE " + EscapeAndQuote(varName);
|
||||
}
|
||||
}
|
||||
}
|
47
Asterisk.2013/Asterisk.NET/FastAGI/Command/HangupCommand.cs
Normal file
47
Asterisk.2013/Asterisk.NET/FastAGI/Command/HangupCommand.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Hangs up the specified channel. If no channel name is given, hangs up the current channel.
|
||||
/// </summary>
|
||||
public class HangupCommand : AGICommand
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The name of the channel to hangup or <code>null</code> for the current channel.
|
||||
/// </summary>
|
||||
private string channel;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the name of the channel to hangup.
|
||||
/// </summary>
|
||||
/// <returns>the name of the channel to hangup or <code>null</code> for the current channel.</returns>
|
||||
/// <summary> Sets the name of the channel to hangup.</summary>
|
||||
/// <param name="channel">the name of the channel to hangup or <code>null</code> for the current channel.</param>
|
||||
public string Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
|
||||
/// <summary> Creates a new HangupCommand that hangs up the current channel.</summary>
|
||||
public HangupCommand()
|
||||
{
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new HangupCommand that hangs up the given channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to hangup.</param>
|
||||
public HangupCommand(string channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "HANGUP" + (channel == null ? "" : " " + EscapeAndQuote(channel));
|
||||
}
|
||||
}
|
||||
}
|
20
Asterisk.2013/Asterisk.NET/FastAGI/Command/NoopCommand.cs
Normal file
20
Asterisk.2013/Asterisk.NET/FastAGI/Command/NoopCommand.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Does nothing.
|
||||
/// </summary>
|
||||
public class NoopCommand : AGICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new NoopCommand.
|
||||
/// </summary>
|
||||
public NoopCommand()
|
||||
{
|
||||
}
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "NOOP";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Receives a character of text on a channel.<br/>
|
||||
/// Specify timeout to be the maximum time to wait for input in milliseconds, or 0 for infinite.<br/>
|
||||
/// Most channels do not support the reception of text.<br/>
|
||||
/// Returns the decimal value of the character if one is received, or 0 if the
|
||||
/// channel does not support text reception. Returns -1 only on error/hangup.
|
||||
/// </summary>
|
||||
public class ReceiveCharCommand : AGICommand
|
||||
{
|
||||
/// <summary> The milliseconds to wait for the channel to receive a character.</summary>
|
||||
private int timeout;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the milliseconds to wait for the channel to receive a character.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ReceiveCharCommand with a default timeout of 0 meaning to wait for ever.
|
||||
/// </summary>
|
||||
public ReceiveCharCommand()
|
||||
{
|
||||
this.timeout = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ReceiveCharCommand.
|
||||
/// </summary>
|
||||
/// <param name="timeout">the milliseconds to wait for the channel to receive a character.</param>
|
||||
public ReceiveCharCommand(int timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "RECEIVE CHAR " + timeout;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Receives a string of text on a channel.<br/>
|
||||
/// Specify timeout to be the maximum time to wait for input in milliseconds, or
|
||||
/// 0 for infinite.<br/>
|
||||
/// Most channels do not support the reception of text.<br/>
|
||||
/// Returns -1 for failure or 1 for success, and the string in parentheses.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
public class ReceiveTextCommand : AGICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// The milliseconds to wait for the channel to receive a character.
|
||||
/// </summary>
|
||||
private int timeout;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ReceiveTextCommand with a default timeout of 0 meaning to wait for ever.
|
||||
/// </summary>
|
||||
public ReceiveTextCommand()
|
||||
{
|
||||
this.timeout = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ReceiveTextCommand.
|
||||
/// <param name=timeout>the milliseconds to wait for the channel to receive the text.</param>
|
||||
/// </summary>
|
||||
public ReceiveTextCommand(int timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the milliseconds to wait for the channel to receive the text.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "RECEIVE TEXT " + timeout;
|
||||
}
|
||||
}
|
||||
}
|
143
Asterisk.2013/Asterisk.NET/FastAGI/Command/RecordFileCommand.cs
Normal file
143
Asterisk.2013/Asterisk.NET/FastAGI/Command/RecordFileCommand.cs
Normal file
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Record to a file until a given dtmf digit in the sequence is received.<br/>
|
||||
/// Returns -1 on hangup or error.<br/>
|
||||
/// The format will specify what kind of file will be recorded. The timeout is
|
||||
/// the maximum record time in milliseconds, or -1 for no timeout. Offset samples
|
||||
/// is optional, and if provided will seek to the offset without exceeding the
|
||||
/// end of the file. "maxSilence" is the number of seconds of maxSilence allowed
|
||||
/// before the function returns despite the lack of dtmf digits or reaching
|
||||
/// timeout.
|
||||
/// </summary>
|
||||
public class RecordFileCommand : AGICommand
|
||||
{
|
||||
#region Variables
|
||||
/// <summary> The name of the file to record.</summary>
|
||||
private string file;
|
||||
/// <summary> The format of the file to be recorded, for example "wav".</summary>
|
||||
private string format;
|
||||
/// <summary> The these digits a user can press to end the recording.</summary>
|
||||
private string escapeDigits;
|
||||
/// <summary> The maximum record time in milliseconds, or -1 for no timeout.</summary>
|
||||
private int timeout;
|
||||
/// <summary> The offset samples to skip.</summary>
|
||||
private int offset;
|
||||
/// <summary> Wheather a beep should be played before recording.</summary>
|
||||
private bool beep;
|
||||
/// <summary> The amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout.</summary>
|
||||
private int maxSilence;
|
||||
#endregion
|
||||
|
||||
#region File
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to stream.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Format
|
||||
/// <summary>
|
||||
/// Get/Set the format of the file to be recorded, for example "wav".
|
||||
/// </summary>
|
||||
public string Format
|
||||
{
|
||||
get { return format; }
|
||||
set { this.format = value; }
|
||||
}
|
||||
#endregion
|
||||
#region EscapeDigits
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to end recording.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Timeout
|
||||
/// <summary>
|
||||
/// Get/Set the maximum record time in milliseconds, or -1 for no timeout.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Offset
|
||||
/// <summary>
|
||||
/// Get/Set the offset samples to skip.
|
||||
/// </summary>
|
||||
public int Offset
|
||||
{
|
||||
get { return offset; }
|
||||
set { this.offset = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Beep
|
||||
/// <summary>
|
||||
/// Get/Set <code>true</code> if a beep should be played before recording. <code>false</code> if not.
|
||||
/// </summary>
|
||||
public bool Beep
|
||||
{
|
||||
get { return beep; }
|
||||
set { this.beep = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - RecordFileCommand(string file, string format, string escapeDigits, int timeout)
|
||||
/// <summary>
|
||||
/// Creates a new RecordFileCommand.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="format">the format of the file to be recorded, for example "wav".</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to end recording.</param>
|
||||
/// <param name="timeout">the maximum record time in milliseconds, or -1 for no timeout.</param>
|
||||
public RecordFileCommand(string file, string format, string escapeDigits, int timeout)
|
||||
{
|
||||
this.file = file;
|
||||
this.format = format;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.timeout = timeout;
|
||||
this.offset = 0;
|
||||
this.beep = false;
|
||||
this.maxSilence = 0;
|
||||
}
|
||||
#endregion
|
||||
#region Constructor - RecordFileCommand(string file, string format, string escapeDigits, int timeout)
|
||||
/// <summary>
|
||||
/// Creates a new RecordFileCommand.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="format">the format of the file to be recorded, for example "wav".</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to end recording.</param>
|
||||
/// <param name="timeout">the maximum record time in milliseconds, or -1 for no timeout.</param>
|
||||
/// <param name="offset">the offset samples to skip.</param>
|
||||
/// <param name="beep"><code>true</code> if a beep should be played before recording.</param>
|
||||
/// <param name="maxSilence">The amount of silence (in seconds) to allow before returning despite the lack of dtmf digits or reaching timeout.</param>
|
||||
public RecordFileCommand(string file, string format, string escapeDigits, int timeout, int offset, bool beep, int maxSilence)
|
||||
{
|
||||
this.file = file;
|
||||
this.format = format;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.timeout = timeout;
|
||||
this.offset = offset;
|
||||
this.beep = beep;
|
||||
this.maxSilence = maxSilence;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildCommand()
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "RECORD FILE " + EscapeAndQuote(file) + " " + EscapeAndQuote(format) + " " + EscapeAndQuote(escapeDigits) + " " + timeout + " " + offset + (beep == true?" BEEP":"") + " s=" + maxSilence;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary> Say a given character string, returning early if any of the given DTMF digits are received on the channel.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed or -1 on error/hangup.
|
||||
/// </summary>
|
||||
public class SayAlphaCommand : AGICommand
|
||||
{
|
||||
/// <summary> The text to say.</summary>
|
||||
private string text;
|
||||
/// <summary> When one of these digits is pressed the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set Returns the text to say.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { this.text = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayAlphaCommand.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
public SayAlphaCommand(string text)
|
||||
{
|
||||
this.text = text;
|
||||
this.escapeDigits = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayAlphaCommand.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
public SayAlphaCommand(string text, string escapeDigits)
|
||||
{
|
||||
this.text = text;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SAY ALPHA " + EscapeAndQuote(text) + " " + EscapeAndQuote(escapeDigits);
|
||||
}
|
||||
}
|
||||
}
|
133
Asterisk.2013/Asterisk.NET/FastAGI/Command/SayDateTimeCommand.cs
Normal file
133
Asterisk.2013/Asterisk.NET/FastAGI/Command/SayDateTimeCommand.cs
Normal file
|
@ -0,0 +1,133 @@
|
|||
using System.Text;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Say a given time, returning early if any of the given DTMF digits are pressed.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed or -1 on error/hangup.<br/>
|
||||
/// Available since Asterisk 1.2.
|
||||
/// </summary>
|
||||
public class SayDateTimeCommand : AGICommand
|
||||
{
|
||||
private static string DEFAULT_FORMAT = "ABdY 'digits/at' IMp";
|
||||
|
||||
private long time;
|
||||
private string escapeDigits;
|
||||
private string format;
|
||||
private string timezone;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayDateTimeCommand that says the given time.
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// </summary>
|
||||
public SayDateTimeCommand(long time)
|
||||
{
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayDateTimeCommand that says the given time and allows interruption by one of the given escape digits.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
public SayDateTimeCommand(long time, string escapeDigits)
|
||||
{
|
||||
this.time = time;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayDateTimeCommand that says the given time in the given
|
||||
/// format and allows interruption by one of the given escape digits.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
/// <param name="format">the format the time should be said in</param>
|
||||
public SayDateTimeCommand(long time, string escapeDigits, string format)
|
||||
{
|
||||
this.time = time;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayDateTimeCommand that says the given time in the given
|
||||
/// format and timezone and allows interruption by one of the given escape
|
||||
/// digits.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC)</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command or <code>null</code> for none.</param>
|
||||
/// <param name="format">the format the time should be said in</param>
|
||||
/// <param name="timezone">the timezone to use when saying the time, for example "UTC" or "Europe/Berlin".</param>
|
||||
public SayDateTimeCommand(long time, string escapeDigits, string format, string timezone)
|
||||
{
|
||||
this.time = time;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.format = format;
|
||||
this.timezone = timezone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the time to say in seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
|
||||
/// </summary>
|
||||
public long Time
|
||||
{
|
||||
get { return this.time; }
|
||||
set { this.time = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string getEscapeDigits
|
||||
{
|
||||
get { return this.escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the format the time should be said in.
|
||||
/// </summary>
|
||||
public string Format
|
||||
{
|
||||
get { return this.format; }
|
||||
set { this.format = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the timezone to use when saying the time.
|
||||
/// </summary>
|
||||
public string Timezone
|
||||
{
|
||||
get { return this.timezone; }
|
||||
set { this.timezone = value; }
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("SAY DATETIME ");
|
||||
sb.Append(time);
|
||||
sb.Append(" ");
|
||||
sb.Append(EscapeAndQuote(escapeDigits));
|
||||
|
||||
if (format == null && timezone != null)
|
||||
{
|
||||
sb.Append(" ");
|
||||
sb.Append(EscapeAndQuote(DEFAULT_FORMAT));
|
||||
}
|
||||
if (format != null)
|
||||
{
|
||||
sb.Append(" ");
|
||||
sb.Append(EscapeAndQuote(format));
|
||||
}
|
||||
|
||||
if (timezone != null)
|
||||
{
|
||||
sb.Append(" ");
|
||||
sb.Append(EscapeAndQuote(timezone));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Say a given digit string, returning early if any of the given DTMF digits are received on the channel.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed,
|
||||
/// or the ASCII numerical value of the digit if one was pressed or -1 on error/hangup.
|
||||
/// </summary>
|
||||
public class SayDigitsCommand : AGICommand
|
||||
{
|
||||
#region Variables
|
||||
/// <summary> The digits string to say.</summary>
|
||||
private string digits;
|
||||
/// <summary> When one of these digits is pressed while saying the digits the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
#endregion
|
||||
|
||||
#region Digits
|
||||
/// <summary>
|
||||
/// Get/Set the digits string to say.
|
||||
/// </summary>
|
||||
public string Digits
|
||||
{
|
||||
get { return digits; }
|
||||
set { this.digits = value; }
|
||||
}
|
||||
#endregion
|
||||
#region EscapeDigits
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - SayDigitsCommand(string digits)
|
||||
/// <summary>
|
||||
/// Creates a new SayDigitsCommand.
|
||||
/// </summary>
|
||||
/// <param name="digits">the digits to say.</param>
|
||||
public SayDigitsCommand(string digits)
|
||||
{
|
||||
this.digits = digits;
|
||||
this.escapeDigits = null;
|
||||
}
|
||||
#endregion
|
||||
#region Constructor - SayDigitsCommand(string digits, string escapeDigits)
|
||||
/// <summary>
|
||||
/// Creates a new SayDigitsCommand.
|
||||
/// </summary>
|
||||
/// <param name="digits">the digits to say.</param>
|
||||
/// <param name="escapeDigits">the digits that allow the user to interrupt this command.</param>
|
||||
public SayDigitsCommand(string digits, string escapeDigits)
|
||||
{
|
||||
this.digits = digits;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildCommand()
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SAY DIGITS " + EscapeAndQuote(digits) + " " + EscapeAndQuote(escapeDigits);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Say a given number, returning early if any of the given DTMF number are received on the channel.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed or -1 on error/hangup.
|
||||
/// </summary>
|
||||
public class SayNumberCommand : AGICommand
|
||||
{
|
||||
/// <summary> The number to say.</summary>
|
||||
private string number;
|
||||
/// <summary> When one of these number is pressed while streaming the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the number to say.
|
||||
/// </summary>
|
||||
public string Number
|
||||
{
|
||||
get { return number; }
|
||||
set { this.number = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the number that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayNumberCommand.
|
||||
/// </summary>
|
||||
/// <param name="number">the number to say.</param>
|
||||
public SayNumberCommand(string number)
|
||||
{
|
||||
this.number = number;
|
||||
this.escapeDigits = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayNumberCommand.
|
||||
/// </summary>
|
||||
/// <param name="number">the number to say.</param>
|
||||
/// <param name="escapeDigits">contains the number that allow the user to interrupt this command.</param>
|
||||
public SayNumberCommand(string number, string escapeDigits)
|
||||
{
|
||||
this.number = number;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SAY NUMBER " + EscapeAndQuote(number) + " " + EscapeAndQuote(escapeDigits);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Say a given character string with phonetics, returning early if any of the given DTMF digits are received on the channel.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed or -1 on error/hangup.
|
||||
/// </summary>
|
||||
public class SayPhoneticCommand : AGICommand
|
||||
{
|
||||
/// <summary> The text to say.</summary>
|
||||
private string text;
|
||||
/// <summary> When one of these digits is pressed the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the text to say.
|
||||
/// </summary>
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { this.text = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayPhonticCommand.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
public SayPhoneticCommand(string text)
|
||||
{
|
||||
this.text = text;
|
||||
this.escapeDigits = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayPhoneticCommand.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to say.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
public SayPhoneticCommand(string text, string escapeDigits)
|
||||
{
|
||||
this.text = text;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SAY PHONETIC " + EscapeAndQuote(text) + " " + EscapeAndQuote(escapeDigits);
|
||||
}
|
||||
}
|
||||
}
|
60
Asterisk.2013/Asterisk.NET/FastAGI/Command/SayTimeCommand.cs
Normal file
60
Asterisk.2013/Asterisk.NET/FastAGI/Command/SayTimeCommand.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Say a given time, returning early if any of the given DTMF digits are received on the channel.<br/>
|
||||
/// Time is the number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed or -1 on error/hangup.
|
||||
/// </summary>
|
||||
public class SayTimeCommand : AGICommand
|
||||
{
|
||||
/// <summary> The time to say in seconds since 00:00:00 on January 1, 1970.</summary>
|
||||
private long time;
|
||||
/// <summary> When one of these digits is pressed the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the time to say in seconds since 00:00:00 on January 1, 1970.
|
||||
/// </summary>
|
||||
public long Time
|
||||
{
|
||||
get { return time; }
|
||||
set { this.time = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get { return escapeDigits; }
|
||||
set { this.escapeDigits = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayTimeCommand.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds since 00:00:00 on January 1, 1970.</param>
|
||||
public SayTimeCommand(long time)
|
||||
{
|
||||
this.time = time;
|
||||
this.escapeDigits = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SayTimeCommand.
|
||||
/// </summary>
|
||||
/// <param name="time">the time to say in seconds since 00:00:00 on January 1, 1970.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
public SayTimeCommand(long time, string escapeDigits)
|
||||
{
|
||||
this.time = time;
|
||||
this.escapeDigits = escapeDigits;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SAY TIME " + time + " " + EscapeAndQuote(escapeDigits);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends the given image on a channel.<br/>
|
||||
/// Most channels do not support the transmission of images.<br/>
|
||||
/// Returns 0 if image is sent, or if the channel does not support image
|
||||
/// transmission. Returns -1 only on error/hangup.<br/>
|
||||
/// Image names should not include extensions.
|
||||
/// </summary>
|
||||
public class SendImageCommand : AGICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/Set the image to send.
|
||||
/// </summary>
|
||||
/// <param name="image">the image to send, should not include extension.</param>
|
||||
/// <returns> the image to send.</returns>
|
||||
public string Image
|
||||
{
|
||||
get { return image; }
|
||||
set { this.image = value; }
|
||||
}
|
||||
|
||||
/// <summary> The name of the image to send.</summary>
|
||||
private string image;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SendImageCommand.
|
||||
/// </summary>
|
||||
/// <param name="image">the image to send, should not include extension.</param>
|
||||
public SendImageCommand(string image)
|
||||
{
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SEND IMAGE " + EscapeAndQuote(image);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends the given text on a channel.<br/>
|
||||
/// Most channels do not support the transmission of text.<br/>
|
||||
/// Returns 0 if text is sent, or if the channel does not support text
|
||||
/// transmission. Returns -1 only on error/hangup.
|
||||
/// </summary>
|
||||
public class SendTextCommand : AGICommand
|
||||
{
|
||||
/// <summary> The text to send.</summary>
|
||||
private string text;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the text to send.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to send.</param>
|
||||
/// <returns>the text to send.</returns>
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { this.text = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SendTextCommand.
|
||||
/// </summary>
|
||||
/// <param name="text">the text to send.</param>
|
||||
public SendTextCommand(string text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SEND TEXT " + EscapeAndQuote(text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Cause the channel to automatically hangup at the given number of seconds in the future.<br/>
|
||||
/// Of course it can be hungup before then as well. Setting to 0 will cause the
|
||||
/// autohangup feature to be disabled on this channel.
|
||||
/// </summary>
|
||||
public class SetAutoHangupCommand : AGICommand
|
||||
{
|
||||
/// <summary> The number of seconds before this channel is automatically hung up.</summary>
|
||||
private int time;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the number of seconds before this channel is automatically hung up.
|
||||
/// </summary>
|
||||
/// <returns>the number of seconds before this channel is automatically hung up.</returns>
|
||||
/// <param name="time">
|
||||
/// the number of seconds before this channel is automatically hung up.<br/>
|
||||
/// 0 disables the autohangup feature.
|
||||
/// </param>
|
||||
public int Time
|
||||
{
|
||||
get { return time; }
|
||||
set { this.time = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetAutoHangupCommand.
|
||||
/// </summary>
|
||||
/// <param name="time">
|
||||
/// the number of seconds before this channel is automatically hung up.<br/>
|
||||
/// 0 disables the autohangup feature.
|
||||
/// </param>
|
||||
public SetAutoHangupCommand(int time)
|
||||
{
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET AUTOHANGUP " + time;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Changes the CallerID of the current channel.
|
||||
/// </summary>
|
||||
public class SetCallerIdCommand : AGICommand
|
||||
{
|
||||
/// <summary> The new callerId.</summary>
|
||||
private string callerId;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the new callerId.
|
||||
/// </summary>
|
||||
public string CallerId
|
||||
{
|
||||
get { return callerId; }
|
||||
set { this.callerId = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetCallerIdCommand.
|
||||
/// </summary>
|
||||
/// <param name="callerId">the new callerId.</param>
|
||||
public SetCallerIdCommand(string callerId)
|
||||
{
|
||||
this.callerId = callerId;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET CALLERID " + EscapeAndQuote(callerId);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the context for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
public class SetContextCommand : AGICommand
|
||||
{
|
||||
/// <summary> The context for continuation upon exiting the application.</summary>
|
||||
private string context;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the context for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
public string Context
|
||||
{
|
||||
get { return context; }
|
||||
set { this.context = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetPriorityCommand.
|
||||
/// </summary>
|
||||
/// <param name="context">the context for continuation upon exiting the application.</param>
|
||||
public SetContextCommand(string context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET CONTEXT " + EscapeAndQuote(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the extension for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
public class SetExtensionCommand : AGICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/Set the extension for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
/// <returns>the extension for continuation upon exiting the application.</returns>
|
||||
/// <param name="extension">the extension for continuation upon exiting the application.</param>
|
||||
public string Extension
|
||||
{
|
||||
get { return extension; }
|
||||
set { this.extension = value; }
|
||||
}
|
||||
|
||||
/// <summary> The extension for continuation upon exiting the application.</summary>
|
||||
private string extension;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetPriorityCommand.
|
||||
/// </summary>
|
||||
/// <param name="extension">the extension for continuation upon exiting the application.</param>
|
||||
public SetExtensionCommand(string extension)
|
||||
{
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET EXTENSION " + EscapeAndQuote(extension);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Turns off music on hold on the current channel.<br/>
|
||||
/// Always returns 0.
|
||||
/// </summary>
|
||||
public class SetMusicOffCommand : AGICommand
|
||||
{
|
||||
/// <summary> Creates a new SetMusicOffCommand.</summary>
|
||||
public SetMusicOffCommand()
|
||||
{
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET MUSIC OFF";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Turns on music on hold on the current channel.<br/>
|
||||
/// Always returns 0.
|
||||
/// </summary>
|
||||
public class SetMusicOnCommand : AGICommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Get/Set the music on hold class to play music from.
|
||||
/// </summary>
|
||||
/// <returns>the music on hold class to play music from or <code>null</code> for the default class.</returns>
|
||||
/// <param name="musicOnHoldClass">the music on hold class to play music from or <code>null</code> for the default class.</param>
|
||||
public string MusicOnHoldClass
|
||||
{
|
||||
get { return musicOnHoldClass; }
|
||||
set { this.musicOnHoldClass = value; }
|
||||
}
|
||||
|
||||
/// <summary> The music on hold class to play music from.</summary>
|
||||
private string musicOnHoldClass;
|
||||
|
||||
/// <summary> Creates a new SetMusicOnCommand playing music from the default music on hold class.</summary>
|
||||
public SetMusicOnCommand()
|
||||
{
|
||||
this.musicOnHoldClass = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetMusicOnCommand playing music from the default music on hold class.
|
||||
/// </summary>
|
||||
/// <param name="musicOnHoldClass">the music on hold class to play music from.</param>
|
||||
public SetMusicOnCommand(string musicOnHoldClass)
|
||||
{
|
||||
this.musicOnHoldClass = musicOnHoldClass;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET MUSIC ON" + (musicOnHoldClass == null?"":" " + EscapeAndQuote(musicOnHoldClass));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the priority for continuation upon exiting the application.<br/>
|
||||
/// Since Asterisk 1.2 SetPriorityCommand also supports labels.
|
||||
/// </summary>
|
||||
public class SetPriorityCommand : AGICommand
|
||||
{
|
||||
/// <summary> The priority or label for continuation upon exiting the application.</summary>
|
||||
private string priorityOrLabel;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the priority or label for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
public int Priority
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Int32.Parse(this.priorityOrLabel);
|
||||
}
|
||||
catch {}
|
||||
return 0;
|
||||
}
|
||||
set { this.priorityOrLabel = value.ToString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the label for continuation upon exiting the application.
|
||||
/// </summary>
|
||||
public string Label
|
||||
{
|
||||
get { return this.priorityOrLabel; }
|
||||
set { this.priorityOrLabel = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetPriorityCommand.
|
||||
/// </summary>
|
||||
/// <param name="priority">the priority for continuation upon exiting the application.</param>
|
||||
public SetPriorityCommand(int priority)
|
||||
{
|
||||
this.priorityOrLabel = priority.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SetPriorityCommand.
|
||||
/// </summary>
|
||||
/// <param name="label">the label for continuation upon exiting the application.</param>
|
||||
public SetPriorityCommand(string label)
|
||||
{
|
||||
this.priorityOrLabel = label;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET PRIORITY " + EscapeAndQuote(priorityOrLabel);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the given channel variable to the given value.
|
||||
/// </summary>
|
||||
public class SetVariableCommand : AGICommand
|
||||
{
|
||||
/// <summary> The name of the variable to set.</summary>
|
||||
private string varName;
|
||||
/// <summary> The value to set.</summary>
|
||||
private string varValue;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the name of the variable to set.
|
||||
/// </summary>
|
||||
public string Variable
|
||||
{
|
||||
get { return varName; }
|
||||
set { this.varName = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the value to set.
|
||||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get { return varValue; }
|
||||
set { this.varValue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetVariableCommand.
|
||||
/// </summary>
|
||||
/// <param name="variable">the name of the variable to set.</param>
|
||||
/// <param name="value">the value to set.</param>
|
||||
public SetVariableCommand(string name, string value)
|
||||
{
|
||||
this.varName = name;
|
||||
this.varValue = value;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "SET VARIABLE " + EscapeAndQuote(varName) + " " + EscapeAndQuote(varValue);
|
||||
}
|
||||
}
|
||||
}
|
122
Asterisk.2013/Asterisk.NET/FastAGI/Command/StreamFileCommand.cs
Normal file
122
Asterisk.2013/Asterisk.NET/FastAGI/Command/StreamFileCommand.cs
Normal file
|
@ -0,0 +1,122 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Plays the given file, allowing playback to be interrupted by the given digits, if any.<br/>
|
||||
/// If offset is provided then the audio will seek to sample offset before play starts.<br/>
|
||||
/// Returns 0 if playback completes without a digit being pressed, or the ASCII
|
||||
/// numerical value of the digit if one was pressed, or -1 on error or if the
|
||||
/// channel was disconnected. <br/>
|
||||
/// Remember, the file extension must not be included in the filename.
|
||||
/// </summary>
|
||||
public class StreamFileCommand : AGICommand
|
||||
{
|
||||
#region File
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to stream.
|
||||
/// The name of the file to stream, must not include extension.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return file;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.file = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EscapeDigits
|
||||
/// <summary>
|
||||
/// Get/Set the digits that allow the user to interrupt this command.
|
||||
/// </summary>
|
||||
public string EscapeDigits
|
||||
{
|
||||
get
|
||||
{
|
||||
return escapeDigits;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.escapeDigits = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Offset
|
||||
/// <summary>
|
||||
/// Get/Set the offset samples to skip before streaming.
|
||||
/// </summary>
|
||||
public int Offset
|
||||
{
|
||||
get
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.offset = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary> The name of the file to stream.</summary>
|
||||
private string file;
|
||||
|
||||
/// <summary> When one of these digits is pressed while streaming the command returns.</summary>
|
||||
private string escapeDigits;
|
||||
|
||||
/// <summary> The offset samples to skip before streaming.</summary>
|
||||
private int offset;
|
||||
|
||||
/// <summary> Creates a new StreamFileCommand, streaming from the beginning.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.
|
||||
/// </param>
|
||||
public StreamFileCommand(string file)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = null;
|
||||
this.offset = - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new StreamFileCommand, streaming from the beginning.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.</param>
|
||||
public StreamFileCommand(string file, string escapeDigits)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new StreamFileCommand, streaming from the given offset.
|
||||
/// </summary>
|
||||
/// <param name="file">the name of the file to stream, must not include extension.</param>
|
||||
/// <param name="escapeDigits">contains the digits that allow the user to interrupt this command.
|
||||
/// Maybe <code>null</code> if you don't want the user to interrupt.
|
||||
/// </param>
|
||||
/// <param name="offset">the offset samples to skip before streaming.</param>
|
||||
public StreamFileCommand(string file, string escapeDigits, int offset)
|
||||
{
|
||||
this.file = file;
|
||||
this.escapeDigits = escapeDigits;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "STREAM FILE " + EscapeAndQuote(file) + " " + EscapeAndQuote(escapeDigits) + (offset < 0?"":" " + offset);
|
||||
}
|
||||
}
|
||||
}
|
40
Asterisk.2013/Asterisk.NET/FastAGI/Command/TDDModeCommand.cs
Normal file
40
Asterisk.2013/Asterisk.NET/FastAGI/Command/TDDModeCommand.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Enable/Disable TDD transmission/reception on a channel.<br/>
|
||||
/// Returns 1 if successful, or 0 if channel is not TDD-capable.
|
||||
/// </summary>
|
||||
public class TDDModeCommand : AGICommand
|
||||
{
|
||||
private string mode;
|
||||
|
||||
/// <summary>
|
||||
/// Get the mode to set.
|
||||
/// </summary>
|
||||
public string Mode
|
||||
{
|
||||
get { return mode; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the mode to set. The mode to set, this can be one of "on", "off", "mate" or "tdd".
|
||||
/// </summary>
|
||||
public string Timeout
|
||||
{
|
||||
set { this.mode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new TDDModeCommand. The mode to set, this can be one of "on", "off", "mate" or "tdd".
|
||||
/// </summary>
|
||||
public TDDModeCommand(string mode)
|
||||
{
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "TDD MODE " + EscapeAndQuote(mode);
|
||||
}
|
||||
}
|
||||
}
|
71
Asterisk.2013/Asterisk.NET/FastAGI/Command/VerboseCommand.cs
Normal file
71
Asterisk.2013/Asterisk.NET/FastAGI/Command/VerboseCommand.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
#region Class - VerboseCommand
|
||||
/// <summary>
|
||||
/// Sends a message to the console via the verbose message system.<br/>
|
||||
/// Always returns 1.
|
||||
/// </summary>
|
||||
public class VerboseCommand : AGICommand
|
||||
{
|
||||
#region Variables
|
||||
/// <summary> The message to send.</summary>
|
||||
private string message;
|
||||
/// <summary> The verbosity level to use.<br/>
|
||||
/// Must be in [1..4]
|
||||
/// </summary>
|
||||
private int level;
|
||||
#endregion
|
||||
|
||||
#region Message
|
||||
/// <summary>
|
||||
/// Get/Set the message to send.
|
||||
/// </summary>
|
||||
public string Message
|
||||
{
|
||||
get { return message; }
|
||||
set { this.message = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Level
|
||||
/// <summary>
|
||||
/// Get/Set the level to use.
|
||||
/// </summary>
|
||||
/// <throws> IllegalArgumentException if level is not in [1..4] </throws>
|
||||
public int Level
|
||||
{
|
||||
get { return level; }
|
||||
set
|
||||
{
|
||||
if (value < 1 || value > 4)
|
||||
{
|
||||
throw new ArgumentException("level must be in [1..4]");
|
||||
}
|
||||
this.level = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - VerboseCommand(string message, int level)
|
||||
/// <summary>
|
||||
/// Creates a new VerboseCommand.
|
||||
/// </summary>
|
||||
/// <param name="message">the message to send.</param>
|
||||
/// <param name="level">the verbosity level to use. Must be in [1..4]</param>
|
||||
/// <throws> IllegalArgumentException if level is not in [1..4] </throws>
|
||||
public VerboseCommand(string message, int level)
|
||||
{
|
||||
this.Message = message;
|
||||
this.Level = level;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildCommand()
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "VERBOSE " + EscapeAndQuote(message) + " " + level;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
namespace Asterisk.NET.FastAGI.Command
|
||||
{
|
||||
/// <summary>
|
||||
/// Waits up to 'timeout' milliseconds for channel to receive a DTMF digit.<br/>
|
||||
/// Returns -1 on channel failure, 0 if no digit is received in the timeout, or
|
||||
/// the numerical value of the ascii of the digit if one is received. Use -1 for
|
||||
/// the timeout value if you desire the call to block indefinitely.
|
||||
/// </summary>
|
||||
public class WaitForDigitCommand : AGICommand
|
||||
{
|
||||
/// <summary> The milliseconds to wait for the channel to receive a DTMF digit.</summary>
|
||||
private long timeout;
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the milliseconds to wait for the channel to receive a DTMF digit.
|
||||
/// </summary>
|
||||
public long Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new WaitForDigitCommand with a default timeout of -1 which blocks the channel indefinitely.
|
||||
/// </summary>
|
||||
public WaitForDigitCommand()
|
||||
{
|
||||
this.timeout = - 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new WaitForDigitCommand.
|
||||
/// </summary>
|
||||
/// <param name="timeout">the milliseconds to wait for the channel to receive a DTMF digit.</param>
|
||||
public WaitForDigitCommand(int timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public override string BuildCommand()
|
||||
{
|
||||
return "WAIT FOR DIGIT " + timeout.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base class for all AGI specific exceptions.
|
||||
/// </summary>
|
||||
public class AGIException : Exception
|
||||
{
|
||||
public AGIException()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new AGIExeption with the given message.
|
||||
/// </summary>
|
||||
/// <param name="message">a message decribing the AGIException.</param>
|
||||
public AGIException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new AGIExeption with the given message and cause.
|
||||
/// </summary>
|
||||
/// <param name="message">a message decribing the AGIException.</param>
|
||||
/// <param name="cause">the throwable that caused this exception to be thrown.</param>
|
||||
public AGIException(string message, Exception cause)
|
||||
: base(message, cause)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// The AGIHangupException is thrown if the channel has been hang up while processing the AGIRequest.
|
||||
/// </summary>
|
||||
public class AGIHangupException : AGIException
|
||||
{
|
||||
public AGIHangupException()
|
||||
: base("Channel was hung up.")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// The AGINetworkException usally wraps an IOException denoting a network problem when talking to the Asterisk server.
|
||||
/// </summary>
|
||||
public class AGINetworkException : AGIException
|
||||
{
|
||||
public AGINetworkException(string message, Exception cause)
|
||||
: base(message, cause)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// An InvalidCommandSyntaxException is thrown when the reader receives a reply with status code 520.
|
||||
/// </summary>
|
||||
public class InvalidCommandSyntaxException : AGIException
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the synopsis of the command that was called with invalid syntax.
|
||||
/// </summary>
|
||||
/// <returns>the synopsis of the command that was called with invalid syntax.</returns>
|
||||
public string Synopsis
|
||||
{
|
||||
get { return synopsis; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns a description of the command that was called with invalid syntax.
|
||||
/// </summary>
|
||||
/// <returns>a description of the command that was called with invalid syntax.</returns>
|
||||
public string Usage
|
||||
{
|
||||
get { return usage; }
|
||||
}
|
||||
|
||||
private string synopsis;
|
||||
private string usage;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new InvalidCommandSyntaxException with the given synopsis and usage.
|
||||
/// </summary>
|
||||
/// <param name="synopsis">the synopsis of the command.</param>
|
||||
/// <param name="usage">the usage of the command.</param>
|
||||
public InvalidCommandSyntaxException(string synopsis, string usage)
|
||||
: base("Invalid command syntax: " + synopsis)
|
||||
{
|
||||
this.synopsis = synopsis;
|
||||
this.usage = usage;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// An InvalidOrUnknownCommandException is thrown when the reader receives a reply with status code 510.
|
||||
/// </summary>
|
||||
public class InvalidOrUnknownCommandException : AGIException
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new InvalidOrUnknownCommandException.
|
||||
/// </summary>
|
||||
/// <param name="command">the invalid or unknown command.</param>
|
||||
public InvalidOrUnknownCommandException(string command)
|
||||
: base("Invalid or unknown command: " + command)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
128
Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategy.cs
Normal file
128
Asterisk.2013/Asterisk.NET/FastAGI/MappingStrategy.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Asterisk.NET.FastAGI
|
||||
{
|
||||
/// <summary>
|
||||
/// A MappingStrategy that is configured via a resource bundle.<br/>
|
||||
/// The resource bundle contains the script part of the url as key and the fully
|
||||
/// qualified class name of the corresponding AGIScript as value.<br/>
|
||||
/// Example:
|
||||
/// <pre>
|
||||
/// noopcommand = Asterisk.NET.FastAGI.Command.NoopCommand
|
||||
/// </pre>
|
||||
/// NoopCommand must implement the AGIScript interface and have a default constructor with no parameters.<br/>
|
||||
/// </summary>
|
||||
public class MappingStrategy
|
||||
{
|
||||
#if LOGGER
|
||||
private Logger logger = Logger.Instance();
|
||||
#endif
|
||||
private string resourceName;
|
||||
private Hashtable mapping;
|
||||
|
||||
public MappingStrategy()
|
||||
{
|
||||
this.resourceName = Common.AGI_DEFAULT_RESOURCE_BUNDLE_NAME;
|
||||
this.mapping = null;
|
||||
}
|
||||
|
||||
public MappingStrategy(string resourceName)
|
||||
{
|
||||
this.resourceName = resourceName;
|
||||
this.mapping = null;
|
||||
}
|
||||
|
||||
internal AGIScript DetermineScript(AGIRequest request)
|
||||
{
|
||||
AGIScript script = null;
|
||||
if (mapping != null)
|
||||
lock (mapping.SyncRoot)
|
||||
{
|
||||
if (mapping.Contains(request.Script))
|
||||
script = (AGIScript)mapping[request.Script];
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
public string ResourceBundleName
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
mapping = null;
|
||||
resourceName = null;
|
||||
}
|
||||
else if (this.resourceName != value)
|
||||
{
|
||||
this.resourceName = value;
|
||||
Load();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Load()
|
||||
{
|
||||
string scriptName;
|
||||
string className;
|
||||
AGIScript agiScript;
|
||||
|
||||
if (mapping == null)
|
||||
mapping = new Hashtable();
|
||||
lock (mapping)
|
||||
{
|
||||
mapping.Clear();
|
||||
try
|
||||
{
|
||||
ResourceReader rr = new ResourceReader(AppDomain.CurrentDomain.BaseDirectory + resourceName);
|
||||
foreach (DictionaryEntry de in rr)
|
||||
{
|
||||
scriptName = (string)de.Key;
|
||||
className = (string)de.Value;
|
||||
agiScript = createAGIScriptInstance(className);
|
||||
if(mapping.Contains(scriptName))
|
||||
throw new AGIException(String.Format("Duplicate mapping name '{0}' in file {1}", scriptName, resourceName));
|
||||
mapping.Add(scriptName, agiScript);
|
||||
#if LOGGER
|
||||
logger.Info("Added mapping for '" + scriptName + "' to class " + agiScript.GetType().FullName);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Resource bundle '" + resourceName + "' is missing.");
|
||||
#endif
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AGIScript createAGIScriptInstance(string className)
|
||||
{
|
||||
Type agiScriptClass;
|
||||
ConstructorInfo constructor;
|
||||
AGIScript agiScript;
|
||||
|
||||
try
|
||||
{
|
||||
agiScriptClass = Type.GetType(className);
|
||||
constructor = agiScriptClass.GetConstructor(new Type[]{});
|
||||
agiScript = (AGIScript) constructor.Invoke(new object[]{});
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to create AGIScript instance of type " + className, ex);
|
||||
return null;
|
||||
#else
|
||||
throw new AGIException("Unable to create AGIScript instance of type " + className, ex);
|
||||
#endif
|
||||
}
|
||||
return agiScript;
|
||||
}
|
||||
}
|
||||
}
|
10
Asterisk.2013/Asterisk.NET/FastAGI/Script/AGINoAction.cs
Normal file
10
Asterisk.2013/Asterisk.NET/FastAGI/Script/AGINoAction.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Asterisk.NET.FastAGI.Scripts
|
||||
{
|
||||
class AGINoAction : AGIScript
|
||||
{
|
||||
public override void Service(AGIRequest request, AGIChannel channel)
|
||||
{
|
||||
base.Hangup();
|
||||
}
|
||||
}
|
||||
}
|
834
Asterisk.2013/Asterisk.NET/Helper.cs
Normal file
834
Asterisk.2013/Asterisk.NET/Helper.cs
Normal file
|
@ -0,0 +1,834 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Collections.Generic;
|
||||
using Asterisk.NET.Manager.Event;
|
||||
using Asterisk.NET.Manager.Response;
|
||||
using Asterisk.NET.Manager;
|
||||
|
||||
namespace Asterisk.NET
|
||||
{
|
||||
internal class Helper
|
||||
{
|
||||
private static CultureInfo defaultCulture;
|
||||
#if LOGGER
|
||||
private static Logger logger = Logger.Instance();
|
||||
#endif
|
||||
|
||||
#region CultureInfo
|
||||
internal static CultureInfo CultureInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
if (defaultCulture == null)
|
||||
defaultCulture = System.Globalization.CultureInfo.GetCultureInfo("en");
|
||||
return defaultCulture;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToHexString(sbyte[])
|
||||
/// <summary> The hex digits used to build a hex string representation of a byte array.</summary>
|
||||
internal static readonly char[] hexChar = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte array to a hex string representing it. The hex digits are lower case.
|
||||
/// </summary>
|
||||
/// <param name="b">the byte array to convert</param>
|
||||
/// <returns> the hex representation of b</returns>
|
||||
internal static string ToHexString(sbyte[] b)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(b.Length * 2);
|
||||
for (int i = 0; i < b.Length; i++)
|
||||
{
|
||||
sb.Append(hexChar[Helper.URShift((b[i] & 0xf0), 4)]);
|
||||
sb.Append(hexChar[b[i] & 0x0f]);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInternalActionId(actionId)
|
||||
internal static string GetInternalActionId(string actionId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(actionId))
|
||||
return string.Empty;
|
||||
int delimiterIndex = actionId.IndexOf(Common.INTERNAL_ACTION_ID_DELIMITER);
|
||||
if (delimiterIndex > 0)
|
||||
return actionId.Substring(0, delimiterIndex).Trim();
|
||||
return string.Empty;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region StripInternalActionId(actionId)
|
||||
internal static string StripInternalActionId(string actionId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(actionId))
|
||||
return string.Empty;
|
||||
int delimiterIndex = actionId.IndexOf(Common.INTERNAL_ACTION_ID_DELIMITER);
|
||||
if (delimiterIndex > 0)
|
||||
{
|
||||
if (actionId.Length > delimiterIndex + 1)
|
||||
return actionId.Substring(delimiterIndex + 1).Trim();
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsTrue(string)
|
||||
/// <summary>
|
||||
/// Checks if a String represents <code>true</code> or <code>false</code> according to Asterisk's logic.<br/>
|
||||
/// The original implementation is <code>util.c</code> is as follows:
|
||||
/// </summary>
|
||||
/// <param name="s">the String to check for <code>true</code>.</param>
|
||||
/// <returns>
|
||||
/// <code>true</code> if s represents <code>true</code>,
|
||||
/// <code>false</code> otherwise.
|
||||
/// </returns>
|
||||
internal static bool IsTrue(string s)
|
||||
{
|
||||
if (s == null || s.Length == 0)
|
||||
return false;
|
||||
string sx = s.ToLower(Helper.CultureInfo);
|
||||
if (sx == "yes" || sx == "true" || sx == "y" || sx == "t" || sx == "1" || sx == "on")
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region URShift(...)
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
internal static int URShift(int number, int bits)
|
||||
{
|
||||
if (number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2 << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
internal static int URShift(int number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
internal static long URShift(long number, int bits)
|
||||
{
|
||||
if (number >= 0)
|
||||
return number >> bits;
|
||||
else
|
||||
return (number >> bits) + (2L << ~bits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an unsigned bitwise right shift with the specified number
|
||||
/// </summary>
|
||||
/// <param name="number">Number to operate on</param>
|
||||
/// <param name="bits">Ammount of bits to shift</param>
|
||||
/// <returns>The resulting number from the shift operation</returns>
|
||||
internal static long URShift(long number, long bits)
|
||||
{
|
||||
return URShift(number, (int)bits);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToArray(ICollection c, object[] objects)
|
||||
/// <summary>
|
||||
/// Obtains an array containing all the elements of the collection.
|
||||
/// </summary>
|
||||
/// <param name="objects">The array into which the elements of the collection will be stored.</param>
|
||||
/// <returns>The array containing all the elements of the collection.</returns>
|
||||
internal static object[] ToArray(ICollection c, object[] objects)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
Type type = objects.GetType().GetElementType();
|
||||
object[] objs = (object[])Array.CreateInstance(type, c.Count);
|
||||
|
||||
IEnumerator e = c.GetEnumerator();
|
||||
|
||||
while (e.MoveNext())
|
||||
objs[index++] = e.Current;
|
||||
|
||||
//If objects is smaller than c then do not return the new array in the parameter
|
||||
if (objects.Length >= c.Count)
|
||||
objs.CopyTo(objects, 0);
|
||||
|
||||
return objs;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseVariables(Dictionary<string, string> dictionary, string variables, char[] delim)
|
||||
/// <summary>
|
||||
/// Parse variable(s) string to dictionary.
|
||||
/// </summary>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="variables">variable(a) string</param>
|
||||
/// <param name="delim">variable pairs delimiter</param>
|
||||
/// <returns></returns>
|
||||
internal static Dictionary<string, string> ParseVariables(Dictionary<string, string> dictionary, string variables, char[] delim)
|
||||
{
|
||||
if (dictionary == null)
|
||||
dictionary = new Dictionary<string, string>();
|
||||
else
|
||||
dictionary.Clear();
|
||||
|
||||
if (string.IsNullOrEmpty(variables))
|
||||
return dictionary;
|
||||
string[] vars = variables.Split(delim);
|
||||
int idx;
|
||||
string vname, vval;
|
||||
foreach (string var in vars)
|
||||
{
|
||||
idx = var.IndexOf('=');
|
||||
if (idx > 0)
|
||||
{
|
||||
vname = var.Substring(0, idx);
|
||||
vval = var.Substring(idx + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vname = var;
|
||||
vval = string.Empty;
|
||||
}
|
||||
dictionary.Add(vname, vval);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region JoinVariables(IDictionary dictionary, string delim)
|
||||
/// <summary>
|
||||
/// Join variables dictionary to string.
|
||||
/// </summary>
|
||||
/// <param name="dictionary"></param>
|
||||
/// <param name="delim"></param>
|
||||
/// <returns></returns>
|
||||
internal static string JoinVariables(IDictionary dictionary, char[] delim, string delimKeyValue)
|
||||
{
|
||||
return JoinVariables(dictionary, new string(delim), delimKeyValue);
|
||||
}
|
||||
internal static string JoinVariables(IDictionary dictionary, string delim, string delimKeyValue)
|
||||
{
|
||||
if (dictionary == null)
|
||||
return string.Empty;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (DictionaryEntry var in dictionary)
|
||||
{
|
||||
if (sb.Length > 0)
|
||||
sb.Append(delim);
|
||||
sb.Append(string.Concat(var.Key, delimKeyValue, var.Value));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetMillisecondsFrom(DateTime start)
|
||||
internal static long GetMillisecondsFrom(DateTime start)
|
||||
{
|
||||
TimeSpan ts = (TimeSpan)(DateTime.Now - start);
|
||||
return (long)ts.TotalMilliseconds;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseString(string val)
|
||||
internal static object ParseString(string val)
|
||||
{
|
||||
if (val == "none")
|
||||
return string.Empty;
|
||||
return val;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetGetters(class)
|
||||
/// <summary>
|
||||
/// Returns a Map of getter methods of the given class.<br/>
|
||||
/// The key of the map contains the name of the attribute that can be accessed by the getter, the
|
||||
/// value the getter itself . A method is considered a getter if its name starts with "get",
|
||||
/// it is declared internal and takes no arguments.
|
||||
/// </summary>
|
||||
/// <param name="clazz">the class to return the getters for</param>
|
||||
/// <returns> a Map of attributes and their accessor methods (getters)</returns>
|
||||
internal static Dictionary<string, MethodInfo> GetGetters(Type clazz)
|
||||
{
|
||||
string name;
|
||||
string methodName;
|
||||
MethodInfo method;
|
||||
|
||||
Dictionary<string, MethodInfo> accessors = new Dictionary<string, MethodInfo>();
|
||||
MethodInfo[] methods = clazz.GetMethods();
|
||||
|
||||
for (int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
method = methods[i];
|
||||
methodName = method.Name;
|
||||
|
||||
// skip not "get..." methods and skip methods with != 0 parameters
|
||||
if (!methodName.StartsWith("get_") || method.GetParameters().Length != 0)
|
||||
continue;
|
||||
|
||||
name = methodName.Substring(4);
|
||||
if (name.Length == 0)
|
||||
continue;
|
||||
accessors[name] = method;
|
||||
}
|
||||
return accessors;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetSetters(Type clazz)
|
||||
/// <summary>
|
||||
/// Returns a Map of setter methods of the given class.<br/>
|
||||
/// The key of the map contains the name of the attribute that can be accessed by the setter, the
|
||||
/// value the setter itself. A method is considered a setter if its name starts with "set",
|
||||
/// it is declared internal and takes no arguments.
|
||||
/// </summary>
|
||||
/// <param name="clazz">the class to return the setters for</param>
|
||||
/// <returns> a Map of attributes and their accessor methods (setters)</returns>
|
||||
internal static IDictionary GetSetters(Type clazz)
|
||||
{
|
||||
IDictionary accessors = new Hashtable();
|
||||
MethodInfo[] methods = clazz.GetMethods();
|
||||
string name;
|
||||
string methodName;
|
||||
MethodInfo method;
|
||||
|
||||
for (int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
method = methods[i];
|
||||
methodName = method.Name;
|
||||
// skip not "set..." methods and skip methods with != 1 parameters
|
||||
if (!methodName.StartsWith("set_") || method.GetParameters().Length != 1)
|
||||
continue;
|
||||
name = methodName.Substring("set_".Length).ToLower(Helper.CultureInfo);
|
||||
if (name.Length == 0) continue;
|
||||
accessors[name] = method;
|
||||
}
|
||||
return accessors;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString(object obj)
|
||||
/// <summary>
|
||||
/// Convert object with all properties to string
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
internal static string ToString(object obj)
|
||||
{
|
||||
object value;
|
||||
StringBuilder sb = new StringBuilder(obj.GetType().Name, 1024);
|
||||
sb.Append(" {");
|
||||
string strValue;
|
||||
IDictionary getters = Helper.GetGetters(obj.GetType());
|
||||
bool notFirst = false;
|
||||
List<MethodInfo> arrays = new List<MethodInfo>();
|
||||
// First step - all values properties (not a list)
|
||||
foreach (string name in getters.Keys)
|
||||
{
|
||||
MethodInfo getter = (MethodInfo)getters[name];
|
||||
Type propType = getter.ReturnType;
|
||||
if (propType == typeof(object))
|
||||
continue;
|
||||
if (!(propType == typeof(string) || propType == typeof(bool) || propType == typeof(double) || propType == typeof(DateTime) || propType == typeof(int) || propType == typeof(long)))
|
||||
{
|
||||
string propTypeName = propType.Name;
|
||||
if (propTypeName.StartsWith("Dictionary") || propTypeName.StartsWith("List"))
|
||||
{
|
||||
arrays.Add(getter);
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
value = getter.Invoke(obj, new object[] { });
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
continue;
|
||||
if (value is string)
|
||||
{
|
||||
strValue = (string)value;
|
||||
if (strValue.Length == 0)
|
||||
continue;
|
||||
}
|
||||
else if (value is bool)
|
||||
{
|
||||
strValue = ((bool)value ? "true" : "false");
|
||||
}
|
||||
else if (value is double)
|
||||
{
|
||||
double d = (double)value;
|
||||
if (d == 0.0)
|
||||
continue;
|
||||
strValue = d.ToString();
|
||||
}
|
||||
else if (value is DateTime)
|
||||
{
|
||||
DateTime dt = (DateTime)value;
|
||||
if (dt == DateTime.MinValue)
|
||||
continue;
|
||||
strValue = dt.ToLongTimeString();
|
||||
}
|
||||
else if (value is int)
|
||||
{
|
||||
int i = (int)value;
|
||||
if (i == 0)
|
||||
continue;
|
||||
strValue = i.ToString();
|
||||
}
|
||||
else if (value is long)
|
||||
{
|
||||
long l = (long)value;
|
||||
if (l == 0)
|
||||
continue;
|
||||
strValue = l.ToString();
|
||||
}
|
||||
else
|
||||
strValue = value.ToString();
|
||||
|
||||
if (notFirst)
|
||||
sb.Append("; ");
|
||||
notFirst = true;
|
||||
sb.Append(string.Concat(getter.Name.Substring(4), ":", strValue));
|
||||
}
|
||||
|
||||
// Second step - all lists
|
||||
foreach (MethodInfo getter in arrays)
|
||||
{
|
||||
value = null;
|
||||
try
|
||||
{
|
||||
value = getter.Invoke(obj, new object[] { });
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (value == null)
|
||||
continue;
|
||||
|
||||
#region List
|
||||
IList list;
|
||||
if (value is IList && (list = (IList)value).Count > 0)
|
||||
{
|
||||
if (notFirst)
|
||||
sb.Append("; ");
|
||||
notFirst = true;
|
||||
sb.Append(getter.Name.Substring(4));
|
||||
sb.Append(":[");
|
||||
bool notFirst2 = false;
|
||||
foreach (object o in list)
|
||||
{
|
||||
if (notFirst2)
|
||||
sb.Append("; ");
|
||||
notFirst2 = true;
|
||||
sb.Append(o.ToString());
|
||||
}
|
||||
sb.Append("]");
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDictionary
|
||||
else if (value is IDictionary && ((IDictionary)value).Count > 0)
|
||||
{
|
||||
if (notFirst)
|
||||
sb.Append("; ");
|
||||
notFirst = true;
|
||||
sb.Append(getter.Name.Substring(4));
|
||||
sb.Append(":[");
|
||||
bool notFirst2 = false;
|
||||
foreach (object key in ((IDictionary)value).Keys)
|
||||
{
|
||||
object o = ((IDictionary)value)[key];
|
||||
if (notFirst2)
|
||||
sb.Append("; ");
|
||||
notFirst2 = true;
|
||||
sb.Append(string.Concat(key, ":", o));
|
||||
}
|
||||
sb.Append("]");
|
||||
continue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
sb.Append("}");
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetAttributes(object evt, IDictionary attributes)
|
||||
internal static void SetAttributes(IParseSupport o, Dictionary<string, string> attributes)
|
||||
{
|
||||
Type dataType;
|
||||
object val;
|
||||
|
||||
// Preparse attributes
|
||||
attributes = o.ParseSpecial(attributes);
|
||||
|
||||
IDictionary setters = Helper.GetSetters(o.GetType());
|
||||
MethodInfo setter;
|
||||
foreach (string name in attributes.Keys)
|
||||
{
|
||||
if (name == "event")
|
||||
continue;
|
||||
|
||||
if (name == "source")
|
||||
setter = (MethodInfo)setters["src"];
|
||||
else
|
||||
setter = (MethodInfo)setters[stripIllegalCharacters(name)];
|
||||
|
||||
if (setter == null)
|
||||
{
|
||||
// No setter found to key, try general parser
|
||||
if (!o.Parse(name, (string)attributes[name]))
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to set property '" + name + "' on " + o.GetType() + ": no setter");
|
||||
#endif
|
||||
throw new ManagerException("Parse error key '" + name + "' on " + o.GetType());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dataType = (setter.GetParameters()[0]).ParameterType;
|
||||
if (dataType == typeof(bool))
|
||||
val = Helper.IsTrue((string)attributes[name]);
|
||||
else if (dataType == typeof(string))
|
||||
val = Helper.ParseString((string)attributes[name]);
|
||||
else if (dataType == typeof(Int32))
|
||||
{
|
||||
Int32 v = 0;
|
||||
Int32.TryParse((string)attributes[name], out v);
|
||||
val = v;
|
||||
}
|
||||
else if (dataType == typeof(Int64))
|
||||
{
|
||||
Int64 v = 0;
|
||||
Int64.TryParse((string)attributes[name], out v);
|
||||
val = v;
|
||||
}
|
||||
else if (dataType == typeof(double))
|
||||
{
|
||||
Double v = 0.0;
|
||||
Double.TryParse((string)attributes[name], System.Globalization.NumberStyles.AllowDecimalPoint, Common.CultureInfoEn, out v);
|
||||
val = v;
|
||||
}
|
||||
else if (dataType == typeof(decimal))
|
||||
{
|
||||
Decimal v = 0;
|
||||
Decimal.TryParse((string)attributes[name], System.Globalization.NumberStyles.AllowDecimalPoint, Common.CultureInfoEn, out v);
|
||||
val = v;
|
||||
}
|
||||
else if (dataType.IsEnum)
|
||||
{
|
||||
try
|
||||
{
|
||||
val = Convert.ChangeType(Enum.Parse(dataType, (string)attributes[name], true), dataType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to convert value '" + attributes[name] + "' of property '" + name + "' on " + o.GetType() + " to required enum type " + dataType, ex);
|
||||
continue;
|
||||
#else
|
||||
throw new ManagerException("Unable to convert value '" + attributes[name] + "' of property '" + name + "' on " + o.GetType() + " to required enum type " + dataType, ex); #endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
ConstructorInfo constructor = dataType.GetConstructor(new Type[] { typeof(string) });
|
||||
val = constructor.Invoke(new object[] { attributes[name] });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to convert value '" + attributes[name] + "' of property '" + name + "' on " + o.GetType() + " to required type " + dataType, ex);
|
||||
continue;
|
||||
#else
|
||||
throw new ManagerException("Unable to convert value '" + attributes[name] + "' of property '" + name + "' on " + o.GetType() + " to required type " + dataType, ex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
setter.Invoke(o, new object[] { val });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to set property '" + name + "' on " + o.GetType(), ex);
|
||||
continue;
|
||||
#else
|
||||
throw new ManagerException("Unable to set property '" + name + "' on " + o.GetType(), ex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddKeyValue(IDictionary list, string line)
|
||||
internal static void AddKeyValue(IDictionary list, string line)
|
||||
{
|
||||
int delimiterIndex = line.IndexOf(":");
|
||||
if (delimiterIndex > 0 && line.Length > delimiterIndex + 1)
|
||||
{
|
||||
string name = line.Substring(0, delimiterIndex).ToLower(Helper.CultureInfo).Trim();
|
||||
string val = line.Substring(delimiterIndex + 1).Trim();
|
||||
if (val == "<null>")
|
||||
list[name] = null;
|
||||
else
|
||||
list[name] = val;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region stripIllegalCharacters(string s)
|
||||
/// <summary>
|
||||
/// Strips all illegal charaters from the given lower case string.
|
||||
/// </summary>
|
||||
/// <param name="s">the original string</param>
|
||||
/// <returns>the string with all illegal characters stripped</returns>
|
||||
private static string stripIllegalCharacters(string s)
|
||||
{
|
||||
char c;
|
||||
bool needsStrip = false;
|
||||
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
c = s[i];
|
||||
if (c >= '0' && c <= '9')
|
||||
continue;
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
continue;
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
continue;
|
||||
else
|
||||
{
|
||||
needsStrip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needsStrip)
|
||||
return s;
|
||||
|
||||
StringBuilder sb = new StringBuilder(s.Length);
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
c = s[i];
|
||||
if (c >= '0' && c <= '9')
|
||||
sb.Append(c);
|
||||
else if (c >= 'a' && c <= 'z')
|
||||
sb.Append(c);
|
||||
else if (c >= 'A' && c <= 'Z')
|
||||
sb.Append(c);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildResponse(IDictionary attributes)
|
||||
/// <summary>
|
||||
/// Constructs an instance of ManagerResponse based on a map of attributes.
|
||||
/// </summary>
|
||||
/// <param name="attributes">the attributes and their values. The keys of this map must be all lower case.</param>
|
||||
/// <returns>the response with the given attributes.</returns>
|
||||
internal static ManagerResponse BuildResponse(Dictionary<string, string> attributes)
|
||||
{
|
||||
ManagerResponse response;
|
||||
|
||||
string responseType = ((string)attributes["response"]).ToLower(Helper.CultureInfo);
|
||||
|
||||
// Determine type
|
||||
if (responseType == "error")
|
||||
response = new ManagerError();
|
||||
else if (attributes.ContainsKey("challenge"))
|
||||
response = new ChallengeResponse();
|
||||
else if (attributes.ContainsKey("mailbox") && attributes.ContainsKey("waiting"))
|
||||
response = new MailboxStatusResponse();
|
||||
else if (attributes.ContainsKey("mailbox") && attributes.ContainsKey("newmessages") && attributes.ContainsKey("oldmessages"))
|
||||
response = new MailboxCountResponse();
|
||||
else if (attributes.ContainsKey("exten") && attributes.ContainsKey("context") && attributes.ContainsKey("hint") && attributes.ContainsKey("status"))
|
||||
response = new ExtensionStateResponse();
|
||||
else
|
||||
response = new ManagerResponse();
|
||||
|
||||
Helper.SetAttributes(response, attributes);
|
||||
return response;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region BuildEvent(Hashtable list, object source, IDictionary attributes)
|
||||
/// <summary>
|
||||
/// Builds the event based on the given map of attributes and the registered event classes.
|
||||
/// </summary>
|
||||
/// <param name="source">source attribute for the event</param>
|
||||
/// <param name="attributes">map containing event attributes</param>
|
||||
/// <returns>a concrete instance of ManagerEvent or <code>null</code> if no event class was registered for the event type.</returns>
|
||||
internal static ManagerEvent BuildEvent(IDictionary<int, ConstructorInfo> list, ManagerConnection source, Dictionary<string, string> attributes)
|
||||
{
|
||||
ManagerEvent e;
|
||||
string eventType;
|
||||
ConstructorInfo constructor = null;
|
||||
int hash, hashEvent;
|
||||
|
||||
eventType = ((string)attributes["event"]).ToLower(Helper.CultureInfo);
|
||||
// Remove Event tail from event name (ex. JabberEvent)
|
||||
if (eventType.EndsWith("event"))
|
||||
eventType = eventType.Substring(0, eventType.Length - 5);
|
||||
hashEvent = eventType.GetHashCode();
|
||||
|
||||
if (eventType == "user")
|
||||
{
|
||||
string userevent = ((string)attributes["userevent"]).ToLower(Helper.CultureInfo);
|
||||
hash = string.Concat(eventType, userevent).GetHashCode();
|
||||
if(list.ContainsKey(hash))
|
||||
constructor = list[hash];
|
||||
else
|
||||
constructor = list[hashEvent];
|
||||
}
|
||||
else if (list.ContainsKey(hashEvent))
|
||||
constructor = list[hashEvent];
|
||||
|
||||
if (constructor == null)
|
||||
e = new UnknownEvent(source);
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
e = (ManagerEvent)constructor.Invoke(new object[] { source });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if LOGGER
|
||||
logger.Error("Unable to create new instance of " + eventType, ex);
|
||||
return null;
|
||||
#else
|
||||
throw ex;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SetAttributes(e, attributes);
|
||||
|
||||
// ResponseEvents are sent in response to a ManagerAction if the
|
||||
// response contains lots of data. They include the actionId of
|
||||
// the corresponding ManagerAction.
|
||||
if (e is ResponseEvent)
|
||||
{
|
||||
ResponseEvent responseEvent = (ResponseEvent)e;
|
||||
string actionId = responseEvent.ActionId;
|
||||
if (actionId != null)
|
||||
{
|
||||
responseEvent.ActionId = Helper.StripInternalActionId(actionId);
|
||||
responseEvent.InternalActionId = Helper.GetInternalActionId(actionId);
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RegisterBuiltinEventClasses(Hashtable list)
|
||||
/// <summary>
|
||||
/// Register buildin Event classes
|
||||
/// </summary>
|
||||
/// <param name="list"></param>
|
||||
internal static void RegisterBuiltinEventClasses(Dictionary<int, ConstructorInfo> list)
|
||||
{
|
||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
||||
Type manager = typeof(ManagerEvent);
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
if (type.IsPublic && !type.IsAbstract && manager.IsAssignableFrom(type))
|
||||
RegisterEventClass(list, type);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RegisterEventClass(Dictionary<string, ConstructorInfo> list, Type clazz)
|
||||
internal static void RegisterEventClass(Dictionary<int, ConstructorInfo> list, Type clazz)
|
||||
{
|
||||
// Ignore all abstract classes
|
||||
// Class not derived from ManagerEvent
|
||||
if (clazz.IsAbstract || !typeof(ManagerEvent).IsAssignableFrom(clazz))
|
||||
return;
|
||||
|
||||
string eventType = clazz.Name.ToLower(Helper.CultureInfo);
|
||||
|
||||
// Remove "event" at the end (if presents)
|
||||
if (eventType.EndsWith("event"))
|
||||
eventType = eventType.Substring(0, eventType.Length - 5);
|
||||
|
||||
// If assignable from UserEvent and no "userevent" at the start - add "userevent" to beginning
|
||||
if (typeof(UserEvent).IsAssignableFrom(clazz) && !eventType.StartsWith("user"))
|
||||
eventType = "user" + eventType;
|
||||
|
||||
int hash = eventType.GetHashCode();
|
||||
if (list.ContainsKey(hash))
|
||||
return;
|
||||
|
||||
ConstructorInfo constructor = null;
|
||||
try
|
||||
{
|
||||
constructor = clazz.GetConstructor(new Type[] { typeof(ManagerConnection) });
|
||||
}
|
||||
catch (MethodAccessException ex)
|
||||
{
|
||||
throw new ArgumentException("RegisterEventClass : " + clazz + " has no usable constructor.", ex);
|
||||
}
|
||||
|
||||
if (constructor != null && constructor.IsPublic)
|
||||
list.Add(hash, constructor);
|
||||
else
|
||||
throw new ArgumentException("RegisterEventClass : " + clazz + " has no public default constructor");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RegisterEventHandler(Dictionary<int, int> list, int index, Type eventType)
|
||||
internal static void RegisterEventHandler(Dictionary<int, int> list, int index, Type eventType)
|
||||
{
|
||||
int eventHash = eventType.Name.GetHashCode();
|
||||
if (list.ContainsKey(eventHash))
|
||||
throw new ArgumentException("Event class already registered : " + eventType.Name);
|
||||
list.Add(eventHash, index);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
38
Asterisk.2013/Asterisk.NET/IO/ServerSocket.cs
Normal file
38
Asterisk.2013/Asterisk.NET/IO/ServerSocket.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// ServerSocket using standard socket classes.
|
||||
/// </summary>
|
||||
public class ServerSocket
|
||||
{
|
||||
private TcpListener tcpListener;
|
||||
private Encoding encoding;
|
||||
|
||||
public ServerSocket(int port, IPAddress bindAddress, Encoding encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
tcpListener = new TcpListener(new IPEndPoint(bindAddress, port));
|
||||
tcpListener.Start();
|
||||
}
|
||||
|
||||
public IO.SocketConnection Accept()
|
||||
{
|
||||
if (tcpListener != null)
|
||||
{
|
||||
TcpClient tcpClient = tcpListener.AcceptTcpClient();
|
||||
if (tcpClient != null)
|
||||
return new IO.SocketConnection(tcpClient, encoding);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
tcpListener.Stop();
|
||||
}
|
||||
}
|
||||
}
|
204
Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs
Normal file
204
Asterisk.2013/Asterisk.NET/IO/SocketConnection.cs
Normal file
|
@ -0,0 +1,204 @@
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System;
|
||||
|
||||
namespace Asterisk.NET.IO
|
||||
{
|
||||
public class SocketConnection
|
||||
{
|
||||
private TcpClient tcpClient;
|
||||
private NetworkStream networkStream;
|
||||
private StreamReader reader;
|
||||
private StreamWriter writer;
|
||||
private Encoding encoding;
|
||||
private bool initial;
|
||||
|
||||
#region Constructor - SocketConnection(string host, int port, int receiveTimeout)
|
||||
/// <summary>
|
||||
/// Consructor
|
||||
/// </summary>
|
||||
/// <param name="host">client host</param>
|
||||
/// <param name="port">client port</param>
|
||||
/// <param name="encoding">encoding</param>
|
||||
public SocketConnection(string host, int port, Encoding encoding)
|
||||
{
|
||||
initial = true;
|
||||
this.encoding = encoding;
|
||||
this.tcpClient = new TcpClient(host, port);
|
||||
this.networkStream = this.tcpClient.GetStream();
|
||||
this.reader = new StreamReader(this.networkStream, encoding);
|
||||
this.writer = new StreamWriter(this.networkStream, encoding);
|
||||
this.writer.AutoFlush = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructor - SocketConnection(socket)
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="socket">TCP client from Listener</param>
|
||||
/// <param name="encoding">encoding</param>
|
||||
internal SocketConnection(TcpClient tcpClient, Encoding encoding)
|
||||
{
|
||||
initial = true;
|
||||
this.encoding = encoding;
|
||||
this.tcpClient = tcpClient;
|
||||
this.networkStream = this.tcpClient.GetStream();
|
||||
this.reader = new StreamReader(this.networkStream, encoding);
|
||||
this.writer = new StreamWriter(this.networkStream, encoding);
|
||||
this.writer.AutoFlush = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public TcpClient TcpClient
|
||||
{
|
||||
get { return tcpClient; }
|
||||
}
|
||||
|
||||
public NetworkStream NetworkStream
|
||||
{
|
||||
get { return networkStream; }
|
||||
}
|
||||
|
||||
public Encoding Encoding
|
||||
{
|
||||
get { return encoding; }
|
||||
}
|
||||
|
||||
public bool Initial
|
||||
{
|
||||
get { return initial; }
|
||||
set { initial = value; }
|
||||
}
|
||||
|
||||
#region IsConnected
|
||||
/// <summary>
|
||||
/// Returns the connection state of the socket.
|
||||
/// </summary>
|
||||
public bool IsConnected
|
||||
{
|
||||
get { return tcpClient.Connected; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LocalAddress
|
||||
public IPAddress LocalAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Address;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LocalPort
|
||||
public int LocalPort
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoteAddress
|
||||
public IPAddress RemoteAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IPEndPoint)(tcpClient.Client.RemoteEndPoint)).Address;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemotePort
|
||||
public int RemotePort
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((IPEndPoint)(tcpClient.Client.LocalEndPoint)).Port;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadLine()
|
||||
/// <summary>
|
||||
/// Reads a line of text from the socket connection. The current thread is
|
||||
/// blocked until either the next line is received or an IOException
|
||||
/// encounters.
|
||||
/// </summary>
|
||||
/// <returns>the line of text received excluding any newline character</returns>
|
||||
/// <throws> IOException if the connection has been closed. </throws>
|
||||
public string ReadLine()
|
||||
{
|
||||
string line = null;
|
||||
try
|
||||
{
|
||||
line = reader.ReadLine();
|
||||
}
|
||||
catch
|
||||
{
|
||||
line = null;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Write(string s)
|
||||
/// <summary>
|
||||
/// Sends a given String to the socket connection.
|
||||
/// </summary>
|
||||
/// <param name="s">the String to send.</param>
|
||||
/// <throws> IOException if the String cannot be sent, maybe because the </throws>
|
||||
/// <summary>connection has already been closed.</summary>
|
||||
public void Write(string s)
|
||||
{
|
||||
writer.Write(s);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Write(string msg)
|
||||
/// <summary>
|
||||
/// Sends a given String to the socket connection.
|
||||
/// </summary>
|
||||
/// <param name="msg">the String to send.</param>
|
||||
/// <throws> IOException if the String cannot be sent, maybe because the </throws>
|
||||
/// <summary>connection has already been closed.</summary>
|
||||
public void WriteEx(string msg)
|
||||
{
|
||||
byte[] data = encoding.GetBytes(msg);
|
||||
networkStream.BeginWrite(data, 0, data.Length, onWriteFinished, networkStream);
|
||||
networkStream.Flush();
|
||||
}
|
||||
|
||||
private void onWriteFinished(IAsyncResult ar)
|
||||
{
|
||||
NetworkStream stream = (NetworkStream)ar.AsyncState;
|
||||
stream.EndWrite(ar);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Close
|
||||
/// <summary>
|
||||
/// Closes the socket connection including its input and output stream and
|
||||
/// frees all associated ressources.<br/>
|
||||
/// When calling close() any Thread currently blocked by a call to readLine()
|
||||
/// will be unblocked and receive an IOException.
|
||||
/// </summary>
|
||||
/// <throws> IOException if the socket connection cannot be closed. </throws>
|
||||
public void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
tcpClient.Client.Shutdown(SocketShutdown.Both);
|
||||
tcpClient.Client.Close();
|
||||
tcpClient.Close();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
16
Asterisk.2013/Asterisk.NET/IParseSupport.cs
Normal file
16
Asterisk.2013/Asterisk.NET/IParseSupport.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Asterisk.NET
|
||||
{
|
||||
internal interface IParseSupport
|
||||
{
|
||||
Dictionary<string, string> Attributes
|
||||
{
|
||||
get;
|
||||
}
|
||||
bool Parse(string key, string value);
|
||||
Dictionary<string, string> ParseSpecial(Dictionary<string, string> attributes);
|
||||
}
|
||||
}
|
261
Asterisk.2013/Asterisk.NET/Logger.cs
Normal file
261
Asterisk.2013/Asterisk.NET/Logger.cs
Normal file
|
@ -0,0 +1,261 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
|
||||
namespace Asterisk.NET
|
||||
{
|
||||
#if LOGGER
|
||||
|
||||
#region class LogFactory
|
||||
/// <summary>
|
||||
/// Facade to hide details of the underlying logging system.
|
||||
/// </summary>
|
||||
public sealed class Logger
|
||||
{
|
||||
private static Logger logger;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of Log suitable for logging from the given class.
|
||||
/// </summary>
|
||||
/// <returns> the created logger.</returns>
|
||||
public static Logger Instance()
|
||||
{
|
||||
if(logger == null)
|
||||
logger = new Logger();
|
||||
return logger;
|
||||
}
|
||||
|
||||
public enum MessageLevel
|
||||
{
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Debug
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CommonsLoggingLog obtained from commons-logging's LogFactory for the given class.
|
||||
/// </summary>
|
||||
public Logger()
|
||||
{
|
||||
}
|
||||
|
||||
private void writeLine(string type, string msg)
|
||||
{
|
||||
System.Diagnostics.Debug.Print(string.Format("{0}[{1}] {2}", type, Thread.CurrentThread.Name, msg));
|
||||
}
|
||||
private void writeLine(string msg)
|
||||
{
|
||||
System.Diagnostics.Debug.Print(msg);
|
||||
}
|
||||
|
||||
// Max 2 calls from original caller !
|
||||
private string debugInfo()
|
||||
{
|
||||
System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(2, true);
|
||||
System.Reflection.MethodBase mb = sf.GetMethod();
|
||||
return string.Concat(mb.DeclaringType.Name, ":", mb.Name);
|
||||
}
|
||||
|
||||
|
||||
Hashtable visibleDebug = new Hashtable();
|
||||
Hashtable visibleError = new Hashtable();
|
||||
Hashtable visibleInfo = new Hashtable();
|
||||
Hashtable visibleWarning = new Hashtable();
|
||||
|
||||
private bool visibleDebugDef = true;
|
||||
private bool visibleErrorDef = true;
|
||||
private bool visibleInfoDef = true;
|
||||
private bool visibleWarningDef = true;
|
||||
|
||||
/// <summary>
|
||||
/// Get visibility for message level of class:method
|
||||
/// </summary>
|
||||
/// <param name="debugClass">messageType:class:method</param>
|
||||
/// <returns></returns>
|
||||
public bool IsVisible(MessageLevel messageLevel, string classMethod)
|
||||
{
|
||||
return isVisible(messageLevel, classMethod.GetHashCode());
|
||||
}
|
||||
|
||||
private bool isVisible(MessageLevel messageLevel, int hash)
|
||||
{
|
||||
switch (messageLevel)
|
||||
{
|
||||
case MessageLevel.Debug:
|
||||
return (visibleDebug.ContainsKey(hash) ? (bool)visibleDebug[hash] : visibleDebugDef);
|
||||
case MessageLevel.Error:
|
||||
return (visibleError.ContainsKey(hash) ? (bool)visibleError[hash] : visibleErrorDef);
|
||||
case MessageLevel.Info:
|
||||
return (visibleInfo.ContainsKey(hash) ? (bool)visibleInfo[hash] : visibleInfoDef);
|
||||
case MessageLevel.Warning:
|
||||
return (visibleWarning.ContainsKey(hash) ? (bool)visibleWarning[hash] : visibleWarningDef);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set visibility for message level of class:method
|
||||
/// </summary>
|
||||
/// <param name="visible">visible</param>
|
||||
/// <param name="messageLevel">message level</param>
|
||||
/// <param name="classMethod">class:method</param>
|
||||
public void Visible(bool visible, MessageLevel messageLevel, string classMethod)
|
||||
{
|
||||
int hash = classMethod.GetHashCode();
|
||||
switch (messageLevel)
|
||||
{
|
||||
case MessageLevel.Debug:
|
||||
visibleDebug[hash] = visible;
|
||||
return;
|
||||
case MessageLevel.Error:
|
||||
visibleError[hash] = visible;
|
||||
return;
|
||||
case MessageLevel.Info:
|
||||
visibleInfo[hash] = visible;
|
||||
return;
|
||||
case MessageLevel.Warning:
|
||||
visibleWarning[hash] = visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set visibility for message level of class:method
|
||||
/// </summary>
|
||||
/// <param name="visible">visible</param>
|
||||
/// <param name="messageLevel">message level</param>
|
||||
/// <param name="classMethod">class:method</param>
|
||||
public void Visible(bool visible, MessageLevel messageLevel)
|
||||
{
|
||||
switch (messageLevel)
|
||||
{
|
||||
case MessageLevel.Debug:
|
||||
visibleDebugDef = visible;
|
||||
return;
|
||||
case MessageLevel.Error:
|
||||
visibleErrorDef = visible;
|
||||
return;
|
||||
case MessageLevel.Info:
|
||||
visibleInfoDef = visible;
|
||||
return;
|
||||
case MessageLevel.Warning:
|
||||
visibleWarningDef = visible;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#region Debug
|
||||
public void Debug(object o)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Debug, caller.GetHashCode()))
|
||||
writeLine(" Debug:", string.Concat(caller, " - ", o.ToString()));
|
||||
}
|
||||
public void Debug(string msg)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Debug, caller.GetHashCode()))
|
||||
writeLine(" Debug:", string.Concat(caller, " - ", msg));
|
||||
}
|
||||
public void Debug(string format, params object[] args)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Debug, caller.GetHashCode()))
|
||||
writeLine(" Debug:", string.Concat(caller, " - ", string.Format(format, args)));
|
||||
}
|
||||
public void Debug(string msg, Exception ex)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Debug, caller.GetHashCode()))
|
||||
writeLine(" Debug:", string.Concat(caller, " - ", string.Format("{0}\n{1}", msg, ex)));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Info
|
||||
public void Info(object o)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Info, caller.GetHashCode()))
|
||||
writeLine(" Info:", string.Concat(caller, " - ", o.ToString()));
|
||||
}
|
||||
public void Info(string msg)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Info, caller.GetHashCode()))
|
||||
writeLine(" Info:", string.Concat(caller, " - ", msg));
|
||||
}
|
||||
public void Info(string format, params object[] args)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Info, caller.GetHashCode()))
|
||||
writeLine(" Info:", string.Concat(caller, " - ", string.Format(format, args)));
|
||||
}
|
||||
public void Info(string msg, Exception ex)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Info, caller.GetHashCode()))
|
||||
writeLine(" Info:", string.Concat(caller, " - ", string.Format("{0}\n{1}", msg, ex)));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Warning
|
||||
public void Warning(object o)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Warning, caller.GetHashCode()))
|
||||
writeLine("Warning:", string.Concat(caller, " - ", o.ToString()));
|
||||
}
|
||||
public void Warning(string msg)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Warning, caller.GetHashCode()))
|
||||
writeLine("Warning:", string.Concat(caller, " - ", msg));
|
||||
}
|
||||
public void Warning(string format, params object[] args)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Warning, caller.GetHashCode()))
|
||||
writeLine("Warning:", string.Concat(caller, " - ", string.Format(format, args)));
|
||||
}
|
||||
public void Warning(string msg, Exception ex)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Warning, caller.GetHashCode()))
|
||||
writeLine("Warning:", string.Concat(caller, " - ", string.Format("{0}\n{1}", msg, ex)));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Error
|
||||
public void Error(object o)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Error, caller.GetHashCode()))
|
||||
writeLine(" Error:", string.Concat(caller, " - ", o.ToString()));
|
||||
}
|
||||
public void Error(string msg)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Error, caller.GetHashCode()))
|
||||
writeLine(" Error:", string.Concat(caller, " - ", msg));
|
||||
}
|
||||
public void Error(string format, params object[] args)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Error, caller.GetHashCode()))
|
||||
writeLine(" Error:", string.Concat(caller, " - ", string.Format(format, args)));
|
||||
}
|
||||
public void Error(string msg, Exception ex)
|
||||
{
|
||||
string caller = debugInfo();
|
||||
if (isVisible(MessageLevel.Error, caller.GetHashCode()))
|
||||
writeLine(" Error:", string.Concat(caller, " - ", string.Format("{0}\n{1}", msg, ex)));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The AbsoluteTimeoutAction sets the absolute maximum amount of time permitted for a call on a given channel.<br/>
|
||||
/// Note that the timeout is set from the current time forward, not counting the number of seconds the call has already been up.<br/>
|
||||
/// When setting a new timeout all previous absolute timeouts are cancelled.<br/>
|
||||
/// When the timeout is reached the call is returned to the T extension so that
|
||||
/// you can playback an explanatory note to the calling party (the called party will not hear that).<br/>
|
||||
/// This action corresponds the the AbsoluteTimeout command used in the dialplan.
|
||||
/// </summary>
|
||||
public class AbsoluteTimeoutAction : ManagerAction
|
||||
{
|
||||
private string channel;
|
||||
private int timeout;
|
||||
|
||||
#region AbsoluteTimeoutAction()
|
||||
/// <summary>
|
||||
/// Creates a new empty AbsoluteTimeoutAction.
|
||||
/// </summary>
|
||||
public AbsoluteTimeoutAction()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
#region AbsoluteTimeoutAction(channel, timeout)
|
||||
/// <summary>
|
||||
/// Creates a new AbsoluteTimeoutAction with the given channel and timeout.
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel</param>
|
||||
/// <param name="timeout">the timeout in seconds or 0 to cancel the AbsoluteTimeout</param>
|
||||
public AbsoluteTimeoutAction(string channel, int timeout)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "AbsoluteTimeout".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "AbsoluteTimeout"; }
|
||||
}
|
||||
#endregion
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Get/Set the name of the channel.</summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Timeout
|
||||
/// <summary>
|
||||
/// Get/Set the timeout (in seconds) to set.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The AgentCallbackLoginAction sets an agent as logged in with callback.<br/>
|
||||
/// You can pass an extentsion (and optionally a context) to specify the
|
||||
/// destination of the callback.<br/>
|
||||
/// In contrast to the AgentCallbackLogin application that you can use within
|
||||
/// Asterisk's dialplan, you don't need to know the agent's password when logging
|
||||
/// in an agent.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
public class AgentCallbackLoginAction : ManagerAction
|
||||
{
|
||||
private string agent;
|
||||
private string exten;
|
||||
private string context;
|
||||
private bool ackCall;
|
||||
private long wrapupTime;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "AgentCallbackLogin".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "AgentCallbackLogin"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the agent to log in, for example "1002".<br/>
|
||||
/// This is property is mandatory.
|
||||
/// </summary>
|
||||
public string Agent
|
||||
{
|
||||
get { return this.agent; }
|
||||
set { this.agent = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the extension to use for callback.<br/>
|
||||
/// This is property is mandatory.
|
||||
/// </summary>
|
||||
public string Exten
|
||||
{
|
||||
get { return this.exten; }
|
||||
set { this.exten = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the context of the extension to use for callback.
|
||||
/// </summary>
|
||||
public string Context
|
||||
{
|
||||
get { return this.context; }
|
||||
set { this.context = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set if an acknowledgement is needed when agent is called back.<br/>
|
||||
/// <code>true</code> if acknowledgement by '#' is required when agent is called back, <code>false</code> otherwise.
|
||||
/// This property is optional, it allows you to override the defaults defined in Asterisk's configuration.
|
||||
/// </summary>
|
||||
public bool AckCall
|
||||
{
|
||||
get { return this.ackCall; }
|
||||
set { this.ackCall = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the minimum amount of time (in milliseconds) after disconnecting before the caller can receive a new call.<br/>
|
||||
/// This property is optional, it allows you to override the defaults defined in Asterisk's configuration.
|
||||
/// </summary>
|
||||
public long WrapupTime
|
||||
{
|
||||
get { return this.wrapupTime; }
|
||||
set { this.wrapupTime = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty AgentCallbackLoginAction.
|
||||
/// </summary>
|
||||
public AgentCallbackLoginAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new AgentCallbackLoginAction, that logs in the given agent at
|
||||
/// the given callback extension.
|
||||
/// </summary>
|
||||
/// <param name="agent">the name of the agent to log in</param>
|
||||
/// <param name="exten">the extension that is called to connect a queue member with this agent</param>
|
||||
public AgentCallbackLoginAction(string agent, string exten)
|
||||
{
|
||||
this.agent = agent;
|
||||
this.exten = exten;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new AgentCallbackLoginAction, that logs in the given agent at
|
||||
/// the given callback extension in the given context.
|
||||
/// </summary>
|
||||
/// <param name="agent">the name of the agent to log in</param>
|
||||
/// <param name="exten">the extension that is called to connect a queue member with this agent</param>
|
||||
/// <param name="context">the context of the extension to use for callback</param>
|
||||
public AgentCallbackLoginAction(string agent, string exten, string context)
|
||||
: this(agent, exten)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The AgentLogoffAction sets an agent as no longer logged in.
|
||||
/// </summary>
|
||||
public class AgentLogoffAction : ManagerAction
|
||||
{
|
||||
private string agent;
|
||||
private bool soft;
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Returns the name of this action, i.e. "AgentLogoff".
|
||||
/// </summary>
|
||||
/// <returns>the name of this action</returns>
|
||||
override public string Action
|
||||
{
|
||||
get
|
||||
{
|
||||
return "AgentLogoff";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Agent
|
||||
/// <summary>
|
||||
/// Returns the name of the agent to log off, for example "1002".
|
||||
/// </summary>
|
||||
/// <returns>the name of the agent to log off</returns>
|
||||
/// <summary> Sets the name of the agent to log off, for example "1002".<br/>
|
||||
/// This is property is mandatory.
|
||||
/// </summary>
|
||||
/// <param name="agent">the name of the agent to log off</param>
|
||||
public string Agent
|
||||
{
|
||||
get
|
||||
{
|
||||
return agent;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.agent = value;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Soft
|
||||
/// <summary>
|
||||
/// Get/Set whether to hangup existing calls or not.<br/>
|
||||
/// Default is to hangup existing calls on logoff.
|
||||
/// </summary>
|
||||
/// <returns> true if existing calls should not be hung up, false otherwise.<br/>
|
||||
/// <code>null</code> if default should be used.
|
||||
/// </returns>
|
||||
public bool Soft
|
||||
{
|
||||
get { return soft; }
|
||||
set { this.soft = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors - AgentLogoffAction()
|
||||
/// <summary> Creates a new empty AgentLogoffAction.</summary>
|
||||
public AgentLogoffAction()
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a new AgentLogoffAction that logs off the given agent
|
||||
/// </summary>
|
||||
/// <param name="agent">the name of the agent to log off.</param>
|
||||
public AgentLogoffAction(string agent)
|
||||
{
|
||||
this.agent = agent;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors - AgentLogoffAction(string agent, bool soft)
|
||||
/// <summary>
|
||||
/// Creates a new AgentLogoffAction that logs off the given agent
|
||||
/// </summary>
|
||||
/// <param name="agent">the name of the agent to log off.</param>
|
||||
/// <param name="soft">true if exisiting calls should not be hung up on logout.</param>
|
||||
public AgentLogoffAction(string agent, bool soft)
|
||||
: this(agent)
|
||||
{
|
||||
this.soft = soft;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
41
Asterisk.2013/Asterisk.NET/Manager/Action/AgentsAction.cs
Normal file
41
Asterisk.2013/Asterisk.NET/Manager/Action/AgentsAction.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The AgentsAction requests the state of all agents.<br/>
|
||||
/// For each agent an AgentsEvent is generated.
|
||||
/// After the state of all agents has been reported an AgentsCompleteEvent is generated.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.AgentsEvent" />
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.AgentsCompleteEvent" />
|
||||
public class AgentsAction : ManagerActionEvent
|
||||
{
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Agents".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Agents"; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ActionCompleteEventClass
|
||||
public override Type ActionCompleteEventClass()
|
||||
{
|
||||
return typeof(Event.AgentsCompleteEvent);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AgentsAction()
|
||||
/// <summary>
|
||||
/// Creates a new AgentsAction.
|
||||
/// </summary>
|
||||
public AgentsAction()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
50
Asterisk.2013/Asterisk.NET/Manager/Action/ChallengeAction.cs
Normal file
50
Asterisk.2013/Asterisk.NET/Manager/Action/ChallengeAction.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ChallengeAction requests a challenge from the server to use when logging
|
||||
/// in using challenge/response. Sending this action to the asterisk server
|
||||
/// results in a ChallengeResponse being received from the server.
|
||||
/// </summary>
|
||||
/// <seealso cref="Manager.Action.LoginAction"/>
|
||||
/// <seealso cref="Manager.Response.ChallengeResponse"/>
|
||||
public class ChallengeAction : ManagerAction
|
||||
{
|
||||
private string authType;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Challenge".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Challenge"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digest alogrithm to use. Currently asterisk only supports "MD5".
|
||||
/// </summary>
|
||||
public string AuthType
|
||||
{
|
||||
get { return this.authType; }
|
||||
set { this.authType = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty ChallengeAction with MD5 algorithm
|
||||
/// </summary>
|
||||
public ChallengeAction()
|
||||
{
|
||||
this.authType = "MD5";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ChallengeAction that requests a new login challenge for use
|
||||
/// with the given digest algorithm.
|
||||
/// </summary>
|
||||
/// <param name="authType">the digest alogrithm to use.</param>
|
||||
public ChallengeAction(string authType)
|
||||
{
|
||||
this.authType = authType;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ChangeMonitorAction changes the monitoring filename of a channel.
|
||||
/// It has no effect if the channel is not monitored.<br/>
|
||||
/// It is implemented in <code>res/res_monitor.c</code>
|
||||
/// </summary>
|
||||
public class ChangeMonitorAction : ManagerAction
|
||||
{
|
||||
private string channel;
|
||||
private string file;
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "ChangeMonitor".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "ChangeMonitor"; }
|
||||
}
|
||||
#endregion
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Get/Set the name of the monitored channel.<br/>
|
||||
/// This property is mandatory.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return this.channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
#endregion
|
||||
#region File
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to which the voice data is written.<br/>
|
||||
/// This property is mandatory.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return this.file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ChangeMonitorAction()
|
||||
/// <summary>
|
||||
/// Creates a new empty ChangeMonitorAction.
|
||||
/// </summary>
|
||||
public ChangeMonitorAction()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
#region ChangeMonitorAction(string channel, string file)
|
||||
/// <summary>
|
||||
/// Creates a new ChangeMonitorAction that causes monitoring data for the
|
||||
/// given channel to be written to the given file(s).
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel that is monitored</param>
|
||||
/// <param name="file">the (base) name of the file(s) to which the voice data is written</param>
|
||||
public ChangeMonitorAction(string channel, string file)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.file = file;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
45
Asterisk.2013/Asterisk.NET/Manager/Action/CommandAction.cs
Normal file
45
Asterisk.2013/Asterisk.NET/Manager/Action/CommandAction.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The CommandAction sends a command line interface (CLI) command to the asterisk server.<br/>
|
||||
/// For a list of supported commands type <code>help</code> on asterisk's command line.
|
||||
/// </summary>
|
||||
public class CommandAction : ManagerAction
|
||||
{
|
||||
protected internal string command;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Command".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Command"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the CLI command to send to the asterisk server.
|
||||
/// </summary>
|
||||
public string Command
|
||||
{
|
||||
get { return this.command; }
|
||||
set { this.command = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CommandAction.
|
||||
/// </summary>
|
||||
public CommandAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new CommandAction with the given command.
|
||||
/// </summary>
|
||||
/// <param name="command">the CLI command to execute.</param>
|
||||
public CommandAction(string command)
|
||||
{
|
||||
this.command = command;
|
||||
}
|
||||
}
|
||||
}
|
67
Asterisk.2013/Asterisk.NET/Manager/Action/DBGetAction.cs
Normal file
67
Asterisk.2013/Asterisk.NET/Manager/Action/DBGetAction.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves an entry in the Asterisk database for a given family and key.<br/>
|
||||
/// If an entry is found a DBGetResponseEvent is sent by Asterisk containing the
|
||||
/// value, otherwise a ManagerError indicates that no entry matches.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.DBGetResponseEvent" />
|
||||
public class DBGetAction : ManagerActionEvent
|
||||
{
|
||||
private string family;
|
||||
private string key;
|
||||
|
||||
public override string Action
|
||||
{
|
||||
get { return "DBGet"; }
|
||||
}
|
||||
/// <summary> Returns the family of the key.
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns> the family of the key.
|
||||
/// </returns>
|
||||
/// <summary> Sets the family of the key.
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key.
|
||||
/// </param>
|
||||
public string Family
|
||||
{
|
||||
get { return family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the the key of the entry to retrieve.
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return key; }
|
||||
set { this.key = value; }
|
||||
}
|
||||
public override Type ActionCompleteEventClass()
|
||||
{
|
||||
return typeof(Event.DBGetResponseEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty DBGetAction.
|
||||
/// </summary>
|
||||
public DBGetAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DBGetAction that retrieves the value of the database entry
|
||||
/// with the given key in the given family.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key</param>
|
||||
/// <param name="key">the key of the entry to retrieve</param>
|
||||
public DBGetAction(string family, string key)
|
||||
{
|
||||
this.family = family;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
64
Asterisk.2013/Asterisk.NET/Manager/Action/DBPutAction.cs
Normal file
64
Asterisk.2013/Asterisk.NET/Manager/Action/DBPutAction.cs
Normal file
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds or updates an entry in the Asterisk database for a given family, key, and value.<br/>
|
||||
/// Available since Asterisk 1.2
|
||||
/// </summary>
|
||||
public class DBPutAction : ManagerAction
|
||||
{
|
||||
private string family;
|
||||
private string key;
|
||||
private string val;
|
||||
|
||||
override public string Action
|
||||
{
|
||||
get { return "DBPut"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the family of the key to set.
|
||||
/// </summary>
|
||||
public string Family
|
||||
{
|
||||
get { return this.family; }
|
||||
set { this.family = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the the key to set.
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return this.key; }
|
||||
set { this.key = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the value to set.
|
||||
/// </summary>
|
||||
public string Val
|
||||
{
|
||||
get { return val; }
|
||||
set { this.val = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty DBPutAction.
|
||||
/// </summary>
|
||||
public DBPutAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new DBPutAction that sets the value of the database entry with the given key in the given family.
|
||||
/// </summary>
|
||||
/// <param name="family">the family of the key</param>
|
||||
/// <param name="key">the key of the entry to set</param>
|
||||
/// <param name="val">the value to set</param>
|
||||
public DBPutAction(string family, string key, string val)
|
||||
{
|
||||
this.family = family;
|
||||
this.key = key;
|
||||
this.val = val;
|
||||
}
|
||||
}
|
||||
}
|
50
Asterisk.2013/Asterisk.NET/Manager/Action/EventsAction.cs
Normal file
50
Asterisk.2013/Asterisk.NET/Manager/Action/EventsAction.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// With the EventsAction you can specify what kind of events should be sent to this manager connection.
|
||||
/// </summary>
|
||||
public class EventsAction : ManagerAction
|
||||
{
|
||||
private string eventMask;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Events".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Events"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the event mask.<br/>
|
||||
/// Set to "on" if all events should be send, "off" if not events should be
|
||||
/// sent or a combination of "system", "call" and "log" (separated by ',') to
|
||||
/// specify what kind of events should be sent.
|
||||
/// </summary>
|
||||
public string EventMask
|
||||
{
|
||||
get { return this.eventMask; }
|
||||
set { this.eventMask = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty EventsAction.
|
||||
/// </summary>
|
||||
public EventsAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new EventsAction that applies the given event mask to the current manager connection.
|
||||
/// </summary>
|
||||
/// <param name="eventMask">the event mask.<br/>
|
||||
/// Set to "on" if all events should be send, "off" if not events should be sent
|
||||
/// or a combination of "system", "call" and "log" (separated by ',') to specify what kind of events should be sent.
|
||||
/// </param>
|
||||
public EventsAction(string eventMask)
|
||||
{
|
||||
this.eventMask = eventMask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ExtensionStateAction queries the state of an extension in a given context.
|
||||
/// </summary>
|
||||
public class ExtensionStateAction : ManagerAction
|
||||
{
|
||||
private string exten;
|
||||
private string context;
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "ExtensionState".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "ExtensionState"; }
|
||||
}
|
||||
#endregion
|
||||
#region Exten
|
||||
/// <summary>
|
||||
/// Get/Set the extension to query.
|
||||
/// </summary>
|
||||
public string Exten
|
||||
{
|
||||
get { return exten; }
|
||||
set { this.exten = value; }
|
||||
}
|
||||
#endregion
|
||||
#region Context
|
||||
/// <summary>
|
||||
/// Get/Set the name of the context that contains the extension to query.
|
||||
/// </summary>
|
||||
public string Context
|
||||
{
|
||||
get { return context; }
|
||||
set { this.context = value; }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
54
Asterisk.2013/Asterisk.NET/Manager/Action/GetConfigAction.cs
Normal file
54
Asterisk.2013/Asterisk.NET/Manager/Action/GetConfigAction.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Asterisk.NET.Manager.Response;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The GetConfigAction sends a GetConfig command to the asterisk server.
|
||||
/// </summary>
|
||||
public class GetConfigAction : ManagerActionResponse
|
||||
{
|
||||
private string filename;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetConfigAction.
|
||||
/// </summary>
|
||||
public GetConfigAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action.
|
||||
/// </summary>
|
||||
public override string Action
|
||||
{
|
||||
get { return "GetConfig"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action.
|
||||
/// </summary>
|
||||
/// <param name="filename">the configuration filename.</param>
|
||||
/// </summary>
|
||||
public GetConfigAction(string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/Set the configuration filename.
|
||||
/// </summary>
|
||||
public string Filename
|
||||
{
|
||||
get { return this.filename; }
|
||||
set { this.filename = value; }
|
||||
}
|
||||
|
||||
public override object ActionCompleteResponseClass()
|
||||
{
|
||||
return new GetConfigResponse();
|
||||
}
|
||||
}
|
||||
}
|
65
Asterisk.2013/Asterisk.NET/Manager/Action/GetVarAction.cs
Normal file
65
Asterisk.2013/Asterisk.NET/Manager/Action/GetVarAction.cs
Normal file
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The GetVarAction queries for a channel variable.
|
||||
/// </summary>
|
||||
public class GetVarAction : ManagerAction
|
||||
{
|
||||
private string channel;
|
||||
private string varName;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty GetVarAction.
|
||||
/// </summary>
|
||||
public GetVarAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetVarAction that queries for the given global variable.
|
||||
/// </summary>
|
||||
/// <param name="variable">the name of the global variable to query.</param>
|
||||
public GetVarAction(string variable)
|
||||
{
|
||||
this.varName = variable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new GetVarAction that queries for the given local channel variable.
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel, for example "SIP/1234-9cd".</param>
|
||||
/// <param name="variable">the name of the variable to query.</param>
|
||||
public GetVarAction(string channel, string variable)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.varName = variable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "GetVar".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "GetVar"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the channel, if you query for a local channel variable.
|
||||
/// Leave empty to query for a global variable.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return this.channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the variable to query.
|
||||
/// </summary>
|
||||
public string Variable
|
||||
{
|
||||
get { return this.varName; }
|
||||
set { this.varName = value; }
|
||||
}
|
||||
}
|
||||
}
|
44
Asterisk.2013/Asterisk.NET/Manager/Action/HangupAction.cs
Normal file
44
Asterisk.2013/Asterisk.NET/Manager/Action/HangupAction.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The HangupAction causes the pbx to hang up a given channel.
|
||||
/// </summary>
|
||||
public class HangupAction : ManagerAction
|
||||
{
|
||||
private string channel;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty HangupAction.
|
||||
/// </summary>
|
||||
public HangupAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new HangupAction that hangs up the given channel.
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to hangup.</param>
|
||||
public HangupAction(string channel)
|
||||
{
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Hangup".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Hangup"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the channel to hangup.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return this.channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
}
|
||||
}
|
128
Asterisk.2013/Asterisk.NET/Manager/Action/LoginAction.cs
Normal file
128
Asterisk.2013/Asterisk.NET/Manager/Action/LoginAction.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The LoginAction authenticates the connection.<br/>
|
||||
/// A successful login is the precondition for sending any other action except
|
||||
/// for the ChallengeAction.<br/>
|
||||
/// An unsuccessful login results in an ManagerError being received from the
|
||||
/// server with a message set to "Authentication failed" and the socket being
|
||||
/// closed by Asterisk.
|
||||
/// </summary>
|
||||
/// <seealso cref="Manager.Action.ChallengeAction" />
|
||||
/// <seealso cref="Manager.Response.ManagerError" />
|
||||
public class LoginAction : ManagerAction
|
||||
{
|
||||
private string username;
|
||||
private string secret;
|
||||
private string authType;
|
||||
private string key;
|
||||
private string events;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Login".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Login"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the username as configured in asterik's <code>manager.conf</code>.</summary>
|
||||
public string Username
|
||||
{
|
||||
get { return this.username; }
|
||||
set { this.username = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the secret to use when using cleartext login.<br/>
|
||||
/// The secret contains the user's password as configured in Asterisk's <code>manager.conf</code>.<br/>
|
||||
/// The secret and key properties are mutually exclusive.
|
||||
/// </summary>
|
||||
public string Secret
|
||||
{
|
||||
get { return this.secret; }
|
||||
set { this.secret = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the digest alogrithm when using challenge/response.<br/>
|
||||
/// The digest algorithm is used to create the key based on the challenge and
|
||||
/// the user's password.<br/>
|
||||
/// Currently Asterisk supports only "MD5".
|
||||
/// </summary>
|
||||
public string AuthType
|
||||
{
|
||||
get { return this.authType; }
|
||||
set { this.authType = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the key.
|
||||
/// </summary>
|
||||
public string Key
|
||||
{
|
||||
get { return this.key; }
|
||||
set { this.key = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the event mask.<br/>
|
||||
/// Set to "on" if all events should be send, "off" if not events should be sent or a combination of
|
||||
/// "system", "call" and "log" (separated by ',') to specify what kind of events should be sent.
|
||||
/// </summary>
|
||||
public string Events
|
||||
{
|
||||
get { return this.events; }
|
||||
set { this.events = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty LoginAction.
|
||||
/// </summary>
|
||||
public LoginAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LoginAction that performs a cleartext login.<br/>
|
||||
/// You should not use cleartext login if you are concerned about security and login with a password hash instead.
|
||||
/// </summary>
|
||||
/// <param name="username">the username as configured in Asterisk's <code>manager.conf</code></param>
|
||||
/// <param name="secret">the user's password as configured in Asterisk's <code>manager.conf</code></param>
|
||||
/// <seealso cref="Manager.Action.ChallengeAction" />
|
||||
public LoginAction(string username, string secret)
|
||||
{
|
||||
this.username = username;
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LoginAction that performs a login via challenge/response.
|
||||
/// </summary>
|
||||
/// <param name="username">the username as configured in Asterisk's <code>manager.conf</code></param>
|
||||
/// <param name="authType">the digest alogrithm, must match the digest algorithm that was used with the corresponding ChallengeAction.</param>
|
||||
/// <param name="key">the hash of the user's password and the challenge</param>
|
||||
public LoginAction(string username, string authType, string key)
|
||||
{
|
||||
this.username = username;
|
||||
this.authType = authType;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LoginAction that performs a login via challenge/response.
|
||||
/// </summary>
|
||||
/// <param name="username">the username as configured in Asterisk's <code>manager.conf</code></param>
|
||||
/// <param name="authType">the digest alogrithm, must match the digest algorithm that was used with the corresponding ChallengeAction.</param>
|
||||
/// <param name="key">the hash of the user's password and the challenge</param>
|
||||
/// <param name="events">the event mask.<br/>
|
||||
/// Set to "on" if all events should be send, "off" if not events should be sent
|
||||
/// or a combination of "system", "call" and "log" (separated by ',') to specify what kind of events should be sent.
|
||||
/// </param>
|
||||
public LoginAction(string username, string authType, string key, string events)
|
||||
{
|
||||
this.username = username;
|
||||
this.authType = authType;
|
||||
this.key = key;
|
||||
this.events = events;
|
||||
}
|
||||
}
|
||||
}
|
25
Asterisk.2013/Asterisk.NET/Manager/Action/LogoffAction.cs
Normal file
25
Asterisk.2013/Asterisk.NET/Manager/Action/LogoffAction.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The LogoffAction causes the server to close the connection.
|
||||
/// </summary>
|
||||
public class LogoffAction : ManagerAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Logoff".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Logoff"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new LogoffAction.
|
||||
/// </summary>
|
||||
public LogoffAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The MailboxCountAction queries the number of unread and read messages in a mailbox.<br/>
|
||||
/// The MailboxCountAction returns a MailboxStatusResponse.
|
||||
/// </summary>
|
||||
/// <seealso cref="Manager.Response.MailboxCountResponse" />
|
||||
public class MailboxCountAction : ManagerAction
|
||||
{
|
||||
private string mailbox;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "MailboxCount".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "MailboxCount"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the mailbox to query.<br/>
|
||||
/// This can either be only the number of the mailbox or a string of the form
|
||||
/// mailboxnumber@context.If no context is specified "default" is assumed.<br/>
|
||||
/// This property is mandatory.
|
||||
/// </summary>
|
||||
public string Mailbox
|
||||
{
|
||||
get { return this.mailbox; }
|
||||
set { this.mailbox = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty MailboxCountAction.
|
||||
/// </summary>
|
||||
public MailboxCountAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new MailboxCountAction that queries the number of unread and
|
||||
/// read messages in the given mailbox.
|
||||
/// </summary>
|
||||
/// <param name="mailbox">the name of the mailbox to query.<br/>
|
||||
/// This can either be only the number of the mailbox or a string
|
||||
/// of the form mailboxnumber@context.If no context is specified
|
||||
/// "default" is assumed.
|
||||
/// </param>
|
||||
public MailboxCountAction(string mailbox)
|
||||
{
|
||||
this.mailbox = mailbox;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The MailboxStatusAction checks if a mailbox contains waiting messages.<br/>
|
||||
/// The MailboxStatusAction returns a MailboxStatusResponse.
|
||||
/// </summary>
|
||||
/// <seealso cref="Manager.Response.MailboxStatusResponse" />
|
||||
public class MailboxStatusAction : ManagerAction
|
||||
{
|
||||
private string mailbox;
|
||||
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "MailboxStatus".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "MailboxStatus"; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Get/Set the name of the mailbox to query.<br/>
|
||||
/// This can either be only the name of the mailbox or a string of the form
|
||||
/// mailboxnumber@context. If no context is specified "default" is assumed.<br/>
|
||||
/// Multiple mailboxes may be given, separated by ','. In this case the
|
||||
/// action checks whether at least one of the given mailboxes has waiting
|
||||
/// messages.<br/>
|
||||
/// This property is mandatory.<br/>
|
||||
/// Example: "1234,1235@mycontext"
|
||||
/// </summary>
|
||||
public string Mailbox
|
||||
{
|
||||
get { return this.mailbox; }
|
||||
set { this.mailbox = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty MailboxStatusAction.
|
||||
/// </summary>
|
||||
public MailboxStatusAction()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new MailboxStatusAction that checks for waiting messages in the given mailbox.
|
||||
/// </summary>
|
||||
/// <param name="mailbox">the name of the mailbox to check.<br/>
|
||||
/// This can either be only the number of the mailbox or a string
|
||||
/// of the form mailboxnumber@context.If no context is specified
|
||||
/// "default" is assumed.
|
||||
/// </param>
|
||||
public MailboxStatusAction(string mailbox)
|
||||
{
|
||||
this.mailbox = mailbox;
|
||||
}
|
||||
}
|
||||
}
|
66
Asterisk.2013/Asterisk.NET/Manager/Action/ManagerAction.cs
Normal file
66
Asterisk.2013/Asterisk.NET/Manager/Action/ManagerAction.cs
Normal file
|
@ -0,0 +1,66 @@
|
|||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// This class implements the ManagerAction interface
|
||||
/// and can serve as base class for your concrete Action implementations.
|
||||
/// </summary>
|
||||
public abstract class ManagerAction
|
||||
{
|
||||
private string actionId;
|
||||
private string server;
|
||||
private string proxyKey;
|
||||
|
||||
/// <summary>
|
||||
/// Manager API Action key. Also use as ProxyAction key to <see cref="ProxyAction">ProxyAction</see> actions.
|
||||
/// </summary>
|
||||
public abstract string Action
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
#region ActionId
|
||||
public string ActionId
|
||||
{
|
||||
get { return this.actionId; }
|
||||
set { this.actionId = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Server
|
||||
/// <summary>
|
||||
/// Specify a server to which to send your commands (x.x.x.x or hostname).<br/>
|
||||
/// This should match the server name specified in your config file's "host" entry.
|
||||
/// If you do not specify a server, the proxy will pick the first one it finds -- fine in single-server configurations.
|
||||
/// </summary>
|
||||
public string Server
|
||||
{
|
||||
get { return this.server; }
|
||||
set { this.server = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ProxyKey
|
||||
/// <summary>
|
||||
/// You can use this as a simple authentication mechanism.<br/>
|
||||
/// Rather than have to login with a username & password,
|
||||
/// you can specify a <b>ProxyKey</b> that must be passed from
|
||||
/// a client before requests are processed.<br/>
|
||||
/// This is helpful in situations where you would like to authenticate and
|
||||
/// execute an action in a single step.
|
||||
/// </summary>
|
||||
public virtual string ProxyKey
|
||||
{
|
||||
get { return this.proxyKey; }
|
||||
set { this.proxyKey = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Helper.ToString(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ManagerActionEvent is implemented by ManagerActions that
|
||||
/// return their result not in a ManagerResponse but by sending a series of events.<br/>
|
||||
/// The event type that indicates that Asterisk is finished is returned by the
|
||||
/// ActionCompleteEventClass property.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.ResponseEvent"/>
|
||||
public abstract class ManagerActionEvent : ManagerAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the event type that indicates that Asterisk is finished sending response events for this action.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.ResponseEvent"/>
|
||||
public abstract Type ActionCompleteEventClass();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using Asterisk.NET.Manager.Response;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ManagerActionResponse is implemented by ManagerActions that
|
||||
/// return their result in a custom ManagerResponse<br/>
|
||||
/// The response type that indicates that Asterisk is finished is returned by the
|
||||
/// ActionCompleteResponseClass property.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.ResponseEvent"/>
|
||||
public abstract class ManagerActionResponse : ManagerAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the response type that indicates that Asterisk is finished sending response for this action.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Response"/>
|
||||
public abstract object ActionCompleteResponseClass();
|
||||
}
|
||||
}
|
130
Asterisk.2013/Asterisk.NET/Manager/Action/MonitorAction.cs
Normal file
130
Asterisk.2013/Asterisk.NET/Manager/Action/MonitorAction.cs
Normal file
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The MonitorAction starts monitoring (recording) a channel.<br/>
|
||||
/// It is implemented in <code>res/res_monitor.c</code>
|
||||
/// </summary>
|
||||
public class MonitorAction : ManagerAction
|
||||
{
|
||||
private string channel;
|
||||
private string file;
|
||||
private string format;
|
||||
private bool mix;
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Monitor".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Monitor"; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Get/Set the name of the channel to monitor.<br/>
|
||||
/// This property is mandatory.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return this.channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region File
|
||||
/// <summary>
|
||||
/// Get/Set the name of the file to which the voice data is written.<br/>
|
||||
/// If this property is not set it defaults to to the channel name as per CLI with the '/' replaced by '-'.
|
||||
/// </summary>
|
||||
public string File
|
||||
{
|
||||
get { return this.file; }
|
||||
set { this.file = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Format
|
||||
/// <summary>
|
||||
/// Get/Set the format to use for encoding the voice files.<br/>
|
||||
/// If this property is not set it defaults to "wav".
|
||||
/// </summary>
|
||||
public string Format
|
||||
{
|
||||
get { return this.format; }
|
||||
set { this.format = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Mix
|
||||
/// <summary>
|
||||
/// Returns true if the two voice files should be joined at the end of the call.
|
||||
/// </summary>
|
||||
public bool Mix
|
||||
{
|
||||
get { return this.mix; }
|
||||
set { this.mix = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MonitorAction()
|
||||
/// <summary>
|
||||
/// Creates a new empty MonitorAction.
|
||||
/// </summary>
|
||||
public MonitorAction()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MonitorAction(string channel, string file)
|
||||
/// <summary>
|
||||
/// Creates a new MonitorAction that starts monitoring the given channel and
|
||||
/// writes voice data to the given file(s).
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to monitor</param>
|
||||
/// <param name="file">the (base) name of the file(s) to which the voice data is written</param>
|
||||
public MonitorAction(string channel, string file)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.file = file;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MonitorAction(string channel, string file)
|
||||
/// <summary>
|
||||
/// Creates a new MonitorAction that starts monitoring the given channel and
|
||||
/// writes voice data to the given file(s).
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to monitor</param>
|
||||
/// <param name="file">the (base) name of the file(s) to which the voice data is written</param>
|
||||
/// <param name="format">the format to use for encoding the voice files</param>
|
||||
public MonitorAction(string channel, string file, string format)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.file = file;
|
||||
this.format = format;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MonitorAction(string channel, string file, string format, int mix)
|
||||
/// <summary>
|
||||
/// Creates a new MonitorAction that starts monitoring the given channel and
|
||||
/// writes voice data to the given file(s).
|
||||
/// </summary>
|
||||
/// <param name="channel">the name of the channel to monitor</param>
|
||||
/// <param name="file">the (base) name of the file(s) to which the voice data is written</param>
|
||||
/// <param name="format">the format to use for encoding the voice files</param>
|
||||
/// <param name="mix">true if the two voice files should be joined at the end of the call</param>
|
||||
public MonitorAction(string channel, string file, string format, bool mix)
|
||||
{
|
||||
this.channel = channel;
|
||||
this.file = file;
|
||||
this.format = format;
|
||||
this.mix = mix;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
239
Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs
Normal file
239
Asterisk.2013/Asterisk.NET/Manager/Action/OriginateAction.cs
Normal file
|
@ -0,0 +1,239 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The OriginateAction generates an outgoing call to the extension in the given
|
||||
/// context with the given priority or to a given application with optional
|
||||
/// parameters.<br/>
|
||||
/// If you want to connect to an extension use the properties context, exten and
|
||||
/// priority. If you want to connect to an application use the properties
|
||||
/// application and data if needed. Note that no call detail record will be
|
||||
/// written when directly connecting to an application, so it may be better to
|
||||
/// connect to an extension that starts the application you wish to connect to.<br/>
|
||||
/// The response to this action is sent when the channel has been answered and
|
||||
/// asterisk starts connecting it to the given extension. So be careful not to
|
||||
/// choose a too short timeout when waiting for the response.<br/>
|
||||
/// If you set async to <code>true</code> Asterisk reports an OriginateSuccess-
|
||||
/// and OriginateFailureEvents. The action id of these events equals the action
|
||||
/// id of this OriginateAction.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.OriginateSuccessEvent" />
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.OriginateFailureEvent" />
|
||||
public class OriginateAction : ManagerActionEvent
|
||||
{
|
||||
private string channel;
|
||||
private string exten;
|
||||
private string context;
|
||||
private int priority;
|
||||
private int timeout;
|
||||
private string callerId;
|
||||
private Dictionary<string, string> variables;
|
||||
private string account;
|
||||
private string application;
|
||||
private string data;
|
||||
private bool async;
|
||||
|
||||
#region Action
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Originate".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Originate"; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Account
|
||||
/// <summary>
|
||||
/// Get/Set the account code to use for the originated call.
|
||||
/// The account code is included in the call detail record generated for this call and will be used for billing.
|
||||
/// </summary>
|
||||
public string Account
|
||||
{
|
||||
get { return account; }
|
||||
set { this.account = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CallerId
|
||||
/// <summary>
|
||||
/// Get/Set the caller id to set on the outgoing channel.
|
||||
/// </summary>
|
||||
public string CallerId
|
||||
{
|
||||
get { return callerId; }
|
||||
set { this.callerId = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Channel
|
||||
/// <summary>
|
||||
/// Get/Set Channel on which to originate the call (The same as you specify in the Dial application command)<br/>
|
||||
/// This property is required.
|
||||
/// </summary>
|
||||
public string Channel
|
||||
{
|
||||
get { return channel; }
|
||||
set { this.channel = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Context
|
||||
/// <summary>
|
||||
/// Get/Set the name of the context of the extension to connect to.
|
||||
/// If you set the context you also have to set the exten and priority properties.
|
||||
/// </summary>
|
||||
public string Context
|
||||
{
|
||||
get { return context; }
|
||||
set { this.context = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Exten
|
||||
/// <summary>
|
||||
/// Get/Ser the extension to connect to.
|
||||
/// If you set the extension you also have to set the context and priority properties.
|
||||
/// </summary>
|
||||
public string Exten
|
||||
{
|
||||
get { return exten; }
|
||||
set { this.exten = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Priority
|
||||
/// <summary>
|
||||
/// Get /Set the priority of the extension to connect to.
|
||||
/// If you set the priority you also have to set the context and exten properties.
|
||||
/// </summary>
|
||||
public int Priority
|
||||
{
|
||||
get { return priority; }
|
||||
set { this.priority = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Application
|
||||
/// <summary>
|
||||
/// Get/Set Application to use on connect (use Data for parameters)
|
||||
/// </summary>
|
||||
public string Application
|
||||
{
|
||||
get { return application; }
|
||||
set { this.application = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Data
|
||||
/// <summary>
|
||||
/// Get/Set the parameters to pass to the application.
|
||||
/// Data if Application parameter is user
|
||||
/// </summary>
|
||||
/// <summary> Sets the parameters to pass to the application.</summary>
|
||||
public string Data
|
||||
{
|
||||
get { return data; }
|
||||
set { this.data = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Async
|
||||
/// <summary>
|
||||
/// Get/Set <code>true</code> if this is a fast origination.<br/>
|
||||
/// For the origination to be asynchronous (allows multiple calls to be generated without waiting for a response).<br/>
|
||||
/// Will send OriginateSuccess- and OriginateFailureEvents.
|
||||
/// </summary>
|
||||
public bool Async
|
||||
{
|
||||
get { return async; }
|
||||
set { this.async = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ActionCompleteEventClass
|
||||
public override Type ActionCompleteEventClass()
|
||||
{
|
||||
return typeof(Event.OriginateResponseEvent);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Timeout
|
||||
/// <summary>
|
||||
/// Get/Set the timeout for the origination in seconds.<br/>
|
||||
/// The channel must be answered within this time, otherwise the origination
|
||||
/// is considered to have failed and an OriginateFailureEvent is generated.<br/>
|
||||
/// If not set, Asterisk assumes a default value of 30000 meaning 30 seconds.
|
||||
/// </summary>
|
||||
public int Timeout
|
||||
{
|
||||
get { return timeout; }
|
||||
set { this.timeout = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Variable
|
||||
/// <summary>
|
||||
/// Get/Set the variables to set on the originated call.<br/>
|
||||
/// Variable assignments are of the form "VARNAME=VALUE". You can specify
|
||||
/// multiple variable assignments separated by the '|' character.<br/>
|
||||
/// Example: "VAR1=abc|VAR2=def" sets the channel variables VAR1 to "abc" and VAR2 to "def".
|
||||
/// </summary>
|
||||
public string Variable
|
||||
{
|
||||
get { return Helper.JoinVariables(variables, Common.VAR_DELIMITER, "="); }
|
||||
set { variables = Helper.ParseVariables(variables, value, Common.VAR_DELIMITER); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetVariables()
|
||||
/// <summary>
|
||||
/// Get the variables dictionary to set on the originated call.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> GetVariables()
|
||||
{
|
||||
return variables;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetVariables(IDictionary vars)
|
||||
/// <summary>
|
||||
/// Set the variables dictionary to set on the originated call.
|
||||
/// </summary>
|
||||
public void SetVariables(Dictionary<string, string> vars)
|
||||
{
|
||||
this.variables = vars;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetVariable(string name, string val)
|
||||
/// <summary>
|
||||
/// Gets a variable on the originated call. Replaces any existing variable with the same name.
|
||||
/// </summary>
|
||||
public string GetVariable(string key)
|
||||
{
|
||||
if (variables == null)
|
||||
return string.Empty;
|
||||
return variables[key];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetVariable(string name, string val)
|
||||
/// <summary>
|
||||
/// Sets a variable dictionary on the originated call. Replaces any existing variable with the same name.
|
||||
/// </summary>
|
||||
public void SetVariable(string key, string value)
|
||||
{
|
||||
if (variables == null)
|
||||
variables = new Dictionary<string, string>();
|
||||
if (variables.ContainsKey(key))
|
||||
variables[key] = value;
|
||||
else
|
||||
variables.Add(key, value);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The ParkedCallsAction requests a list of all currently parked calls.<br/>
|
||||
/// For each active channel a ParkedCallEvent is generated. After all parked
|
||||
/// calls have been reported a ParkedCallsCompleteEvent is generated.
|
||||
/// </summary>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.ParkedCallEvent"/>
|
||||
/// <seealso cref="Asterisk.NET.Manager.Event.ParkedCallsCompleteEvent"/>
|
||||
public class ParkedCallsAction : ManagerActionEvent
|
||||
{
|
||||
/// <summary> Get the name of this action, i.e. "ParkedCalls".</summary>
|
||||
public override string Action
|
||||
{
|
||||
get { return "ParkedCalls"; }
|
||||
}
|
||||
|
||||
public override Type ActionCompleteEventClass()
|
||||
{
|
||||
return typeof(Event.ParkedCallsCompleteEvent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ParkedCallsAction.
|
||||
/// </summary>
|
||||
public ParkedCallsAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
26
Asterisk.2013/Asterisk.NET/Manager/Action/PingAction.cs
Normal file
26
Asterisk.2013/Asterisk.NET/Manager/Action/PingAction.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace Asterisk.NET.Manager.Action
|
||||
{
|
||||
/// <summary>
|
||||
/// The PingAction will ellicit a 'Pong' response, it is used to keep the manager
|
||||
/// connection open and performs no operation.
|
||||
/// </summary>
|
||||
public class PingAction : ManagerAction
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the name of this action, i.e. "Ping".
|
||||
/// </summary>
|
||||
override public string Action
|
||||
{
|
||||
get { return "Ping"; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new PingAction.
|
||||
/// </summary>
|
||||
public PingAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue