diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln index 5e27743f6a..d31ca4a53e 100644 --- a/Freeswitch.2008.sln +++ b/Freeswitch.2008.sln @@ -2036,18 +2036,18 @@ Global {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x64.Build.0 = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|Win32.ActiveCfg = Debug|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|Win32.Build.0 = Debug|Win32 - {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.ActiveCfg = Debug|Win32 - {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.Build.0 = Debug|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.ActiveCfg = Debug|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.Build.0 = Debug|x64 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|Win32.ActiveCfg = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|Win32.Build.0 = Release|Win32 - {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.ActiveCfg = Release|Win32 - {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.Build.0 = Release|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.ActiveCfg = Release|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.Build.0 = Release|x64 {7EB71250-F002-4ED8-92CA-CA218114537A}.All|Win32.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.All|x64.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|Win32.ActiveCfg = Debug|Win32 - {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|x64.ActiveCfg = Debug|Win32 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|x64.ActiveCfg = Debug|x64 {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|Win32.ActiveCfg = Release|Win32 - {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|x64.ActiveCfg = Release|Win32 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|x64.ActiveCfg = Release|x64 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|Win32.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|x64.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Debug|Win32.ActiveCfg = Debug|Win32 @@ -2057,9 +2057,9 @@ Global {464AAB78-5489-4916-BE51-BF8D61822311}.All|Win32.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.All|x64.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|Win32.ActiveCfg = Debug|Win32 - {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|x64.ActiveCfg = Debug|Win32 + {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|x64.ActiveCfg = Debug|x64 {464AAB78-5489-4916-BE51-BF8D61822311}.Release|Win32.ActiveCfg = Release|Win32 - {464AAB78-5489-4916-BE51-BF8D61822311}.Release|x64.ActiveCfg = Release|Win32 + {464AAB78-5489-4916-BE51-BF8D61822311}.Release|x64.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.All|Win32.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64.Build.0 = Release|x64 @@ -2474,24 +2474,24 @@ Global {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x64.Build.0 = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|Win32.ActiveCfg = Debug|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|Win32.Build.0 = Debug|Win32 - {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.ActiveCfg = Debug|Win32 - {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.Build.0 = Debug|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.ActiveCfg = Debug|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.Build.0 = Debug|x64 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|Win32.ActiveCfg = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|Win32.Build.0 = Release|Win32 - {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.ActiveCfg = Release|Win32 - {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.Build.0 = Release|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.ActiveCfg = Release|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.Build.0 = Release|x64 {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|Win32.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|x64.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|Win32.ActiveCfg = Debug|Win32 - {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|x64.ActiveCfg = Debug|Win32 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|x64.ActiveCfg = Debug|x64 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|Win32.ActiveCfg = Release|Win32 - {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|x64.ActiveCfg = Release|Win32 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|x64.ActiveCfg = Release|x64 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|Win32.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|x64.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|Win32.ActiveCfg = Debug|Win32 - {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|x64.ActiveCfg = Debug|Win32 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|x64.ActiveCfg = Debug|x64 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|Win32.ActiveCfg = Release|Win32 - {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|x64.ActiveCfg = Release|Win32 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|x64.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|Win32.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64.Build.0 = Release|x64 diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln index 4729745778..5722802839 100644 --- a/Freeswitch.2010.sln +++ b/Freeswitch.2010.sln @@ -705,1734 +705,2908 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_h323", "src\mod\endpoin EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_distributor", "src\mod\applications\mod_distributor\mod_distributor.2010.vcxproj", "{5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}" EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "w32\Setup\Setup.wixproj", "{47213370-B933-487D-9F45-BCA26D7E2B6F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution All|Win32 = All|Win32 All|x64 = All|x64 + All|x64 Setup = All|x64 Setup + All|x86 Setup = All|x86 Setup Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 + Debug|x64 Setup = Debug|x64 Setup + Debug|x86 Setup = Debug|x86 Setup Release|Win32 = Release|Win32 Release|x64 = Release|x64 + Release|x64 Setup = Release|x64 Setup + Release|x86 Setup = Release|x86 Setup EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|Win32.ActiveCfg = Release|x64 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|x64.ActiveCfg = Release|x64 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|x64.Build.0 = Release|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|x64 Setup.ActiveCfg = Release|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|x64 Setup.Build.0 = Release|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.All|x86 Setup.ActiveCfg = Release|x64 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|Win32.ActiveCfg = Debug|Win32 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|Win32.Build.0 = Debug|Win32 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|x64.ActiveCfg = Debug|x64 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|x64.Build.0 = Debug|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|Win32.ActiveCfg = Release|Win32 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|Win32.Build.0 = Release|Win32 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|x64.ActiveCfg = Release|x64 {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|x64.Build.0 = Release|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|x64 Setup.ActiveCfg = Release|x64 + {1AF3A893-F7BE-43DD-B697-8AB2397C0D67}.Release|x86 Setup.ActiveCfg = Release|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|Win32.ActiveCfg = Release|x64 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|x64.ActiveCfg = Release|x64 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|x64.Build.0 = Release|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|x64 Setup.ActiveCfg = Release|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|x64 Setup.Build.0 = Release|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.All|x86 Setup.ActiveCfg = Release|x64 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|Win32.ActiveCfg = Debug|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|Win32.Build.0 = Debug|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|x64.ActiveCfg = Debug|x64 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|x64.Build.0 = Debug|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|Win32.ActiveCfg = Release|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|Win32.Build.0 = Release|Win32 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|x64.ActiveCfg = Release|x64 {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|x64.Build.0 = Release|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|x64 Setup.ActiveCfg = Release|x64 + {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}.Release|x86 Setup.ActiveCfg = Release|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|Win32.ActiveCfg = Release Passthrough|x64 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|x64.ActiveCfg = Release Passthrough|x64 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|x64.Build.0 = Release Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|x64 Setup.ActiveCfg = Release Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|x64 Setup.Build.0 = Release Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.All|x86 Setup.ActiveCfg = Release Passthrough|x64 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|Win32.ActiveCfg = Debug Passthrough|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|Win32.Build.0 = Debug Passthrough|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|x64.ActiveCfg = Debug Passthrough|x64 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|x64.Build.0 = Debug Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|x64 Setup.ActiveCfg = Debug Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Debug|x86 Setup.ActiveCfg = Debug Passthrough|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|Win32.ActiveCfg = Release Passthrough|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|Win32.Build.0 = Release Passthrough|Win32 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|x64.ActiveCfg = Release Passthrough|x64 {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|x64.Build.0 = Release Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|x64 Setup.ActiveCfg = Release Passthrough|x64 + {1D95CD95-0DE2-48C3-AC23-D5C7D1C9C0F0}.Release|x86 Setup.ActiveCfg = Release Passthrough|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|Win32.ActiveCfg = Release|x64 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|x64.ActiveCfg = Release|x64 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|x64.Build.0 = Release|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|x64 Setup.ActiveCfg = Release|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|x64 Setup.Build.0 = Release|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.All|x86 Setup.ActiveCfg = Release|x64 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|Win32.ActiveCfg = Debug|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|Win32.Build.0 = Debug|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|x64.ActiveCfg = Debug|x64 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|x64.Build.0 = Debug|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|Win32.ActiveCfg = Release|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|Win32.Build.0 = Release|Win32 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|x64.ActiveCfg = Release|x64 {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|x64.Build.0 = Release|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|x64 Setup.ActiveCfg = Release|x64 + {AFAC0568-7548-42D5-9F6A-8D3400A1E4F6}.Release|x86 Setup.ActiveCfg = Release|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|Win32.ActiveCfg = Release|x64 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|x64.ActiveCfg = Release|x64 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|x64.Build.0 = Release|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|x64 Setup.ActiveCfg = Release|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|x64 Setup.Build.0 = Release|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.All|x86 Setup.ActiveCfg = Release|x64 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|Win32.ActiveCfg = Debug|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|Win32.Build.0 = Debug|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|x64.ActiveCfg = Debug|x64 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|x64.Build.0 = Debug|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|Win32.ActiveCfg = Release|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|Win32.Build.0 = Release|Win32 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|x64.ActiveCfg = Release|x64 {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|x64.Build.0 = Release|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|x64 Setup.ActiveCfg = Release|x64 + {5FD31A25-5D83-4794-8BEE-904DAD84CE71}.Release|x86 Setup.ActiveCfg = Release|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|Win32.ActiveCfg = Release|x64 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|x64.ActiveCfg = Release|x64 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|x64.Build.0 = Release|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|x64 Setup.ActiveCfg = Release|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|x64 Setup.Build.0 = Release|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.All|x86 Setup.ActiveCfg = Release|x64 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|Win32.ActiveCfg = Debug|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|Win32.Build.0 = Debug|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|x64.ActiveCfg = Debug|x64 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|x64.Build.0 = Debug|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|Win32.ActiveCfg = Release|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|Win32.Build.0 = Release|Win32 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|x64.ActiveCfg = Release|x64 {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|x64.Build.0 = Release|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|x64 Setup.ActiveCfg = Release|x64 + {5580D60E-0F77-4716-9CD4-B8E5986FA375}.Release|x86 Setup.ActiveCfg = Release|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.All|Win32.ActiveCfg = Release|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.All|x64.ActiveCfg = Release|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.All|x64 Setup.ActiveCfg = Release|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.All|x86 Setup.ActiveCfg = Release|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Debug|Win32.ActiveCfg = Debug|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Debug|x64.ActiveCfg = Debug|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Release|Win32.ActiveCfg = Release|Win32 {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Release|x64.ActiveCfg = Release|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Release|x64 Setup.ActiveCfg = Release|Win32 + {1A1FF289-4FD6-4285-A422-D31DD67A4723}.Release|x86 Setup.ActiveCfg = Release|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|Win32.ActiveCfg = Release|x64 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|x64.ActiveCfg = Release|x64 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|x64.Build.0 = Release|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|x64 Setup.ActiveCfg = Release|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|x64 Setup.Build.0 = Release|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.All|x86 Setup.ActiveCfg = Release|x64 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|Win32.ActiveCfg = Debug|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|Win32.Build.0 = Debug|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|x64.ActiveCfg = Debug|x64 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|x64.Build.0 = Debug|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|Win32.ActiveCfg = Release|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|Win32.Build.0 = Release|Win32 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|x64.ActiveCfg = Release|x64 {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|x64.Build.0 = Release|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|x64 Setup.ActiveCfg = Release|x64 + {07113B25-D3AF-4E04-BA77-4CD1171F022C}.Release|x86 Setup.ActiveCfg = Release|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|Win32.ActiveCfg = Release MS-LDAP|x64 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|x64.ActiveCfg = Release MS-LDAP|x64 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|x64.Build.0 = Release MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|x64 Setup.ActiveCfg = Release MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|x64 Setup.Build.0 = Release MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.All|x86 Setup.ActiveCfg = Release MS-LDAP|x64 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|Win32.ActiveCfg = Debug MS-LDAP|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|Win32.Build.0 = Debug MS-LDAP|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|x64.ActiveCfg = Debug MS-LDAP|x64 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|x64.Build.0 = Debug MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|x64 Setup.ActiveCfg = Debug MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Debug|x86 Setup.ActiveCfg = Debug MS-LDAP|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|Win32.ActiveCfg = Release MS-LDAP|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|Win32.Build.0 = Release MS-LDAP|Win32 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|x64.ActiveCfg = Release MS-LDAP|x64 {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|x64.Build.0 = Release MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|x64 Setup.ActiveCfg = Release MS-LDAP|x64 + {EC3E5C7F-EE09-47E2-80FE-546363D14A98}.Release|x86 Setup.ActiveCfg = Release MS-LDAP|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|Win32.ActiveCfg = Release|x64 {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|x64.ActiveCfg = Release|x64 {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|x64.Build.0 = Release|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|x64 Setup.ActiveCfg = Release|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|x64 Setup.Build.0 = Release|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.All|x86 Setup.ActiveCfg = Release|x64 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|Win32.ActiveCfg = Debug|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|Win32.Build.0 = Debug|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|x64.ActiveCfg = Debug|x64 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|x64.Build.0 = Debug|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|Win32.ActiveCfg = Release|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|Win32.Build.0 = Release|Win32 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|x64.ActiveCfg = Release|x64 {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|x64.Build.0 = Release|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|x64 Setup.ActiveCfg = Release|x64 + {A27CCA23-1541-4337-81A4-F0A6413078A0}.Release|x86 Setup.ActiveCfg = Release|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.All|Win32.ActiveCfg = Release|x64 {784113EF-44D9-4949-835D-7065D3C7AD08}.All|x64.ActiveCfg = Release|x64 {784113EF-44D9-4949-835D-7065D3C7AD08}.All|x64.Build.0 = Release|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.All|x64 Setup.ActiveCfg = Release|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.All|x64 Setup.Build.0 = Release|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.All|x86 Setup.ActiveCfg = Release|x64 {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|Win32.ActiveCfg = Debug|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|Win32.Build.0 = Debug|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|x64.ActiveCfg = Debug|x64 {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|x64.Build.0 = Debug|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|Win32.ActiveCfg = Release|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|Win32.Build.0 = Release|Win32 {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|x64.ActiveCfg = Release|x64 {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|x64.Build.0 = Release|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|x64 Setup.ActiveCfg = Release|x64 + {784113EF-44D9-4949-835D-7065D3C7AD08}.Release|x86 Setup.ActiveCfg = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.All|Win32.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.All|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.All|x64.Build.0 = Release|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.All|x64 Setup.ActiveCfg = Release|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.All|x64 Setup.Build.0 = Release|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.All|x86 Setup.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|Win32.ActiveCfg = Debug|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|Win32.Build.0 = Debug|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|x64.ActiveCfg = Debug|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|x64.Build.0 = Debug|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.ActiveCfg = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|Win32.Build.0 = Release|Win32 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.ActiveCfg = Release|x64 {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64.Build.0 = Release|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x64 Setup.ActiveCfg = Release|x64 + {89385C74-5860-4174-9CAF-A39E7C48909C}.Release|x86 Setup.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|Win32.ActiveCfg = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.ActiveCfg = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64.Build.0 = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64 Setup.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x64 Setup.Build.0 = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.All|x86 Setup.ActiveCfg = Release|x64 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|Win32.Build.0 = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64.ActiveCfg = Debug|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.ActiveCfg = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|Win32.Build.0 = Release|Win32 {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64 Setup.ActiveCfg = Release|x64 + {1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x86 Setup.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64 Setup.ActiveCfg = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64 Setup.Build.0 = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.All|x86 Setup.ActiveCfg = Release|x64 {692F6330-4D87-4C82-81DF-40DB5892636E}.Debug|Win32.ActiveCfg = Debug|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.Debug|x64.ActiveCfg = Debug|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|Win32.ActiveCfg = Release|Win32 {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64.ActiveCfg = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x64 Setup.ActiveCfg = Release|x64 + {692F6330-4D87-4C82-81DF-40DB5892636E}.Release|x86 Setup.ActiveCfg = Release|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|Win32.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64.Build.0 = Release|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64 Setup.ActiveCfg = Release|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x64 Setup.Build.0 = Release|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.All|x86 Setup.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|Win32.ActiveCfg = Debug|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|Win32.Build.0 = Debug|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|x64.ActiveCfg = Debug|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|x64.Build.0 = Debug|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|Win32.ActiveCfg = Release|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|Win32.Build.0 = Release|Win32 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|x64.ActiveCfg = Release|x64 {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|x64.Build.0 = Release|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|x64 Setup.ActiveCfg = Release|x64 + {D3EC0AFF-76FC-4210-A825-9A17410660A3}.Release|x86 Setup.ActiveCfg = Release|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|Win32.ActiveCfg = Release|x64 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|x64.ActiveCfg = Release|x64 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|x64.Build.0 = Release|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|x64 Setup.ActiveCfg = Release|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|x64 Setup.Build.0 = Release|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.All|x86 Setup.ActiveCfg = Release|x64 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|Win32.ActiveCfg = Debug|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|Win32.Build.0 = Debug|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|x64.ActiveCfg = Debug|x64 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|x64.Build.0 = Debug|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|Win32.ActiveCfg = Release|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|Win32.Build.0 = Release|Win32 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|x64.ActiveCfg = Release|x64 {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|x64.Build.0 = Release|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|x64 Setup.ActiveCfg = Release|x64 + {FFAA4C52-3A53-4F99-90C1-D59D1F0427F3}.Release|x86 Setup.ActiveCfg = Release|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|Win32.ActiveCfg = Release|x64 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|x64.ActiveCfg = Release|x64 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|x64.Build.0 = Release|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|x64 Setup.ActiveCfg = Release|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|x64 Setup.Build.0 = Release|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.All|x86 Setup.ActiveCfg = Release|x64 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|Win32.ActiveCfg = Debug|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|Win32.Build.0 = Debug|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|x64.ActiveCfg = Debug|x64 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|x64.Build.0 = Debug|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|Win32.ActiveCfg = Release|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|Win32.Build.0 = Release|Win32 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|x64.ActiveCfg = Release|x64 {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|x64.Build.0 = Release|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|x64 Setup.ActiveCfg = Release|x64 + {30A5B29C-983E-4580-9FD0-D647CCDCC7EB}.Release|x86 Setup.ActiveCfg = Release|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.All|Win32.ActiveCfg = Release|x64 {1C453396-D912-4213-89FD-9B489162B7B5}.All|x64.ActiveCfg = Release|x64 {1C453396-D912-4213-89FD-9B489162B7B5}.All|x64.Build.0 = Release|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.All|x64 Setup.ActiveCfg = Release|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.All|x64 Setup.Build.0 = Release|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.All|x86 Setup.ActiveCfg = Release|x64 {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|Win32.ActiveCfg = Debug|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|Win32.Build.0 = Debug|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|x64.ActiveCfg = Debug|x64 {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|x64.Build.0 = Debug|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.Release|Win32.ActiveCfg = Release|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.Release|Win32.Build.0 = Release|Win32 {1C453396-D912-4213-89FD-9B489162B7B5}.Release|x64.ActiveCfg = Release|x64 {1C453396-D912-4213-89FD-9B489162B7B5}.Release|x64.Build.0 = Release|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.Release|x64 Setup.ActiveCfg = Release|x64 + {1C453396-D912-4213-89FD-9B489162B7B5}.Release|x86 Setup.ActiveCfg = Release|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|Win32.ActiveCfg = Release|x64 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|x64.ActiveCfg = Release|x64 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|x64.Build.0 = Release|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|x64 Setup.ActiveCfg = Release|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|x64 Setup.Build.0 = Release|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.All|x86 Setup.ActiveCfg = Release|x64 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|Win32.ActiveCfg = Debug|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|Win32.Build.0 = Debug|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|x64.ActiveCfg = Debug|x64 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|x64.Build.0 = Debug|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|Win32.ActiveCfg = Release|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|Win32.Build.0 = Release|Win32 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|x64.ActiveCfg = Release|x64 {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|x64.Build.0 = Release|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|x64 Setup.ActiveCfg = Release|x64 + {CBEC7225-0C21-4DA8-978E-1F158F8AD950}.Release|x86 Setup.ActiveCfg = Release|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|Win32.ActiveCfg = Release|x64 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|x64.ActiveCfg = Release|x64 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|x64.Build.0 = Release|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|x64 Setup.ActiveCfg = Release|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|x64 Setup.Build.0 = Release|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.All|x86 Setup.ActiveCfg = Release|x64 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|Win32.ActiveCfg = Debug|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|Win32.Build.0 = Debug|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|x64.ActiveCfg = Debug|x64 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|x64.Build.0 = Debug|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|Win32.ActiveCfg = Release|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|Win32.Build.0 = Release|Win32 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|x64.ActiveCfg = Release|x64 {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|x64.Build.0 = Release|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|x64 Setup.ActiveCfg = Release|x64 + {B69247FA-ECD6-40ED-8E44-5CA6C3BAF9A4}.Release|x86 Setup.ActiveCfg = Release|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.All|Win32.ActiveCfg = Release|x64 {C24FB505-05D7-4319-8485-7540B44C8603}.All|x64.ActiveCfg = Release|x64 {C24FB505-05D7-4319-8485-7540B44C8603}.All|x64.Build.0 = Release|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.All|x64 Setup.ActiveCfg = Release|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.All|x64 Setup.Build.0 = Release|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.All|x86 Setup.ActiveCfg = Release|x64 {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|Win32.ActiveCfg = Debug|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|Win32.Build.0 = Debug|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|x64.ActiveCfg = Debug|x64 {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|x64.Build.0 = Debug|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.Release|Win32.ActiveCfg = Release|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.Release|Win32.Build.0 = Release|Win32 {C24FB505-05D7-4319-8485-7540B44C8603}.Release|x64.ActiveCfg = Release|x64 {C24FB505-05D7-4319-8485-7540B44C8603}.Release|x64.Build.0 = Release|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.Release|x64 Setup.ActiveCfg = Release|x64 + {C24FB505-05D7-4319-8485-7540B44C8603}.Release|x86 Setup.ActiveCfg = Release|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|Win32.ActiveCfg = Release|x64 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|x64.ActiveCfg = Release|x64 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|x64.Build.0 = Release|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|x64 Setup.ActiveCfg = Release|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|x64 Setup.Build.0 = Release|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.All|x86 Setup.ActiveCfg = Release|x64 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|Win32.ActiveCfg = Debug|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|Win32.Build.0 = Debug|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|x64.ActiveCfg = Debug|x64 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|x64.Build.0 = Debug|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|Win32.ActiveCfg = Release|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|Win32.Build.0 = Release|Win32 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|x64.ActiveCfg = Release|x64 {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|x64.Build.0 = Release|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|x64 Setup.ActiveCfg = Release|x64 + {B5881A85-FE70-4F64-8607-2CAAE52669C6}.Release|x86 Setup.ActiveCfg = Release|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.All|Win32.ActiveCfg = Release|x64 {05515420-16DE-4E63-BE73-85BE85BA5142}.All|x64.ActiveCfg = Release|x64 {05515420-16DE-4E63-BE73-85BE85BA5142}.All|x64.Build.0 = Release|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.All|x64 Setup.ActiveCfg = Release|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.All|x64 Setup.Build.0 = Release|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.All|x86 Setup.ActiveCfg = Release|x64 {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|Win32.ActiveCfg = Debug|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|Win32.Build.0 = Debug|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|x64.ActiveCfg = Debug|x64 {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|x64.Build.0 = Debug|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|Win32.ActiveCfg = Release|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|Win32.Build.0 = Release|Win32 {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|x64.ActiveCfg = Release|x64 {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|x64.Build.0 = Release|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|x64 Setup.ActiveCfg = Release|x64 + {05515420-16DE-4E63-BE73-85BE85BA5142}.Release|x86 Setup.ActiveCfg = Release|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.All|Win32.ActiveCfg = Release DLL|x64 {1906D736-08BD-4EE1-924F-B536249B9A54}.All|x64.ActiveCfg = Release DLL|x64 {1906D736-08BD-4EE1-924F-B536249B9A54}.All|x64.Build.0 = Release DLL|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.All|x64 Setup.ActiveCfg = Release DLL|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.All|x64 Setup.Build.0 = Release DLL|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.All|x86 Setup.ActiveCfg = Release DLL|x64 {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|Win32.ActiveCfg = Debug|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|Win32.Build.0 = Debug|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|x64.ActiveCfg = Debug|x64 {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|x64.Build.0 = Debug|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|Win32.ActiveCfg = Release|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|Win32.Build.0 = Release|Win32 {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|x64.ActiveCfg = Release|x64 {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|x64.Build.0 = Release|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|x64 Setup.ActiveCfg = Release|x64 + {1906D736-08BD-4EE1-924F-B536249B9A54}.Release|x86 Setup.ActiveCfg = Release|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|Win32.ActiveCfg = Release Dll|x64 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|x64.ActiveCfg = Release Dll|x64 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|x64.Build.0 = Release Dll|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|x64 Setup.ActiveCfg = Release Dll|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|x64 Setup.Build.0 = Release Dll|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.All|x86 Setup.ActiveCfg = Release Dll|x64 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|Win32.ActiveCfg = Debug|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|Win32.Build.0 = Debug|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|x64.ActiveCfg = Debug|x64 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|x64.Build.0 = Debug|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|Win32.ActiveCfg = Release|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|Win32.Build.0 = Release|Win32 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|x64.ActiveCfg = Release|x64 {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|x64.Build.0 = Release|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|x64 Setup.ActiveCfg = Release|x64 + {EEF031CB-FED8-451E-A471-91EC8D4F6750}.Release|x86 Setup.ActiveCfg = Release|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|Win32.ActiveCfg = Release DLL|x64 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|x64.ActiveCfg = Release DLL|x64 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|x64.Build.0 = Release DLL|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|x64 Setup.ActiveCfg = Release DLL|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|x64 Setup.Build.0 = Release DLL|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.All|x86 Setup.ActiveCfg = Release DLL|x64 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|Win32.ActiveCfg = Debug|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|Win32.Build.0 = Debug|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|x64.ActiveCfg = Debug|x64 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|x64.Build.0 = Debug|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|Win32.ActiveCfg = Release|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|Win32.Build.0 = Release|Win32 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|x64.ActiveCfg = Release|x64 {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|x64.Build.0 = Release|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|x64 Setup.ActiveCfg = Release|x64 + {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}.Release|x86 Setup.ActiveCfg = Release|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|Win32.ActiveCfg = Release DLL|x64 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|x64.ActiveCfg = Release DLL|x64 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|x64.Build.0 = Release DLL|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|x64 Setup.ActiveCfg = Release DLL|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|x64 Setup.Build.0 = Release DLL|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.All|x86 Setup.ActiveCfg = Release DLL|x64 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|Win32.ActiveCfg = Debug|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|Win32.Build.0 = Debug|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|x64.ActiveCfg = Debug|x64 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|x64.Build.0 = Debug|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|Win32.ActiveCfg = Release|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|Win32.Build.0 = Release|Win32 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|x64.ActiveCfg = Release|x64 {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|x64.Build.0 = Release|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|x64 Setup.ActiveCfg = Release|x64 + {8D04B550-D240-4A44-8A18-35DA3F7038D9}.Release|x86 Setup.ActiveCfg = Release|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|Win32.ActiveCfg = Release|x64 {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|x64.ActiveCfg = Release|x64 {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|x64.Build.0 = Release|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|x64 Setup.ActiveCfg = Release|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|x64 Setup.Build.0 = Release|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.All|x86 Setup.ActiveCfg = Release|x64 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|Win32.ActiveCfg = Debug|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|Win32.Build.0 = Debug|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|x64.ActiveCfg = Debug|x64 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|x64.Build.0 = Debug|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|Win32.ActiveCfg = Release|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|Win32.Build.0 = Release|Win32 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|x64.ActiveCfg = Release|x64 {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|x64.Build.0 = Release|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|x64 Setup.ActiveCfg = Release|x64 + {1CED5987-A529-46DC-B30F-870D85FF9C94}.Release|x86 Setup.ActiveCfg = Release|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|Win32.ActiveCfg = Release|x64 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|x64.ActiveCfg = Release|x64 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|x64.Build.0 = Release|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|x64 Setup.ActiveCfg = Release|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|x64 Setup.Build.0 = Release|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.All|x86 Setup.ActiveCfg = Release|x64 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|Win32.ActiveCfg = Debug|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|Win32.Build.0 = Debug|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|x64.ActiveCfg = Debug|x64 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|x64.Build.0 = Debug|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|Win32.ActiveCfg = Release|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|Win32.Build.0 = Release|Win32 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|x64.ActiveCfg = Release|x64 {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|x64.Build.0 = Release|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|x64 Setup.ActiveCfg = Release|x64 + {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}.Release|x86 Setup.ActiveCfg = Release|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|Win32.ActiveCfg = Release|x64 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|x64.ActiveCfg = Release|x64 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|x64.Build.0 = Release|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|x64 Setup.ActiveCfg = Release|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|x64 Setup.Build.0 = Release|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.All|x86 Setup.ActiveCfg = Release|x64 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|Win32.ActiveCfg = Debug|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|Win32.Build.0 = Debug|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|x64.ActiveCfg = Debug|x64 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|x64.Build.0 = Debug|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|Win32.ActiveCfg = Release|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|Win32.Build.0 = Release|Win32 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|x64.ActiveCfg = Release|x64 {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|x64.Build.0 = Release|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|x64 Setup.ActiveCfg = Release|x64 + {F057DA7F-79E5-4B00-845C-EF446EF055E3}.Release|x86 Setup.ActiveCfg = Release|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|Win32.ActiveCfg = Release|x64 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|x64.ActiveCfg = Release|x64 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|x64.Build.0 = Release|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|x64 Setup.ActiveCfg = Release|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|x64 Setup.Build.0 = Release|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.All|x86 Setup.ActiveCfg = Release|x64 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|Win32.ActiveCfg = Debug|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|Win32.Build.0 = Debug|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|x64.ActiveCfg = Debug|x64 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|x64.Build.0 = Debug|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|Win32.ActiveCfg = Release|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|Win32.Build.0 = Release|Win32 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|x64.ActiveCfg = Release|x64 {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|x64.Build.0 = Release|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|x64 Setup.ActiveCfg = Release|x64 + {E727E8F6-935D-46FE-8B0E-37834748A0E3}.Release|x86 Setup.ActiveCfg = Release|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|Win32.ActiveCfg = Release|x64 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|x64.ActiveCfg = Release|x64 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|x64.Build.0 = Release|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|x64 Setup.ActiveCfg = Release|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|x64 Setup.Build.0 = Release|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.All|x86 Setup.ActiveCfg = Release|x64 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|Win32.ActiveCfg = Debug|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|Win32.Build.0 = Debug|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|x64.ActiveCfg = Debug|x64 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|x64.Build.0 = Debug|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|Win32.ActiveCfg = Release|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|Win32.Build.0 = Release|Win32 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|x64.ActiveCfg = Release|x64 {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|x64.Build.0 = Release|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|x64 Setup.ActiveCfg = Release|x64 + {3D0370CA-BED2-4657-A475-32375CBCB6E4}.Release|x86 Setup.ActiveCfg = Release|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|Win32.ActiveCfg = Debug|x64 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|x64.ActiveCfg = Debug|x64 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|x64.Build.0 = Debug|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|x64 Setup.ActiveCfg = Debug|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|x64 Setup.Build.0 = Debug|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.All|x86 Setup.ActiveCfg = Debug|x64 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|Win32.ActiveCfg = Debug|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|Win32.Build.0 = Debug|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|x64.ActiveCfg = Debug|x64 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|x64.Build.0 = Debug|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|Win32.ActiveCfg = Release|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|Win32.Build.0 = Release|Win32 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|x64.ActiveCfg = Release|x64 {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|x64.Build.0 = Release|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|x64 Setup.ActiveCfg = Release|x64 + {87EE9DA4-DE1E-4448-8324-183C98DCA588}.Release|x86 Setup.ActiveCfg = Release|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|Win32.ActiveCfg = Debug|x64 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|x64.ActiveCfg = Debug|x64 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|x64.Build.0 = Debug|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|x64 Setup.ActiveCfg = Debug|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|x64 Setup.Build.0 = Debug|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.All|x86 Setup.ActiveCfg = Debug|x64 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|Win32.ActiveCfg = Debug|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|Win32.Build.0 = Debug|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|x64.ActiveCfg = Debug|x64 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|x64.Build.0 = Debug|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|Win32.ActiveCfg = Release|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|Win32.Build.0 = Release|Win32 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|x64.ActiveCfg = Release|x64 {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|x64.Build.0 = Release|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|x64 Setup.ActiveCfg = Release|x64 + {155844C3-EC5F-407F-97A4-A2DDADED9B2F}.Release|x86 Setup.ActiveCfg = Release|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|Win32.ActiveCfg = Debug|x64 {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|x64.ActiveCfg = Debug|x64 {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|x64.Build.0 = Debug|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|x64 Setup.ActiveCfg = Debug|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|x64 Setup.Build.0 = Debug|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.All|x86 Setup.ActiveCfg = Debug|x64 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|Win32.ActiveCfg = Debug|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|Win32.Build.0 = Debug|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|x64.ActiveCfg = Debug|x64 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|x64.Build.0 = Debug|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|Win32.ActiveCfg = Release|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|Win32.Build.0 = Release|Win32 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|x64.ActiveCfg = Release|x64 {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|x64.Build.0 = Release|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|x64 Setup.ActiveCfg = Release|x64 + {204FA0DE-305D-4414-AE2E-F195A23F390D}.Release|x86 Setup.ActiveCfg = Release|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|Win32.ActiveCfg = Release|x64 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|x64.ActiveCfg = Release|x64 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|x64.Build.0 = Release|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|x64 Setup.ActiveCfg = Release|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|x64 Setup.Build.0 = Release|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.All|x86 Setup.ActiveCfg = Release|x64 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|Win32.ActiveCfg = Debug|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|Win32.Build.0 = Debug|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|x64.ActiveCfg = Debug|x64 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|x64.Build.0 = Debug|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|Win32.ActiveCfg = Release|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|Win32.Build.0 = Release|Win32 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|x64.ActiveCfg = Release|x64 {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|x64.Build.0 = Release|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|x64 Setup.ActiveCfg = Release|x64 + {0DF3ABD0-DDC0-4265-B778-07C66780979B}.Release|x86 Setup.ActiveCfg = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|Win32.ActiveCfg = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|Win32.Build.0 = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x64.ActiveCfg = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x64.Build.0 = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x64 Setup.ActiveCfg = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x64 Setup.Build.0 = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x86 Setup.ActiveCfg = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.All|x86 Setup.Build.0 = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|Win32.ActiveCfg = Debug|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|Win32.Build.0 = Debug|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|x64.ActiveCfg = Debug|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|x64.Build.0 = Debug|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|Win32.ActiveCfg = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|Win32.Build.0 = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|x64.ActiveCfg = Release|Win32 {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|x64.Build.0 = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|x64 Setup.ActiveCfg = Release|Win32 + {8B3B4C4C-13C2-446C-BEB0-F412CC2CFB9A}.Release|x86 Setup.ActiveCfg = Release|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|Win32.ActiveCfg = Release DLL|x64 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|x64.ActiveCfg = Release DLL|x64 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|x64.Build.0 = Release DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|x64 Setup.ActiveCfg = Release DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|x64 Setup.Build.0 = Release DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.All|x86 Setup.ActiveCfg = Release DLL|x64 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|Win32.ActiveCfg = Debug DLL|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|Win32.Build.0 = Debug DLL|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|x64.ActiveCfg = Debug DLL|x64 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|x64.Build.0 = Debug DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|x64 Setup.ActiveCfg = Debug DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Debug|x86 Setup.ActiveCfg = Debug DLL|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|Win32.ActiveCfg = Release DLL|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|Win32.Build.0 = Release DLL|Win32 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|x64.ActiveCfg = Release DLL|x64 {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|x64.Build.0 = Release DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|x64 Setup.ActiveCfg = Release DLL|x64 + {DF018947-0FFF-4EB3-BDEE-441DC81DA7A4}.Release|x86 Setup.ActiveCfg = Release DLL|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|Win32.ActiveCfg = Release Passthrough|x64 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|x64.ActiveCfg = Release Passthrough|x64 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|x64.Build.0 = Release Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|x64 Setup.ActiveCfg = Release Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|x64 Setup.Build.0 = Release Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.All|x86 Setup.ActiveCfg = Release Passthrough|x64 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|Win32.ActiveCfg = Debug Passthrough|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|Win32.Build.0 = Debug Passthrough|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|x64.ActiveCfg = Debug Passthrough|x64 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|x64.Build.0 = Debug Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|x64 Setup.ActiveCfg = Debug Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Debug|x86 Setup.ActiveCfg = Debug Passthrough|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|Win32.ActiveCfg = Release Passthrough|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|Win32.Build.0 = Release Passthrough|Win32 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x64.ActiveCfg = Release Passthrough|x64 {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x64.Build.0 = Release Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x64 Setup.ActiveCfg = Release Passthrough|x64 + {FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x86 Setup.ActiveCfg = Release Passthrough|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|Win32.ActiveCfg = Release|x64 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64.ActiveCfg = Release|x64 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64.Build.0 = Release|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64 Setup.ActiveCfg = Release|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64 Setup.Build.0 = Release|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x86 Setup.ActiveCfg = Release|x64 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|Win32.ActiveCfg = Debug|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|Win32.Build.0 = Debug|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|x64.ActiveCfg = Debug|x64 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|x64.Build.0 = Debug|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|Win32.ActiveCfg = Release|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|Win32.Build.0 = Release|Win32 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|x64.ActiveCfg = Release|x64 {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|x64.Build.0 = Release|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|x64 Setup.ActiveCfg = Release|x64 + {9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.Release|x86 Setup.ActiveCfg = Release|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|Win32.ActiveCfg = Release|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|x64.ActiveCfg = Release|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|x64.Build.0 = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|x64 Setup.ActiveCfg = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|x64 Setup.Build.0 = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.All|x86 Setup.ActiveCfg = Release|x64 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.ActiveCfg = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|Win32.Build.0 = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64.ActiveCfg = Debug|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.ActiveCfg = Release|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|Win32.Build.0 = Release|Win32 {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64.ActiveCfg = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x64 Setup.ActiveCfg = Release|x64 + {ACFFF684-4D19-4D48-AF12-88EA1D778BDF}.Release|x86 Setup.ActiveCfg = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|Win32.ActiveCfg = Release|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|x64.ActiveCfg = Release|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|x64.Build.0 = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|x64 Setup.ActiveCfg = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|x64 Setup.Build.0 = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.All|x86 Setup.ActiveCfg = Release|x64 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.ActiveCfg = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|Win32.Build.0 = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64.ActiveCfg = Debug|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.ActiveCfg = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|Win32.Build.0 = Release|Win32 {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64.ActiveCfg = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x64 Setup.ActiveCfg = Release|x64 + {8F992C49-6C51-412F-B2A3-34EAB708EB65}.Release|x86 Setup.ActiveCfg = Release|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|Win32.ActiveCfg = Release|x64 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64.ActiveCfg = Release|x64 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64.Build.0 = Release|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64 Setup.ActiveCfg = Release|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x64 Setup.Build.0 = Release|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.All|x86 Setup.ActiveCfg = Release|x64 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.ActiveCfg = Debug|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|Win32.Build.0 = Debug|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.ActiveCfg = Debug|x64 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64.Build.0 = Debug|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.ActiveCfg = Release|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|Win32.Build.0 = Release|Win32 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.ActiveCfg = Release|x64 {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64.Build.0 = Release|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x64 Setup.ActiveCfg = Release|x64 + {4043FC6A-9A30-4577-8AD5-9B233C9575D8}.Release|x86 Setup.ActiveCfg = Release|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|Win32.ActiveCfg = Release|x64 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64.ActiveCfg = Release|x64 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64.Build.0 = Release|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64 Setup.ActiveCfg = Release|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x64 Setup.Build.0 = Release|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.All|x86 Setup.ActiveCfg = Release|x64 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.ActiveCfg = Debug|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|Win32.Build.0 = Debug|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.ActiveCfg = Debug|x64 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64.Build.0 = Debug|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.ActiveCfg = Release|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|Win32.Build.0 = Release|Win32 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.ActiveCfg = Release|x64 {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64.Build.0 = Release|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x64 Setup.ActiveCfg = Release|x64 + {71A967D5-0E99-4CEF-A587-98836EE6F2EF}.Release|x86 Setup.ActiveCfg = Release|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|Win32.ActiveCfg = Release|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64.ActiveCfg = Release|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64.Build.0 = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64 Setup.ActiveCfg = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x64 Setup.Build.0 = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.All|x86 Setup.ActiveCfg = Release|x64 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.ActiveCfg = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|Win32.Build.0 = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64.ActiveCfg = Debug|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.ActiveCfg = Release|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|Win32.Build.0 = Release|Win32 {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64.ActiveCfg = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x64 Setup.ActiveCfg = Release|x64 + {0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF}.Release|x86 Setup.ActiveCfg = Release|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|Win32.ActiveCfg = Release|x64 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|x64.ActiveCfg = Release|x64 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|x64.Build.0 = Release|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|x64 Setup.ActiveCfg = Release|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|x64 Setup.Build.0 = Release|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.All|x86 Setup.ActiveCfg = Release|x64 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|Win32.ActiveCfg = Debug|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|Win32.Build.0 = Debug|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|x64.ActiveCfg = Debug|x64 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|x64.Build.0 = Debug|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|Win32.ActiveCfg = Release|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|Win32.Build.0 = Release|Win32 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|x64.ActiveCfg = Release|x64 {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|x64.Build.0 = Release|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|x64 Setup.ActiveCfg = Release|x64 + {AB91A099-7690-4ECF-8994-E458F4EA1ED4}.Release|x86 Setup.ActiveCfg = Release|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|Win32.ActiveCfg = Release|x64 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|x64.ActiveCfg = Release|x64 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|x64.Build.0 = Release|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|x64 Setup.ActiveCfg = Release|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|x64 Setup.Build.0 = Release|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.All|x86 Setup.ActiveCfg = Release|x64 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|Win32.ActiveCfg = Debug|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|Win32.Build.0 = Debug|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|x64.ActiveCfg = Debug|x64 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|x64.Build.0 = Debug|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|Win32.ActiveCfg = Release|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|Win32.Build.0 = Release|Win32 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|x64.ActiveCfg = Release|x64 {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|x64.Build.0 = Release|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|x64 Setup.ActiveCfg = Release|x64 + {988CACF7-3FCB-4992-BE69-77872AE67DC8}.Release|x86 Setup.ActiveCfg = Release|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|Win32.ActiveCfg = Release DirectSound|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64.ActiveCfg = Release DirectSound|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64.Build.0 = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.ActiveCfg = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x64 Setup.Build.0 = Release DirectSound|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.All|x86 Setup.ActiveCfg = Release DirectSound|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.ActiveCfg = Debug|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|Win32.Build.0 = Debug|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.ActiveCfg = Debug|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64.Build.0 = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.ActiveCfg = Release|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|Win32.Build.0 = Release|Win32 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.ActiveCfg = Release|x64 {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64.Build.0 = Release|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x64 Setup.ActiveCfg = Release|x64 + {0A18A071-125E-442F-AFF7-A3F68ABECF99}.Release|x86 Setup.ActiveCfg = Release|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|Win32.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64.Build.0 = Release|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64 Setup.ActiveCfg = Release|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x64 Setup.Build.0 = Release|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.All|x86 Setup.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|Win32.ActiveCfg = Debug|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|Win32.Build.0 = Debug|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|x64.ActiveCfg = Debug|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|x64.Build.0 = Debug|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|Win32.ActiveCfg = Release|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|Win32.Build.0 = Release|Win32 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|x64.ActiveCfg = Release|x64 {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|x64.Build.0 = Release|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|x64 Setup.ActiveCfg = Release|x64 + {08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}.Release|x86 Setup.ActiveCfg = Release|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|Win32.ActiveCfg = Release Passthrough|x64 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|x64.ActiveCfg = Release Passthrough|x64 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|x64.Build.0 = Release Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|x64 Setup.ActiveCfg = Release Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|x64 Setup.Build.0 = Release Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.All|x86 Setup.ActiveCfg = Release Passthrough|x64 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|Win32.ActiveCfg = Debug Passthrough|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|Win32.Build.0 = Debug Passthrough|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|x64.ActiveCfg = Debug Passthrough|x64 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|x64.Build.0 = Debug Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|x64 Setup.ActiveCfg = Debug Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Debug|x86 Setup.ActiveCfg = Debug Passthrough|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|Win32.ActiveCfg = Release Passthrough|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|Win32.Build.0 = Release Passthrough|Win32 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|x64.ActiveCfg = Release Passthrough|x64 {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|x64.Build.0 = Release Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|x64 Setup.ActiveCfg = Release Passthrough|x64 + {8DEB383C-4091-4F42-A56F-C9E46D552D79}.Release|x86 Setup.ActiveCfg = Release Passthrough|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|Win32.ActiveCfg = Release|x64 {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|x64.ActiveCfg = Release|x64 {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|x64.Build.0 = Release|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|x64 Setup.ActiveCfg = Release|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|x64 Setup.Build.0 = Release|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.All|x86 Setup.ActiveCfg = Release|x64 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|Win32.ActiveCfg = Debug|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|Win32.Build.0 = Debug|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|x64.ActiveCfg = Debug|x64 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|x64.Build.0 = Debug|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|Win32.ActiveCfg = Release|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|Win32.Build.0 = Release|Win32 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|x64.ActiveCfg = Release|x64 {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|x64.Build.0 = Release|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|x64 Setup.ActiveCfg = Release|x64 + {2C3C2423-234B-4772-8899-D3B137E5CA35}.Release|x86 Setup.ActiveCfg = Release|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|Win32.ActiveCfg = Release|x64 {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|x64.ActiveCfg = Release|x64 {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|x64.Build.0 = Release|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|x64 Setup.ActiveCfg = Release|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|x64 Setup.Build.0 = Release|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.All|x86 Setup.ActiveCfg = Release|x64 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|Win32.ActiveCfg = Debug|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|Win32.Build.0 = Debug|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|x64.ActiveCfg = Debug|x64 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|x64.Build.0 = Debug|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|Win32.ActiveCfg = Release|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|Win32.Build.0 = Release|Win32 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|x64.ActiveCfg = Release|x64 {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|x64.Build.0 = Release|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|x64 Setup.ActiveCfg = Release|x64 + {3850D93A-5F24-4922-BC1C-74D08C37C256}.Release|x86 Setup.ActiveCfg = Release|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|Win32.ActiveCfg = Release|x64 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|x64.ActiveCfg = Release|x64 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|x64.Build.0 = Release|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|x64 Setup.ActiveCfg = Release|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|x64 Setup.Build.0 = Release|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.All|x86 Setup.ActiveCfg = Release|x64 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|Win32.ActiveCfg = Debug|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|Win32.Build.0 = Debug|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|x64.ActiveCfg = Debug|x64 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|x64.Build.0 = Debug|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|Win32.ActiveCfg = Release|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|Win32.Build.0 = Release|Win32 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|x64.ActiveCfg = Release|x64 {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|x64.Build.0 = Release|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|x64 Setup.ActiveCfg = Release|x64 + {2CA40887-1622-46A1-A7F9-17FD7E7E545B}.Release|x86 Setup.ActiveCfg = Release|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.All|Win32.ActiveCfg = Release|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.All|x64.ActiveCfg = Release|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.All|x64.Build.0 = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.All|x64 Setup.ActiveCfg = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.All|x64 Setup.Build.0 = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.All|x86 Setup.ActiveCfg = Release|x64 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.ActiveCfg = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|Win32.Build.0 = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64.ActiveCfg = Debug|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.ActiveCfg = Release|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|Win32.Build.0 = Release|Win32 {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64.ActiveCfg = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x64 Setup.ActiveCfg = Release|x64 + {028C7278-05D7-4E18-82FE-BE231B844F41}.Release|x86 Setup.ActiveCfg = Release|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|Win32.ActiveCfg = Release|x64 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|x64.ActiveCfg = Release|x64 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|x64.Build.0 = Release|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|x64 Setup.ActiveCfg = Release|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|x64 Setup.Build.0 = Release|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.All|x86 Setup.ActiveCfg = Release|x64 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|Win32.ActiveCfg = Debug|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|Win32.Build.0 = Debug|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|x64.ActiveCfg = Debug|x64 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|x64.Build.0 = Debug|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|Win32.ActiveCfg = Release|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|Win32.Build.0 = Release|Win32 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|x64.ActiveCfg = Release|x64 {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|x64.Build.0 = Release|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|x64 Setup.ActiveCfg = Release|x64 + {D7F1E3F2-A3F4-474C-8555-15122571AF52}.Release|x86 Setup.ActiveCfg = Release|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|Win32.ActiveCfg = Release|x64 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|x64.ActiveCfg = Release|x64 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|x64.Build.0 = Release|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|x64 Setup.ActiveCfg = Release|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|x64 Setup.Build.0 = Release|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.All|x86 Setup.ActiveCfg = Release|x64 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|Win32.ActiveCfg = Debug|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|Win32.Build.0 = Debug|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|x64.ActiveCfg = Debug|x64 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|x64.Build.0 = Debug|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|Win32.ActiveCfg = Release|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|Win32.Build.0 = Release|Win32 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|x64.ActiveCfg = Release|x64 {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|x64.Build.0 = Release|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|x64 Setup.ActiveCfg = Release|x64 + {5BC072DB-3826-48EA-AF34-FE32AA01E83B}.Release|x86 Setup.ActiveCfg = Release|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|Win32.ActiveCfg = Release|x64 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|x64.ActiveCfg = Release|x64 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|x64.Build.0 = Release|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|x64 Setup.ActiveCfg = Release|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|x64 Setup.Build.0 = Release|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.All|x86 Setup.ActiveCfg = Release|x64 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|Win32.ActiveCfg = Debug|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|Win32.Build.0 = Debug|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|x64.ActiveCfg = Debug|x64 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|x64.Build.0 = Debug|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|Win32.ActiveCfg = Release|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|Win32.Build.0 = Release|Win32 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|x64.ActiveCfg = Release|x64 {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|x64.Build.0 = Release|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|x64 Setup.ActiveCfg = Release|x64 + {FA429E98-8B03-45E6-A096-A4BC5E821DE4}.Release|x86 Setup.ActiveCfg = Release|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|Win32.ActiveCfg = Release|x64 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|x64.ActiveCfg = Release|x64 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|x64.Build.0 = Release|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|x64 Setup.ActiveCfg = Release|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|x64 Setup.Build.0 = Release|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.All|x86 Setup.ActiveCfg = Release|x64 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|Win32.ActiveCfg = Debug|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|Win32.Build.0 = Debug|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|x64.ActiveCfg = Debug|x64 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|x64.Build.0 = Debug|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|Win32.ActiveCfg = Release|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|Win32.Build.0 = Release|Win32 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|x64.ActiveCfg = Release|x64 {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|x64.Build.0 = Release|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|x64 Setup.ActiveCfg = Release|x64 + {06E3A538-AB32-44F2-B477-755FF9CB5D37}.Release|x86 Setup.ActiveCfg = Release|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|Win32.ActiveCfg = Release|x64 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|x64.ActiveCfg = Release|x64 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|x64.Build.0 = Release|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|x64 Setup.ActiveCfg = Release|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|x64 Setup.Build.0 = Release|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.All|x86 Setup.ActiveCfg = Release|x64 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|Win32.ActiveCfg = Debug|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|Win32.Build.0 = Debug|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|x64.ActiveCfg = Debug|x64 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|x64.Build.0 = Debug|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|Win32.ActiveCfg = Release|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|Win32.Build.0 = Release|Win32 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|x64.ActiveCfg = Release|x64 {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|x64.Build.0 = Release|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|x64 Setup.ActiveCfg = Release|x64 + {6D1BEC70-4DCD-4FE9-ADBD-4A43A67E4D05}.Release|x86 Setup.ActiveCfg = Release|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|Win32.ActiveCfg = Release|x64 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|x64.ActiveCfg = Release|x64 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|x64.Build.0 = Release|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|x64 Setup.ActiveCfg = Release|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|x64 Setup.Build.0 = Release|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.All|x86 Setup.ActiveCfg = Release|x64 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|Win32.ActiveCfg = Debug|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|Win32.Build.0 = Debug|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|x64.ActiveCfg = Debug|x64 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|x64.Build.0 = Debug|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|Win32.ActiveCfg = Release|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|Win32.Build.0 = Release|Win32 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|x64.ActiveCfg = Release|x64 {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|x64.Build.0 = Release|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|x64 Setup.ActiveCfg = Release|x64 + {A4B122CF-5196-476B-8C0E-D8BD59AC3C14}.Release|x86 Setup.ActiveCfg = Release|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|Win32.ActiveCfg = Release|x64 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|x64.ActiveCfg = Release|x64 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|x64.Build.0 = Release|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|x64 Setup.ActiveCfg = Release|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|x64 Setup.Build.0 = Release|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.All|x86 Setup.ActiveCfg = Release|x64 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|Win32.ActiveCfg = Debug|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|Win32.Build.0 = Debug|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|x64.ActiveCfg = Debug|x64 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|x64.Build.0 = Debug|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|Win32.ActiveCfg = Release|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|Win32.Build.0 = Release|Win32 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|x64.ActiveCfg = Release|x64 {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|x64.Build.0 = Release|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|x64 Setup.ActiveCfg = Release|x64 + {75DF7F29-2FBF-47F7-B5AF-5B4952DC1ABD}.Release|x86 Setup.ActiveCfg = Release|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.All|Win32.ActiveCfg = Release|x64 {F6A33240-8F29-48BD-98F0-826995911799}.All|x64.ActiveCfg = Release|x64 {F6A33240-8F29-48BD-98F0-826995911799}.All|x64.Build.0 = Release|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.All|x64 Setup.ActiveCfg = Release|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.All|x64 Setup.Build.0 = Release|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.All|x86 Setup.ActiveCfg = Release|x64 {F6A33240-8F29-48BD-98F0-826995911799}.Debug|Win32.ActiveCfg = Debug|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.Debug|Win32.Build.0 = Debug|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.Debug|x64.ActiveCfg = Debug|x64 {F6A33240-8F29-48BD-98F0-826995911799}.Debug|x64.Build.0 = Debug|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.Release|Win32.ActiveCfg = Release|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.Release|Win32.Build.0 = Release|Win32 {F6A33240-8F29-48BD-98F0-826995911799}.Release|x64.ActiveCfg = Release|x64 {F6A33240-8F29-48BD-98F0-826995911799}.Release|x64.Build.0 = Release|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.Release|x64 Setup.ActiveCfg = Release|x64 + {F6A33240-8F29-48BD-98F0-826995911799}.Release|x86 Setup.ActiveCfg = Release|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|Win32.ActiveCfg = Release|x64 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|x64.ActiveCfg = Release|x64 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|x64.Build.0 = Release|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|x64 Setup.ActiveCfg = Release|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|x64 Setup.Build.0 = Release|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.All|x86 Setup.ActiveCfg = Release|x64 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|Win32.ActiveCfg = Debug|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|Win32.Build.0 = Debug|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|x64.ActiveCfg = Debug|x64 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|x64.Build.0 = Debug|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|Win32.ActiveCfg = Release|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|Win32.Build.0 = Release|Win32 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|x64.ActiveCfg = Release|x64 {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|x64.Build.0 = Release|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|x64 Setup.ActiveCfg = Release|x64 + {65A6273D-FCAB-4C55-B09E-65100141A5D4}.Release|x86 Setup.ActiveCfg = Release|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|Win32.ActiveCfg = Release|x64 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|x64.ActiveCfg = Release|x64 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|x64.Build.0 = Release|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|x64 Setup.ActiveCfg = Release|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|x64 Setup.Build.0 = Release|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.All|x86 Setup.ActiveCfg = Release|x64 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|Win32.ActiveCfg = Debug|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|Win32.Build.0 = Debug|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|x64.ActiveCfg = Debug|x64 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|x64.Build.0 = Debug|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|Win32.ActiveCfg = Release|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|Win32.Build.0 = Release|Win32 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|x64.ActiveCfg = Release|x64 {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|x64.Build.0 = Release|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|x64 Setup.ActiveCfg = Release|x64 + {E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24}.Release|x86 Setup.ActiveCfg = Release|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|Win32.ActiveCfg = Release|x64 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|x64.ActiveCfg = Release|x64 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|x64.Build.0 = Release|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|x64 Setup.ActiveCfg = Release|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|x64 Setup.Build.0 = Release|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.All|x86 Setup.ActiveCfg = Release|x64 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|Win32.ActiveCfg = Debug|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|Win32.Build.0 = Debug|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|x64.ActiveCfg = Debug|x64 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|x64.Build.0 = Debug|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|Win32.ActiveCfg = Release|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|Win32.Build.0 = Release|Win32 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|x64.ActiveCfg = Release|x64 {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|x64.Build.0 = Release|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|x64 Setup.ActiveCfg = Release|x64 + {D0BCAC02-D94B-46B8-9B49-CDDCC2BD7909}.Release|x86 Setup.ActiveCfg = Release|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|Win32.ActiveCfg = Release|x64 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|x64.ActiveCfg = Release|x64 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|x64.Build.0 = Release|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|x64 Setup.ActiveCfg = Release|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|x64 Setup.Build.0 = Release|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.All|x86 Setup.ActiveCfg = Release|x64 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|Win32.ActiveCfg = Debug|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|Win32.Build.0 = Debug|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|x64.ActiveCfg = Debug|x64 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|x64.Build.0 = Debug|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|Win32.ActiveCfg = Release|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|Win32.Build.0 = Release|Win32 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|x64.ActiveCfg = Release|x64 {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|x64.Build.0 = Release|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|x64 Setup.ActiveCfg = Release|x64 + {44D7DEAF-FDA5-495E-8B9D-1439E4F4C21E}.Release|x86 Setup.ActiveCfg = Release|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|Win32.ActiveCfg = Release|x64 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|x64.ActiveCfg = Release|x64 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|x64.Build.0 = Release|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|x64 Setup.ActiveCfg = Release|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|x64 Setup.Build.0 = Release|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.All|x86 Setup.ActiveCfg = Release|x64 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|Win32.ActiveCfg = Debug|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|Win32.Build.0 = Debug|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|x64.ActiveCfg = Debug|x64 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|x64.Build.0 = Debug|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|Win32.ActiveCfg = Release|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|Win32.Build.0 = Release|Win32 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|x64.ActiveCfg = Release|x64 {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|x64.Build.0 = Release|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|x64 Setup.ActiveCfg = Release|x64 + {6FF941AC-82C5-429F-AA4C-AD2FB9E5DA52}.Release|x86 Setup.ActiveCfg = Release|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|Win32.ActiveCfg = Release|x64 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|x64.ActiveCfg = Release|x64 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|x64.Build.0 = Release|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|x64 Setup.ActiveCfg = Release|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|x64 Setup.Build.0 = Release|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.All|x86 Setup.ActiveCfg = Release|x64 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|Win32.ActiveCfg = Debug|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|Win32.Build.0 = Debug|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|x64.ActiveCfg = Debug|x64 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|x64.Build.0 = Debug|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|Win32.ActiveCfg = Release|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|Win32.Build.0 = Release|Win32 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|x64.ActiveCfg = Release|x64 {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|x64.Build.0 = Release|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|x64 Setup.ActiveCfg = Release|x64 + {E3246D17-E29B-4AB5-962A-C69B0C5837BB}.Release|x86 Setup.ActiveCfg = Release|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|Win32.ActiveCfg = Release|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|x64.ActiveCfg = Release|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|x64.Build.0 = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|x64 Setup.ActiveCfg = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|x64 Setup.Build.0 = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.All|x86 Setup.ActiveCfg = Release|x64 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.ActiveCfg = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|Win32.Build.0 = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64.ActiveCfg = Debug|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.ActiveCfg = Release|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|Win32.Build.0 = Release|Win32 {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64.ActiveCfg = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x64 Setup.ActiveCfg = Release|x64 + {36E854E3-CE12-4348-A125-CCF3F9D74813}.Release|x86 Setup.ActiveCfg = Release|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|Win32.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|x64.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|x64.Build.0 = Release|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|x64 Setup.ActiveCfg = Release|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|x64 Setup.Build.0 = Release|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.All|x86 Setup.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|Win32.ActiveCfg = Debug|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|Win32.Build.0 = Debug|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|x64.ActiveCfg = Debug|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|x64.Build.0 = Debug|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|Win32.ActiveCfg = Release|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|Win32.Build.0 = Release|Win32 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64.ActiveCfg = Release|x64 {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64.Build.0 = Release|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x64 Setup.ActiveCfg = Release|x64 + {7B077E7F-1BE7-4291-AB86-55E527B25CAC}.Release|x86 Setup.ActiveCfg = Release|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|Win32.ActiveCfg = Release|x64 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.ActiveCfg = Release|x64 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64.Build.0 = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64 Setup.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x64 Setup.Build.0 = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.All|x86 Setup.ActiveCfg = Release|x64 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.ActiveCfg = Debug|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|Win32.Build.0 = Debug|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.ActiveCfg = Debug|x64 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64.Build.0 = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.ActiveCfg = Release|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|Win32.Build.0 = Release|Win32 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.ActiveCfg = Release|x64 {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64.Build.0 = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x64 Setup.ActiveCfg = Release|x64 + {D2396DD7-7D38-473A-ABB7-6F96D65AE1B9}.Release|x86 Setup.ActiveCfg = Release|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|Win32.ActiveCfg = Release|x64 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.ActiveCfg = Release|x64 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64.Build.0 = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x64 Setup.Build.0 = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.All|x86 Setup.ActiveCfg = Release|x64 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.ActiveCfg = Debug|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|Win32.Build.0 = Debug|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.ActiveCfg = Debug|x64 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64.Build.0 = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.ActiveCfg = Release|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|Win32.Build.0 = Release|Win32 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.ActiveCfg = Release|x64 {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64.Build.0 = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x64 Setup.ActiveCfg = Release|x64 + {CEE544A9-0303-44C2-8ECE-EFA7D7BCBBBA}.Release|x86 Setup.ActiveCfg = Release|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|Win32.ActiveCfg = Debug|x64 {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.ActiveCfg = Debug|x64 {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64.Build.0 = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64 Setup.ActiveCfg = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x64 Setup.Build.0 = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.All|x86 Setup.ActiveCfg = Debug|x64 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.ActiveCfg = Debug|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|Win32.Build.0 = Debug|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.ActiveCfg = Debug|x64 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64.Build.0 = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.ActiveCfg = Release|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|Win32.Build.0 = Release|Win32 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.ActiveCfg = Release|x64 {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64.Build.0 = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x64 Setup.ActiveCfg = Release|x64 + {0D108721-EAE8-4BAF-8102-D8960EC93647}.Release|x86 Setup.ActiveCfg = Release|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.All|Win32.ActiveCfg = Release|x64 {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.ActiveCfg = Release|x64 {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64.Build.0 = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x64 Setup.Build.0 = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.All|x86 Setup.ActiveCfg = Release|x64 {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.ActiveCfg = Debug|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|Win32.Build.0 = Debug|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.ActiveCfg = Debug|x64 {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64.Build.0 = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.ActiveCfg = Release|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.Release|Win32.Build.0 = Release|Win32 {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.ActiveCfg = Release|x64 {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64.Build.0 = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x64 Setup.ActiveCfg = Release|x64 + {B535402E-38D2-4D54-8360-423ACBD17192}.Release|x86 Setup.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|Win32.Build.0 = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64.Build.0 = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64 Setup.ActiveCfg = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x64 Setup.Build.0 = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x86 Setup.ActiveCfg = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.All|x86 Setup.Build.0 = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|Win32.ActiveCfg = Debug|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|Win32.Build.0 = Debug|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|x64.ActiveCfg = Debug|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|x64.Build.0 = Debug|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|Win32.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|Win32.Build.0 = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|x64.ActiveCfg = Release|Win32 {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|x64.Build.0 = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|x64 Setup.ActiveCfg = Release|Win32 + {4F92B672-DADB-4047-8D6A-4BB3796733FD}.Release|x86 Setup.ActiveCfg = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.All|Win32.ActiveCfg = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.All|Win32.Build.0 = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.All|x64.ActiveCfg = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.All|x64.Build.0 = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.All|x64 Setup.ActiveCfg = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.All|x64 Setup.Build.0 = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.All|x86 Setup.ActiveCfg = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.All|x86 Setup.Build.0 = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Debug|Win32.ActiveCfg = Debug|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Debug|Win32.Build.0 = Debug|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Debug|x64.ActiveCfg = Debug|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Debug|x64.Build.0 = Debug|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Release|Win32.ActiveCfg = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Release|Win32.Build.0 = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Release|x64.ActiveCfg = Release|Win32 {2DEE4895-1134-439C-B688-52203E57D878}.Release|x64.Build.0 = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.Release|x64 Setup.ActiveCfg = Release|Win32 + {2DEE4895-1134-439C-B688-52203E57D878}.Release|x86 Setup.ActiveCfg = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|Win32.ActiveCfg = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|Win32.Build.0 = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x64.ActiveCfg = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x64.Build.0 = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x64 Setup.ActiveCfg = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x64 Setup.Build.0 = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x86 Setup.ActiveCfg = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.All|x86 Setup.Build.0 = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|Win32.ActiveCfg = Debug|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|Win32.Build.0 = Debug|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|x64.ActiveCfg = Debug|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|x64.Build.0 = Debug|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|Win32.ActiveCfg = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|Win32.Build.0 = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|x64.ActiveCfg = Release|Win32 {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|x64.Build.0 = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|x64 Setup.ActiveCfg = Release|Win32 + {AF8163EE-FA76-4904-A11D-7D70A1B5BA2E}.Release|x86 Setup.ActiveCfg = Release|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|Win32.ActiveCfg = Debug|x64 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|x64.ActiveCfg = Debug|x64 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|x64.Build.0 = Debug|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|x64 Setup.ActiveCfg = Debug|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|x64 Setup.Build.0 = Debug|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.All|x86 Setup.ActiveCfg = Debug|x64 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|Win32.ActiveCfg = Debug|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|Win32.Build.0 = Debug|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|x64.ActiveCfg = Debug|x64 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|x64.Build.0 = Debug|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|Win32.ActiveCfg = Release|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|Win32.Build.0 = Release|Win32 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|x64.ActiveCfg = Release|x64 {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|x64.Build.0 = Release|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|x64 Setup.ActiveCfg = Release|x64 + {2F025EAD-99BD-40F5-B2CC-F0A28CAD7F2D}.Release|x86 Setup.ActiveCfg = Release|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.All|Win32.ActiveCfg = Debug|x64 {94001A0E-A837-445C-8004-F918F10D0226}.All|x64.ActiveCfg = Debug|x64 {94001A0E-A837-445C-8004-F918F10D0226}.All|x64.Build.0 = Debug|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.All|x64 Setup.ActiveCfg = Debug|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.All|x64 Setup.Build.0 = Debug|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.All|x86 Setup.ActiveCfg = Debug|x64 {94001A0E-A837-445C-8004-F918F10D0226}.Debug|Win32.ActiveCfg = Debug|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.Debug|Win32.Build.0 = Debug|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.Debug|x64.ActiveCfg = Debug|x64 {94001A0E-A837-445C-8004-F918F10D0226}.Debug|x64.Build.0 = Debug|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.Release|Win32.ActiveCfg = Release|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.Release|Win32.Build.0 = Release|Win32 {94001A0E-A837-445C-8004-F918F10D0226}.Release|x64.ActiveCfg = Release|x64 {94001A0E-A837-445C-8004-F918F10D0226}.Release|x64.Build.0 = Release|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.Release|x64 Setup.ActiveCfg = Release|x64 + {94001A0E-A837-445C-8004-F918F10D0226}.Release|x86 Setup.ActiveCfg = Release|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|Win32.ActiveCfg = Release|x64 {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|x64.ActiveCfg = Release|x64 {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|x64.Build.0 = Release|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|x64 Setup.ActiveCfg = Release|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|x64 Setup.Build.0 = Release|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.All|x86 Setup.ActiveCfg = Release|x64 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|Win32.ActiveCfg = Debug|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|Win32.Build.0 = Debug|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|x64.ActiveCfg = Debug|x64 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|x64.Build.0 = Debug|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|Win32.ActiveCfg = Release|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|Win32.Build.0 = Release|Win32 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|x64.ActiveCfg = Release|x64 {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|x64.Build.0 = Release|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|x64 Setup.ActiveCfg = Release|x64 + {2286DA73-9FC5-45BC-A508-85994C3317AB}.Release|x86 Setup.ActiveCfg = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|Win32.ActiveCfg = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|Win32.Build.0 = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x64.ActiveCfg = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x64.Build.0 = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x64 Setup.ActiveCfg = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x64 Setup.Build.0 = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x86 Setup.ActiveCfg = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.All|x86 Setup.Build.0 = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|Win32.ActiveCfg = Debug|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|Win32.Build.0 = Debug|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|x64.ActiveCfg = Debug|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|x64.Build.0 = Debug|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|Win32.ActiveCfg = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|Win32.Build.0 = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|x64.ActiveCfg = Release|Win32 {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|x64.Build.0 = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|x64 Setup.ActiveCfg = Release|Win32 + {3CE1DC99-8246-4DB1-A709-74F19F08EC67}.Release|x86 Setup.ActiveCfg = Release|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.All|Win32.ActiveCfg = Release|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.All|x64.ActiveCfg = Release|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.All|x64 Setup.ActiveCfg = Release|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.All|x86 Setup.ActiveCfg = Release|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Debug|Win32.ActiveCfg = Debug|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Debug|x64.ActiveCfg = Debug|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Release|Win32.ActiveCfg = Release|Win32 {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Release|x64.ActiveCfg = Release|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Release|x64 Setup.ActiveCfg = Release|Win32 + {87A1FE3D-F410-4C8E-9591-8C625985BC70}.Release|x86 Setup.ActiveCfg = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|Win32.ActiveCfg = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|Win32.Build.0 = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x64.ActiveCfg = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x64.Build.0 = Release|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x64 Setup.ActiveCfg = Release|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x64 Setup.Build.0 = Release|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x86 Setup.ActiveCfg = Release|Win32 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.All|x86 Setup.Build.0 = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|Win32.ActiveCfg = Debug|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|Win32.Build.0 = Debug|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.ActiveCfg = Debug|x64 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64.Build.0 = Debug|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|Win32.ActiveCfg = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|Win32.Build.0 = Release|Win32 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.ActiveCfg = Release|x64 {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64.Build.0 = Release|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x64 Setup.ActiveCfg = Release|x64 + {7A8D8174-B355-4114-AFC1-04777CB9DE0A}.Release|x86 Setup.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.All|Win32.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.All|x64.ActiveCfg = Release|Win32 + {7EB71250-F002-4ED8-92CA-CA218114537A}.All|x64 Setup.ActiveCfg = Release|Win32 + {7EB71250-F002-4ED8-92CA-CA218114537A}.All|x86 Setup.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|Win32.ActiveCfg = Debug|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|x64.ActiveCfg = Debug|x64 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|Win32.ActiveCfg = Release|Win32 {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|x64.ActiveCfg = Release|x64 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|x64 Setup.ActiveCfg = Release|x64 + {7EB71250-F002-4ED8-92CA-CA218114537A}.Release|x86 Setup.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|Win32.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|x64.ActiveCfg = Release|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|x64 Setup.ActiveCfg = Release|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.All|x86 Setup.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Debug|Win32.ActiveCfg = Debug|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Debug|x64.ActiveCfg = Debug|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Release|Win32.ActiveCfg = Release|Win32 {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Release|x64.ActiveCfg = Release|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Release|x64 Setup.ActiveCfg = Release|Win32 + {6E49F6C2-ADDA-4BFB-81FE-AB9AF51B455F}.Release|x86 Setup.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.All|Win32.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.All|x64.ActiveCfg = Release|Win32 + {464AAB78-5489-4916-BE51-BF8D61822311}.All|x64 Setup.ActiveCfg = Release|Win32 + {464AAB78-5489-4916-BE51-BF8D61822311}.All|x86 Setup.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|Win32.ActiveCfg = Debug|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|x64.ActiveCfg = Debug|x64 + {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {464AAB78-5489-4916-BE51-BF8D61822311}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.Release|Win32.ActiveCfg = Release|Win32 {464AAB78-5489-4916-BE51-BF8D61822311}.Release|x64.ActiveCfg = Release|x64 + {464AAB78-5489-4916-BE51-BF8D61822311}.Release|x64 Setup.ActiveCfg = Release|x64 + {464AAB78-5489-4916-BE51-BF8D61822311}.Release|x86 Setup.ActiveCfg = Release|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.All|Win32.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64.Build.0 = Release|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64 Setup.ActiveCfg = Release|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.All|x64 Setup.Build.0 = Release|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.All|x86 Setup.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|Win32.ActiveCfg = Debug|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|Win32.Build.0 = Debug|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|x64.ActiveCfg = Debug|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|x64.Build.0 = Debug|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.Release|Win32.ActiveCfg = Release|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.Release|Win32.Build.0 = Release|Win32 {0AD1177E-1FD8-4643-9391-431467A11084}.Release|x64.ActiveCfg = Release|x64 {0AD1177E-1FD8-4643-9391-431467A11084}.Release|x64.Build.0 = Release|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.Release|x64 Setup.ActiveCfg = Release|x64 + {0AD1177E-1FD8-4643-9391-431467A11084}.Release|x86 Setup.ActiveCfg = Release|Win32 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|Win32.ActiveCfg = Release Static|x64 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|x64.ActiveCfg = Release Static|x64 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|x64.Build.0 = Release Static|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|x64 Setup.ActiveCfg = Release Static|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|x64 Setup.Build.0 = Release Static|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.All|x86 Setup.ActiveCfg = Release Static|x64 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Debug|Win32.ActiveCfg = Debug|Win32 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Debug|x64.ActiveCfg = Debug|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Release|Win32.ActiveCfg = Release|Win32 {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Release|x64.ActiveCfg = Release|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Release|x64 Setup.ActiveCfg = Release|x64 + {66444AEE-554C-11DD-A9F0-8C5D56D89593}.Release|x86 Setup.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x64 Setup.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x86 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.All|x86 Setup.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|Win32.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|Win32.Build.0 = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|x64.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|x64.Build.0 = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82FDD086DB1B}.Release|x86 Setup.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x64 Setup.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x86 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.All|x86 Setup.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|Win32.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|Win32.Build.0 = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|x64.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|x64.Build.0 = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB2086DB1B}.Release|x86 Setup.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x64 Setup.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x86 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.All|x86 Setup.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|Win32.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|Win32.Build.0 = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|x64.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|x64.Build.0 = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB3086DB1B}.Release|x86 Setup.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x64 Setup.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x86 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.All|x86 Setup.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|Win32.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|Win32.Build.0 = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|x64.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|x64.Build.0 = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|Win32.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|Win32.Build.0 = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|x64.ActiveCfg = Release|Win32 {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|x64.Build.0 = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|x64 Setup.ActiveCfg = Release|Win32 + {D5D2BF72-29FE-4982-A9FA-82AB1086DB1B}.Release|x86 Setup.ActiveCfg = Release|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|Win32.ActiveCfg = Debug|x64 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|x64.ActiveCfg = Debug|x64 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|x64.Build.0 = Debug|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|x64 Setup.ActiveCfg = Debug|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|x64 Setup.Build.0 = Debug|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.All|x86 Setup.ActiveCfg = Debug|x64 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|Win32.ActiveCfg = Debug|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|Win32.Build.0 = Debug|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|x64.ActiveCfg = Debug|x64 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|x64.Build.0 = Debug|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|Win32.ActiveCfg = Release|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|Win32.Build.0 = Release|Win32 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|x64.ActiveCfg = Release|x64 {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|x64.Build.0 = Release|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|x64 Setup.ActiveCfg = Release|x64 + {E316772F-5D8F-4F2A-8F71-094C3E859D34}.Release|x86 Setup.ActiveCfg = Release|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|Win32.ActiveCfg = Debug|x64 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|x64.ActiveCfg = Debug|x64 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|x64.Build.0 = Debug|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|x64 Setup.ActiveCfg = Debug|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|x64 Setup.Build.0 = Debug|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.All|x86 Setup.ActiveCfg = Debug|x64 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|Win32.ActiveCfg = Debug|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|Win32.Build.0 = Debug|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|x64.ActiveCfg = Debug|x64 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|x64.Build.0 = Debug|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|Win32.ActiveCfg = Release|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|Win32.Build.0 = Release|Win32 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|x64.ActiveCfg = Release|x64 {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|x64.Build.0 = Release|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|x64 Setup.ActiveCfg = Release|x64 + {D3D8B329-20BE-475E-9E83-653CEA0E0EF5}.Release|x86 Setup.ActiveCfg = Release|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.All|Win32.ActiveCfg = Release|x64 {38FE0559-9910-43A8-9E45-3E5004C27692}.All|x64.ActiveCfg = Release|x64 {38FE0559-9910-43A8-9E45-3E5004C27692}.All|x64.Build.0 = Release|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.All|x64 Setup.ActiveCfg = Release|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.All|x64 Setup.Build.0 = Release|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.All|x86 Setup.ActiveCfg = Release|x64 {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|Win32.ActiveCfg = Debug|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|Win32.Build.0 = Debug|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|x64.ActiveCfg = Debug|x64 {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|x64.Build.0 = Debug|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|Win32.ActiveCfg = Release|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|Win32.Build.0 = Release|Win32 {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|x64.ActiveCfg = Release|x64 {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|x64.Build.0 = Release|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|x64 Setup.ActiveCfg = Release|x64 + {38FE0559-9910-43A8-9E45-3E5004C27692}.Release|x86 Setup.ActiveCfg = Release|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|Win32.ActiveCfg = Debug|x64 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|x64.ActiveCfg = Debug|x64 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|x64.Build.0 = Debug|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|x64 Setup.ActiveCfg = Debug|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|x64 Setup.Build.0 = Debug|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.All|x86 Setup.ActiveCfg = Debug|x64 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|Win32.ActiveCfg = Debug|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|Win32.Build.0 = Debug|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|x64.ActiveCfg = Debug|x64 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|x64.Build.0 = Debug|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|Win32.ActiveCfg = Release|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|Win32.Build.0 = Release|Win32 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|x64.ActiveCfg = Release|x64 {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|x64.Build.0 = Release|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|x64 Setup.ActiveCfg = Release|x64 + {0FEEAEC6-4399-4C46-B7DB-62ECE80D15B4}.Release|x86 Setup.ActiveCfg = Release|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|Win32.ActiveCfg = Release|x64 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|x64.ActiveCfg = Release|x64 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|x64.Build.0 = Release|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|x64 Setup.ActiveCfg = Release|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|x64 Setup.Build.0 = Release|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.All|x86 Setup.ActiveCfg = Release|x64 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|Win32.ActiveCfg = Debug|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|Win32.Build.0 = Debug|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|x64.ActiveCfg = Debug|x64 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|x64.Build.0 = Debug|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|Win32.ActiveCfg = Release|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|Win32.Build.0 = Release|Win32 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|x64.ActiveCfg = Release|x64 {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|x64.Build.0 = Release|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|x64 Setup.ActiveCfg = Release|x64 + {2A3D00C6-588D-4E86-81AC-9EF5EDE86E03}.Release|x86 Setup.ActiveCfg = Release|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|Win32.ActiveCfg = Release|x64 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|x64.ActiveCfg = Release|x64 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|x64.Build.0 = Release|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|x64 Setup.ActiveCfg = Release|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|x64 Setup.Build.0 = Release|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.All|x86 Setup.ActiveCfg = Release|x64 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|Win32.ActiveCfg = Debug|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|Win32.Build.0 = Debug|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|x64.ActiveCfg = Debug|x64 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|x64.Build.0 = Debug|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|Win32.ActiveCfg = Release|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|Win32.Build.0 = Release|Win32 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|x64.ActiveCfg = Release|x64 {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|x64.Build.0 = Release|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|x64 Setup.ActiveCfg = Release|x64 + {B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E}.Release|x86 Setup.ActiveCfg = Release|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|Win32.ActiveCfg = Release_Mono|x64 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|x64.ActiveCfg = Release_Mono|x64 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|x64.Build.0 = Release_Mono|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|x64 Setup.ActiveCfg = Release_Mono|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|x64 Setup.Build.0 = Release_Mono|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.All|x86 Setup.ActiveCfg = Release_Mono|x64 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|Win32.ActiveCfg = Debug_CLR|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|Win32.Build.0 = Debug_CLR|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|x64.ActiveCfg = Debug_CLR|x64 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|x64.Build.0 = Debug_CLR|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|x64 Setup.ActiveCfg = Debug_CLR|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Debug|x86 Setup.ActiveCfg = Debug_CLR|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|Win32.ActiveCfg = Release_CLR|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|Win32.Build.0 = Release_CLR|Win32 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|x64.ActiveCfg = Release_CLR|x64 {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|x64.Build.0 = Release_CLR|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|x64 Setup.ActiveCfg = Release_CLR|x64 + {7B42BDA1-72C0-4378-A9B6-5C530F8CD61E}.Release|x86 Setup.ActiveCfg = Release_CLR|Win32 {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|Win32.ActiveCfg = Release|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x64.ActiveCfg = Release|Any CPU + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x64 Setup.ActiveCfg = Release|Any CPU + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x86 Setup.ActiveCfg = Release|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.ActiveCfg = Debug|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.Build.0 = Debug|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.ActiveCfg = Debug|x64 {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|x64 + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x86 Setup.ActiveCfg = Debug|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.ActiveCfg = Release|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.Build.0 = Release|Any CPU {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.ActiveCfg = Release|x64 {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|x64 + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64 Setup.ActiveCfg = Release|x64 + {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x86 Setup.ActiveCfg = Release|Any CPU {E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.ActiveCfg = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.Build.0 = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.All|x64.ActiveCfg = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.All|x64.Build.0 = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.All|x64 Setup.ActiveCfg = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.All|x64 Setup.Build.0 = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.All|x86 Setup.ActiveCfg = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.All|x86 Setup.Build.0 = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Debug|Win32.ActiveCfg = Debug|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Debug|Win32.Build.0 = Debug|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Debug|x64.ActiveCfg = Debug|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Debug|x64.Build.0 = Debug|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Release|Win32.ActiveCfg = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Release|Win32.Build.0 = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Release|x64.ActiveCfg = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.Release|x64.Build.0 = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.Release|x64 Setup.ActiveCfg = Release|Win32 + {E796E337-DE78-4303-8614-9A590862EE95}.Release|x86 Setup.ActiveCfg = Release|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.All|Win32.ActiveCfg = Release|x64 {419C8F80-D858-4B48-A25C-AF4007608137}.All|x64.ActiveCfg = Release|x64 {419C8F80-D858-4B48-A25C-AF4007608137}.All|x64.Build.0 = Release|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.All|x64 Setup.ActiveCfg = Release|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.All|x64 Setup.Build.0 = Release|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.All|x86 Setup.ActiveCfg = Release|x64 {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|Win32.ActiveCfg = Debug|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|Win32.Build.0 = Debug|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|x64.ActiveCfg = Debug|x64 {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|x64.Build.0 = Debug|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.Release|Win32.ActiveCfg = Release|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.Release|Win32.Build.0 = Release|Win32 {419C8F80-D858-4B48-A25C-AF4007608137}.Release|x64.ActiveCfg = Release|x64 {419C8F80-D858-4B48-A25C-AF4007608137}.Release|x64.Build.0 = Release|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.Release|x64 Setup.ActiveCfg = Release|x64 + {419C8F80-D858-4B48-A25C-AF4007608137}.Release|x86 Setup.ActiveCfg = Release|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|Win32.ActiveCfg = Release|x64 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|x64.ActiveCfg = Release|x64 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|x64.Build.0 = Release|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|x64 Setup.ActiveCfg = Release|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|x64 Setup.Build.0 = Release|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.All|x86 Setup.ActiveCfg = Release|x64 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|Win32.ActiveCfg = Debug|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|Win32.Build.0 = Debug|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|x64.ActiveCfg = Debug|x64 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|x64.Build.0 = Debug|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|Win32.ActiveCfg = Release|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|Win32.Build.0 = Release|Win32 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|x64.ActiveCfg = Release|x64 {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|x64.Build.0 = Release|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|x64 Setup.ActiveCfg = Release|x64 + {B3F424EC-3D8F-417C-B244-3919D5E1A577}.Release|x86 Setup.ActiveCfg = Release|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|Win32.ActiveCfg = Release|x64 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|x64.ActiveCfg = Release|x64 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|x64.Build.0 = Release|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|x64 Setup.ActiveCfg = Release|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|x64 Setup.Build.0 = Release|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.All|x86 Setup.ActiveCfg = Release|x64 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|Win32.ActiveCfg = Debug|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|Win32.Build.0 = Debug|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|x64.ActiveCfg = Debug|x64 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|x64.Build.0 = Debug|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|Win32.ActiveCfg = Release|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|Win32.Build.0 = Release|Win32 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|x64.ActiveCfg = Release|x64 {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|x64.Build.0 = Release|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|x64 Setup.ActiveCfg = Release|x64 + {14E4A972-9CFB-436D-B0A5-4943F3F80D47}.Release|x86 Setup.ActiveCfg = Release|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|Win32.ActiveCfg = Release|x64 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|x64.ActiveCfg = Release|x64 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|x64.Build.0 = Release|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|x64 Setup.ActiveCfg = Release|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|x64 Setup.Build.0 = Release|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.All|x86 Setup.ActiveCfg = Release|x64 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|Win32.ActiveCfg = Debug|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|Win32.Build.0 = Debug|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|x64.ActiveCfg = Debug|x64 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|x64.Build.0 = Debug|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|Win32.ActiveCfg = Release|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|Win32.Build.0 = Release|Win32 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|x64.ActiveCfg = Release|x64 {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|x64.Build.0 = Release|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|x64 Setup.ActiveCfg = Release|x64 + {1BC8A8EC-E03B-44DF-BCD9-088650F4D29C}.Release|x86 Setup.ActiveCfg = Release|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.All|Win32.ActiveCfg = Release|x64 {0B6C905B-142E-4999-B39D-92FF7951E921}.All|x64.ActiveCfg = Release|x64 {0B6C905B-142E-4999-B39D-92FF7951E921}.All|x64.Build.0 = Release|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.All|x64 Setup.ActiveCfg = Release|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.All|x64 Setup.Build.0 = Release|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.All|x86 Setup.ActiveCfg = Release|x64 {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|Win32.ActiveCfg = Debug|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|Win32.Build.0 = Debug|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|x64.ActiveCfg = Debug|x64 {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|x64.Build.0 = Debug|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|Win32.ActiveCfg = Release|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|Win32.Build.0 = Release|Win32 {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|x64.ActiveCfg = Release|x64 {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|x64.Build.0 = Release|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|x64 Setup.ActiveCfg = Release|x64 + {0B6C905B-142E-4999-B39D-92FF7951E921}.Release|x86 Setup.ActiveCfg = Release|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|Win32.ActiveCfg = Release|x64 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|x64.ActiveCfg = Release|x64 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|x64.Build.0 = Release|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|x64 Setup.ActiveCfg = Release|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|x64 Setup.Build.0 = Release|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.All|x86 Setup.ActiveCfg = Release|x64 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|Win32.ActiveCfg = Debug|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|Win32.Build.0 = Debug|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|x64.ActiveCfg = Debug|x64 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|x64.Build.0 = Debug|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|Win32.ActiveCfg = Release|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|Win32.Build.0 = Release|Win32 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|x64.ActiveCfg = Release|x64 {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|x64.Build.0 = Release|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|x64 Setup.ActiveCfg = Release|x64 + {CF405366-9558-4AE8-90EF-5E21B51CCB4E}.Release|x86 Setup.ActiveCfg = Release|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|Win32.ActiveCfg = Release|x64 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|x64.ActiveCfg = Release|x64 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|x64.Build.0 = Release|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|x64 Setup.ActiveCfg = Release|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|x64 Setup.Build.0 = Release|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.All|x86 Setup.ActiveCfg = Release|x64 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|Win32.ActiveCfg = Debug|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|Win32.Build.0 = Debug|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|x64.ActiveCfg = Debug|x64 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|x64.Build.0 = Debug|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|Win32.ActiveCfg = Release|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|Win32.Build.0 = Release|Win32 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|x64.ActiveCfg = Release|x64 {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|x64.Build.0 = Release|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|x64 Setup.ActiveCfg = Release|x64 + {D2FB8043-D208-4AEE-8F18-3B5857C871B9}.Release|x86 Setup.ActiveCfg = Release|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|Win32.ActiveCfg = Release|x64 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|x64.ActiveCfg = Release|x64 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|x64.Build.0 = Release|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|x64 Setup.ActiveCfg = Release|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|x64 Setup.Build.0 = Release|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.All|x86 Setup.ActiveCfg = Release|x64 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|Win32.ActiveCfg = Debug|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|Win32.Build.0 = Debug|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|x64.ActiveCfg = Debug|x64 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|x64.Build.0 = Debug|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|Win32.ActiveCfg = Release|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|Win32.Build.0 = Release|Win32 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|x64.ActiveCfg = Release|x64 {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|x64.Build.0 = Release|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|x64 Setup.ActiveCfg = Release|x64 + {329FD5B0-EF28-4606-86D0-F6EA21CF8E36}.Release|x86 Setup.ActiveCfg = Release|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|Win32.ActiveCfg = Release|x64 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|x64.ActiveCfg = Release|x64 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|x64.Build.0 = Release|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|x64 Setup.ActiveCfg = Release|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|x64 Setup.Build.0 = Release|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.All|x86 Setup.ActiveCfg = Release|x64 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|Win32.ActiveCfg = Debug|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|Win32.Build.0 = Debug|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|x64.ActiveCfg = Debug|x64 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|x64.Build.0 = Debug|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|Win32.ActiveCfg = Release|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|Win32.Build.0 = Release|Win32 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|x64.ActiveCfg = Release|x64 {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|x64.Build.0 = Release|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|x64 Setup.ActiveCfg = Release|x64 + {1A3793D1-05D1-4B57-9B0F-5AF3E79DC439}.Release|x86 Setup.ActiveCfg = Release|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|Win32.ActiveCfg = Release|x64 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|x64.ActiveCfg = Release|x64 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|x64.Build.0 = Release|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|x64 Setup.ActiveCfg = Release|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|x64 Setup.Build.0 = Release|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.All|x86 Setup.ActiveCfg = Release|x64 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|Win32.ActiveCfg = Debug|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|Win32.Build.0 = Debug|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|x64.ActiveCfg = Debug|x64 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|x64.Build.0 = Debug|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|Win32.ActiveCfg = Release|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|Win32.Build.0 = Release|Win32 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|x64.ActiveCfg = Release|x64 {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|x64.Build.0 = Release|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|x64 Setup.ActiveCfg = Release|x64 + {401A40CD-5DB4-4E34-AC68-FA99E9FAC014}.Release|x86 Setup.ActiveCfg = Release|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|Win32.ActiveCfg = Release|x64 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|x64.ActiveCfg = Release|x64 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|x64.Build.0 = Release|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|x64 Setup.ActiveCfg = Release|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|x64 Setup.Build.0 = Release|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.All|x86 Setup.ActiveCfg = Release|x64 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|Win32.ActiveCfg = Debug|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|Win32.Build.0 = Debug|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|x64.ActiveCfg = Debug|x64 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|x64.Build.0 = Debug|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|Win32.ActiveCfg = Release|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|Win32.Build.0 = Release|Win32 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|x64.ActiveCfg = Release|x64 {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|x64.Build.0 = Release|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|x64 Setup.ActiveCfg = Release|x64 + {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}.Release|x86 Setup.ActiveCfg = Release|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|Win32.ActiveCfg = Release_WM5_PPC_ARM|x64 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|x64.ActiveCfg = Release_WM5_PPC_ARM|x64 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|x64.Build.0 = Release_WM5_PPC_ARM|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|x64 Setup.ActiveCfg = Release_WM5_PPC_ARM|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|x64 Setup.Build.0 = Release_WM5_PPC_ARM|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.All|x86 Setup.ActiveCfg = Release_WM5_PPC_ARM|x64 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|Win32.ActiveCfg = Debug|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|Win32.Build.0 = Debug|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|x64.ActiveCfg = Debug|x64 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|x64.Build.0 = Debug|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|Win32.ActiveCfg = Release|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|Win32.Build.0 = Release|Win32 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|x64.ActiveCfg = Release|x64 {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|x64.Build.0 = Release|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|x64 Setup.ActiveCfg = Release|x64 + {E972C52F-9E85-4D65-B19C-031E511E9DB4}.Release|x86 Setup.ActiveCfg = Release|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|Win32.ActiveCfg = Release_Static_SSE|x64 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|x64.ActiveCfg = Release_Static_SSE|x64 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|x64.Build.0 = Release_Static_SSE|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|x64 Setup.ActiveCfg = Release_Static_SSE|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|x64 Setup.Build.0 = Release_Static_SSE|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.All|x86 Setup.ActiveCfg = Release_Static_SSE|x64 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|Win32.ActiveCfg = Debug|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|Win32.Build.0 = Debug|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|x64.ActiveCfg = Debug|x64 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|x64.Build.0 = Debug|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|Win32.ActiveCfg = Release|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|Win32.Build.0 = Release|Win32 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|x64.ActiveCfg = Release|x64 {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|x64.Build.0 = Release|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|x64 Setup.ActiveCfg = Release|x64 + {03207781-0D1C-4DB3-A71D-45C608F28DBD}.Release|x86 Setup.ActiveCfg = Release|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|Win32.ActiveCfg = Release|x64 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|x64.ActiveCfg = Release|x64 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|x64.Build.0 = Release|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|x64 Setup.ActiveCfg = Release|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|x64 Setup.Build.0 = Release|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.All|x86 Setup.ActiveCfg = Release|x64 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|Win32.ActiveCfg = Debug|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|Win32.Build.0 = Debug|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|x64.ActiveCfg = Debug|x64 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|x64.Build.0 = Debug|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|Win32.ActiveCfg = Release|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|Win32.Build.0 = Release|Win32 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|x64.ActiveCfg = Release|x64 {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|x64.Build.0 = Release|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|x64 Setup.ActiveCfg = Release|x64 + {9A5DDF08-C88C-4A35-B7F6-D605228446BD}.Release|x86 Setup.ActiveCfg = Release|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.All|Win32.ActiveCfg = Release|x64 {D0B36172-CD76-454A-9B89-990025266C2A}.All|x64.ActiveCfg = Release|x64 {D0B36172-CD76-454A-9B89-990025266C2A}.All|x64.Build.0 = Release|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.All|x64 Setup.ActiveCfg = Release|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.All|x64 Setup.Build.0 = Release|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.All|x86 Setup.ActiveCfg = Release|x64 {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|Win32.ActiveCfg = Debug|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|Win32.Build.0 = Debug|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|x64.ActiveCfg = Debug|x64 {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|x64.Build.0 = Debug|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.Release|Win32.ActiveCfg = Release|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.Release|Win32.Build.0 = Release|Win32 {D0B36172-CD76-454A-9B89-990025266C2A}.Release|x64.ActiveCfg = Release|x64 {D0B36172-CD76-454A-9B89-990025266C2A}.Release|x64.Build.0 = Release|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.Release|x64 Setup.ActiveCfg = Release|x64 + {D0B36172-CD76-454A-9B89-990025266C2A}.Release|x86 Setup.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|Win32.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|Win32.Build.0 = Release|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|x64.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|x64 Setup.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|x86 Setup.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.All|x86 Setup.Build.0 = Release|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.Debug|Win32.ActiveCfg = Debug|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.Debug|x64.ActiveCfg = Debug|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.Release|Win32.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-6338E2526666}.Release|x64.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.Release|x64 Setup.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-6338E2526666}.Release|x86 Setup.ActiveCfg = Release|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|Win32.ActiveCfg = Release|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|x64.ActiveCfg = Release|Win32 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|x64 Setup.ActiveCfg = Release|Win32 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|x86 Setup.ActiveCfg = Release|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Debug|Win32.ActiveCfg = Debug|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Debug|x64.ActiveCfg = Debug|x64 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Release|Win32.ActiveCfg = Release|Win32 {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Release|x64.ActiveCfg = Release|x64 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Release|x64 Setup.ActiveCfg = Release|x64 + {CC1DD008-9406-448D-A0AD-33C3186CFADB}.Release|x86 Setup.ActiveCfg = Release|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|Win32.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|Win32.Build.0 = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|x64.ActiveCfg = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|x64 Setup.ActiveCfg = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|x86 Setup.ActiveCfg = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.All|x86 Setup.Build.0 = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|Win32.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|Win32.Build.0 = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|x64.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|x64.Build.0 = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|x64 Setup.ActiveCfg = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Debug|x86 Setup.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|Win32.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|Win32.Build.0 = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|x64.ActiveCfg = All|Win32 {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|x64.Build.0 = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|x64 Setup.ActiveCfg = All|Win32 + {DEE932AB-5911-4700-9EEB-8C7090A0A330}.Release|x86 Setup.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|Win32.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|Win32.Build.0 = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|x64.ActiveCfg = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|x64 Setup.ActiveCfg = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|x86 Setup.ActiveCfg = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.All|x86 Setup.Build.0 = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|Win32.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|Win32.Build.0 = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|x64.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|x64.Build.0 = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|x64 Setup.ActiveCfg = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Debug|x86 Setup.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|Win32.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|Win32.Build.0 = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|x64.ActiveCfg = All|Win32 {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|x64.Build.0 = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|x64 Setup.ActiveCfg = All|Win32 + {329A6FA0-0FCC-4435-A950-E670AEFA9838}.Release|x86 Setup.ActiveCfg = All|Win32 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|Win32.ActiveCfg = Release|x64 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|x64.ActiveCfg = Release|x64 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|x64.Build.0 = Release|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|x64 Setup.ActiveCfg = Release|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|x64 Setup.Build.0 = Release|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.All|x86 Setup.ActiveCfg = Release|x64 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Debug|Win32.ActiveCfg = Debug|Win32 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Debug|x64.ActiveCfg = Debug|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Release|Win32.ActiveCfg = Release|Win32 {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Release|x64.ActiveCfg = Release|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Release|x64 Setup.ActiveCfg = Release|x64 + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}.Release|x86 Setup.ActiveCfg = Release|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|Win32.ActiveCfg = Release|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|Win32.Build.0 = Release|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|x64.ActiveCfg = Release|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|x64 Setup.ActiveCfg = Release|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|x86 Setup.ActiveCfg = Release|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.All|x86 Setup.Build.0 = Release|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Debug|Win32.ActiveCfg = Debug|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Debug|x64.ActiveCfg = Debug|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Release|Win32.ActiveCfg = Release|Win32 {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Release|x64.ActiveCfg = Release|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Release|x64 Setup.ActiveCfg = Release|Win32 + {C6E78A4C-DB1E-47F4-9B63-4DC27D86343F}.Release|x86 Setup.ActiveCfg = Release|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.All|Win32.ActiveCfg = Release|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.All|x64.ActiveCfg = Release|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.All|x64 Setup.ActiveCfg = Release|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.All|x86 Setup.ActiveCfg = Release|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.Debug|Win32.ActiveCfg = Debug|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.Debug|x64.ActiveCfg = Debug|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.Release|Win32.ActiveCfg = Release|Win32 {1F0A8A77-E661-418F-BB92-82172AE43803}.Release|x64.ActiveCfg = Release|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.Release|x64 Setup.ActiveCfg = Release|Win32 + {1F0A8A77-E661-418F-BB92-82172AE43803}.Release|x86 Setup.ActiveCfg = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|Win32.ActiveCfg = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|Win32.Build.0 = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x64.ActiveCfg = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x64.Build.0 = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x64 Setup.ActiveCfg = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x64 Setup.Build.0 = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x86 Setup.ActiveCfg = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.All|x86 Setup.Build.0 = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|Win32.ActiveCfg = Debug|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|Win32.Build.0 = Debug|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|x64.ActiveCfg = Debug|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|x64.Build.0 = Debug|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|Win32.ActiveCfg = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|Win32.Build.0 = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|x64.ActiveCfg = Release|Win32 {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|x64.Build.0 = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|x64 Setup.ActiveCfg = Release|Win32 + {4F5C9D55-98EF-4256-8311-32D7BD360406}.Release|x86 Setup.ActiveCfg = Release|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.All|Win32.ActiveCfg = Release|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.All|x64.ActiveCfg = Release|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.All|x64 Setup.ActiveCfg = Release|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.All|x86 Setup.ActiveCfg = Release|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Debug|Win32.ActiveCfg = Debug|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Debug|x64.ActiveCfg = Debug|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Release|Win32.ActiveCfg = Release|Win32 {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Release|x64.ActiveCfg = Release|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Release|x64 Setup.ActiveCfg = Release|Win32 + {E10571C4-E7F4-4608-B5F2-B22E7EB95400}.Release|x86 Setup.ActiveCfg = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|Win32.ActiveCfg = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|Win32.Build.0 = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x64.ActiveCfg = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x64.Build.0 = Release|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x64 Setup.ActiveCfg = Release|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x64 Setup.Build.0 = Release|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x86 Setup.ActiveCfg = Release|Win32 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.All|x86 Setup.Build.0 = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|Win32.ActiveCfg = Debug|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|Win32.Build.0 = Debug|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.ActiveCfg = Debug|x64 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64.Build.0 = Debug|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|Win32.ActiveCfg = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|Win32.Build.0 = Release|Win32 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.ActiveCfg = Release|x64 {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64.Build.0 = Release|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x64 Setup.ActiveCfg = Release|x64 + {D1ABE208-6442-4FB4-9AAD-1677E41BC870}.Release|x86 Setup.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|Win32.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|x64.ActiveCfg = Release|Win32 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|x64 Setup.ActiveCfg = Release|Win32 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.All|x86 Setup.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|Win32.ActiveCfg = Debug|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|x64.ActiveCfg = Debug|x64 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|Win32.ActiveCfg = Release|Win32 {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|x64.ActiveCfg = Release|x64 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|x64 Setup.ActiveCfg = Release|x64 + {BA599D0A-4310-4505-91DA-6A6447B3E289}.Release|x86 Setup.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|Win32.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|x64.ActiveCfg = Release|Win32 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|x64 Setup.ActiveCfg = Release|Win32 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.All|x86 Setup.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|Win32.ActiveCfg = Debug|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|x64.ActiveCfg = Debug|x64 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|Win32.ActiveCfg = Release|Win32 {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|x64.ActiveCfg = Release|x64 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|x64 Setup.ActiveCfg = Release|x64 + {EED13FC7-4F81-4E6F-93DB-CDB7DF5CF959}.Release|x86 Setup.ActiveCfg = Release|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|Win32.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64.Build.0 = Release|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64 Setup.ActiveCfg = Release|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x64 Setup.Build.0 = Release|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.All|x86 Setup.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|Win32.ActiveCfg = Debug|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|Win32.Build.0 = Debug|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|x64.ActiveCfg = Debug|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|x64.Build.0 = Debug|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|Win32.ActiveCfg = Release|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|Win32.Build.0 = Release|Win32 {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|x64.ActiveCfg = Release|x64 {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|x64.Build.0 = Release|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|x64 Setup.ActiveCfg = Release|x64 + {70564D74-199A-4452-9C60-19ED5F242F0D}.Release|x86 Setup.ActiveCfg = Release|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|Win32.ActiveCfg = Release|x64 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|x64.ActiveCfg = Release|x64 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|x64.Build.0 = Release|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|x64 Setup.ActiveCfg = Release|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|x64 Setup.Build.0 = Release|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.All|x86 Setup.ActiveCfg = Release|x64 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|Win32.ActiveCfg = Debug|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|Win32.Build.0 = Debug|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|x64.ActiveCfg = Debug|x64 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|x64.Build.0 = Debug|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|Win32.ActiveCfg = Release|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|Win32.Build.0 = Release|Win32 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|x64.ActiveCfg = Release|x64 {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|x64.Build.0 = Release|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|x64 Setup.ActiveCfg = Release|x64 + {3C977801-FE88-48F2-83D3-FA2EBFF6688E}.Release|x86 Setup.ActiveCfg = Release|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|Win32.ActiveCfg = Release|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|Win32.Build.0 = Release|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x64.ActiveCfg = Release|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x64.Build.0 = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x64 Setup.ActiveCfg = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x64 Setup.Build.0 = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x86 Setup.ActiveCfg = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.All|x86 Setup.Build.0 = Release|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|Win32.ActiveCfg = Debug|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|Win32.Build.0 = Debug|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|x64.ActiveCfg = Debug|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|x64.Build.0 = Debug|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|Win32.ActiveCfg = Release|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|Win32.Build.0 = Release|Win32 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|x64.ActiveCfg = Release|x64 {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|x64.Build.0 = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|x64 Setup.ActiveCfg = Release|x64 + {0382E8FD-CFDC-41C0-8B03-792C7C84FC31}.Release|x86 Setup.ActiveCfg = Release|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.All|Win32.ActiveCfg = Release|x64 {432DB165-1EB2-4781-A9C0-71E62610B20A}.All|x64.ActiveCfg = Release|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.All|x64 Setup.ActiveCfg = Release|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.All|x86 Setup.ActiveCfg = Release|x64 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|Win32.ActiveCfg = Debug|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|Win32.Build.0 = Debug|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|x64.ActiveCfg = Debug|x64 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|x64.Build.0 = Debug|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|Win32.ActiveCfg = Release|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|Win32.Build.0 = Release|Win32 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|x64.ActiveCfg = Release|x64 {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|x64.Build.0 = Release|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|x64 Setup.ActiveCfg = Release|x64 + {432DB165-1EB2-4781-A9C0-71E62610B20A}.Release|x86 Setup.ActiveCfg = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|Win32.ActiveCfg = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|Win32.Build.0 = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|x64.ActiveCfg = Release|Win32 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|x64 Setup.ActiveCfg = Release|Win32 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|x86 Setup.ActiveCfg = Release|Win32 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.All|x86 Setup.Build.0 = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|Win32.ActiveCfg = Debug|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|Win32.Build.0 = Debug|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|x64.ActiveCfg = Debug|x64 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|x64.Build.0 = Debug|x64 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|Win32.ActiveCfg = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|Win32.Build.0 = Release|Win32 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|x64.ActiveCfg = Release|x64 {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|x64.Build.0 = Release|x64 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|x64 Setup.ActiveCfg = Release|x64 + {CF70F278-3364-4395-A2E1-23501C9B8AD2}.Release|x86 Setup.ActiveCfg = Release|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|Win32.ActiveCfg = Release|x64 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|x64.ActiveCfg = Release|x64 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|x64.Build.0 = Release|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|x64 Setup.ActiveCfg = Release|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|x64 Setup.Build.0 = Release|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.All|x86 Setup.ActiveCfg = Release|x64 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|Win32.ActiveCfg = Debug|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|Win32.Build.0 = Debug|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|x64.ActiveCfg = Debug|x64 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|x64.Build.0 = Debug|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|Win32.ActiveCfg = Release|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|Win32.Build.0 = Release|Win32 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|x64.ActiveCfg = Release|x64 {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|x64.Build.0 = Release|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|x64 Setup.ActiveCfg = Release|x64 + {D5C87B19-150D-4EF3-A671-96589BD2D14A}.Release|x86 Setup.ActiveCfg = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|Win32.ActiveCfg = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|Win32.Build.0 = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|x64.ActiveCfg = Release|Win32 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|x64 Setup.ActiveCfg = Release|Win32 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|x86 Setup.ActiveCfg = Release|Win32 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.All|x86 Setup.Build.0 = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|Win32.ActiveCfg = Debug|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|Win32.Build.0 = Debug|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|x64.ActiveCfg = Debug|x64 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|x64.Build.0 = Debug|x64 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|Win32.ActiveCfg = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|Win32.Build.0 = Release|Win32 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|x64.ActiveCfg = Release|x64 {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|x64.Build.0 = Release|x64 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|x64 Setup.ActiveCfg = Release|x64 + {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}.Release|x86 Setup.ActiveCfg = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|Win32.ActiveCfg = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|Win32.Build.0 = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|x64.ActiveCfg = Release|Win32 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|x64 Setup.ActiveCfg = Release|Win32 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|x86 Setup.ActiveCfg = Release|Win32 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.All|x86 Setup.Build.0 = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|Win32.ActiveCfg = Debug|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|Win32.Build.0 = Debug|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|x64.ActiveCfg = Debug|x64 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|x64.Build.0 = Debug|x64 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|Win32.ActiveCfg = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|Win32.Build.0 = Release|Win32 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|x64.ActiveCfg = Release|x64 {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|x64.Build.0 = Release|x64 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|x64 Setup.ActiveCfg = Release|x64 + {B5A00BFA-6083-4FAE-A097-71642D6473B5}.Release|x86 Setup.ActiveCfg = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|Win32.ActiveCfg = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|Win32.Build.0 = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|x64.ActiveCfg = Release|Win32 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|x64 Setup.ActiveCfg = Release|Win32 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|x86 Setup.ActiveCfg = Release|Win32 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.All|x86 Setup.Build.0 = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|Win32.ActiveCfg = Debug|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|Win32.Build.0 = Debug|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|x64.ActiveCfg = Debug|x64 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|x64.Build.0 = Debug|x64 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|Win32.ActiveCfg = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|Win32.Build.0 = Release|Win32 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|x64.ActiveCfg = Release|x64 {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|x64.Build.0 = Release|x64 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|x64 Setup.ActiveCfg = Release|x64 + {1C320193-46A6-4B34-9C56-8AB584FC1B56}.Release|x86 Setup.ActiveCfg = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|Win32.ActiveCfg = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|Win32.Build.0 = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|x64.ActiveCfg = Release|Win32 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|x64 Setup.ActiveCfg = Release|Win32 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|x86 Setup.ActiveCfg = Release|Win32 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.All|x86 Setup.Build.0 = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|Win32.ActiveCfg = Debug|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|Win32.Build.0 = Debug|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|x64.ActiveCfg = Debug|x64 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|x64.Build.0 = Debug|x64 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|Win32.ActiveCfg = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|Win32.Build.0 = Release|Win32 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|x64.ActiveCfg = Release|x64 {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|x64.Build.0 = Release|x64 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|x64 Setup.ActiveCfg = Release|x64 + {72782932-37CC-46AE-8C7F-9A7B1A6EE108}.Release|x86 Setup.ActiveCfg = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|Win32.ActiveCfg = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|Win32.Build.0 = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|x64.ActiveCfg = Release|Win32 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|x64 Setup.ActiveCfg = Release|Win32 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|x86 Setup.ActiveCfg = Release|Win32 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.All|x86 Setup.Build.0 = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|Win32.ActiveCfg = Debug|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|Win32.Build.0 = Debug|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|x64.ActiveCfg = Debug|x64 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|x64.Build.0 = Debug|x64 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|Win32.ActiveCfg = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|Win32.Build.0 = Release|Win32 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|x64.ActiveCfg = Release|x64 {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|x64.Build.0 = Release|x64 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|x64 Setup.ActiveCfg = Release|x64 + {12A49562-BAB9-43A3-A21D-15B60BBB4C31}.Release|x86 Setup.ActiveCfg = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|Win32.ActiveCfg = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|Win32.Build.0 = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|x64.ActiveCfg = Release|Win32 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|x64 Setup.ActiveCfg = Release|Win32 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|x86 Setup.ActiveCfg = Release|Win32 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.All|x86 Setup.Build.0 = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|Win32.ActiveCfg = Debug|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|Win32.Build.0 = Debug|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|x64.ActiveCfg = Debug|x64 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|x64.Build.0 = Debug|x64 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|Win32.ActiveCfg = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|Win32.Build.0 = Release|Win32 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|x64.ActiveCfg = Release|x64 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|x64.Build.0 = Release|x64 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|x64 Setup.ActiveCfg = Release|x64 + {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}.Release|x86 Setup.ActiveCfg = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.All|Win32.ActiveCfg = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.All|Win32.Build.0 = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.All|x64.ActiveCfg = Release|Win32 + {504B3154-7A4F-459D-9877-B951021C3F1F}.All|x64 Setup.ActiveCfg = Release|Win32 + {504B3154-7A4F-459D-9877-B951021C3F1F}.All|x86 Setup.ActiveCfg = Release|Win32 + {504B3154-7A4F-459D-9877-B951021C3F1F}.All|x86 Setup.Build.0 = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|Win32.ActiveCfg = Debug|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|Win32.Build.0 = Debug|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|x64.ActiveCfg = Debug|x64 {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|x64.Build.0 = Debug|x64 + {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {504B3154-7A4F-459D-9877-B951021C3F1F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|Win32.ActiveCfg = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|Win32.Build.0 = Release|Win32 {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|x64.ActiveCfg = Release|x64 {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|x64.Build.0 = Release|x64 + {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|x64 Setup.ActiveCfg = Release|x64 + {504B3154-7A4F-459D-9877-B951021C3F1F}.Release|x86 Setup.ActiveCfg = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|Win32.ActiveCfg = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|Win32.Build.0 = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|x64.ActiveCfg = Release|Win32 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|x64 Setup.ActiveCfg = Release|Win32 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|x86 Setup.ActiveCfg = Release|Win32 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.All|x86 Setup.Build.0 = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|Win32.ActiveCfg = Debug|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|Win32.Build.0 = Debug|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|x64.ActiveCfg = Debug|x64 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|x64.Build.0 = Debug|x64 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|Win32.ActiveCfg = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|Win32.Build.0 = Release|Win32 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|x64.ActiveCfg = Release|x64 {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|x64.Build.0 = Release|x64 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|x64 Setup.ActiveCfg = Release|x64 + {746F3632-5BB2-4570-9453-31D6D58A7D8E}.Release|x86 Setup.ActiveCfg = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|Win32.ActiveCfg = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|Win32.Build.0 = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|x64.ActiveCfg = Release|Win32 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|x64 Setup.ActiveCfg = Release|Win32 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|x86 Setup.ActiveCfg = Release|Win32 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.All|x86 Setup.Build.0 = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|Win32.ActiveCfg = Debug|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|Win32.Build.0 = Debug|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|x64.ActiveCfg = Debug|x64 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|x64.Build.0 = Debug|x64 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|Win32.ActiveCfg = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|Win32.Build.0 = Release|Win32 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|x64.ActiveCfg = Release|x64 {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|x64.Build.0 = Release|x64 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|x64 Setup.ActiveCfg = Release|x64 + {DEB01ACB-D65F-4A62-AED9-58C1054499E9}.Release|x86 Setup.ActiveCfg = Release|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|Win32.ActiveCfg = Release|x64 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|x64.ActiveCfg = Release|x64 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|x64.Build.0 = Release|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|x64 Setup.ActiveCfg = Release|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|x64 Setup.Build.0 = Release|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.All|x86 Setup.ActiveCfg = Release|x64 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|Win32.ActiveCfg = Debug|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|Win32.Build.0 = Debug|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|x64.ActiveCfg = Debug|x64 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|x64.Build.0 = Debug|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|Win32.ActiveCfg = Release|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|Win32.Build.0 = Release|Win32 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|x64.ActiveCfg = Release|x64 {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|x64.Build.0 = Release|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|x64 Setup.ActiveCfg = Release|x64 + {D07C378A-F5F7-438F-ADF3-4AC4FB1883CD}.Release|x86 Setup.ActiveCfg = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|Win32.ActiveCfg = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|Win32.Build.0 = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|x64.ActiveCfg = Release|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|x64 Setup.ActiveCfg = Release|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|x86 Setup.ActiveCfg = Release|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.All|x86 Setup.Build.0 = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|Win32.ActiveCfg = Debug|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|Win32.Build.0 = Debug|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|x64.ActiveCfg = Debug|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|x64.Build.0 = Debug|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|Win32.ActiveCfg = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|Win32.Build.0 = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|x64.ActiveCfg = Release|Win32 {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|x64.Build.0 = Release|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|x64 Setup.ActiveCfg = Release|Win32 + {FFF82F9B-6A2B-4BE3-95D8-DC5A4FC71E19}.Release|x86 Setup.ActiveCfg = Release|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|Win32.ActiveCfg = Release|x64 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|x64.ActiveCfg = Release|x64 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|x64.Build.0 = Release|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|x64 Setup.ActiveCfg = Release|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|x64 Setup.Build.0 = Release|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.All|x86 Setup.ActiveCfg = Release|x64 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|Win32.ActiveCfg = Debug|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|Win32.Build.0 = Debug|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|x64.ActiveCfg = Debug|x64 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|x64.Build.0 = Debug|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|Win32.ActiveCfg = Release|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|Win32.Build.0 = Release|Win32 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|x64.ActiveCfg = Release|x64 {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|x64.Build.0 = Release|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|x64 Setup.ActiveCfg = Release|x64 + {ABB71A76-42B0-47A4-973A-42E3D920C6FD}.Release|x86 Setup.ActiveCfg = Release|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|Win32.ActiveCfg = Release Passthrough|x64 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|x64.ActiveCfg = Release Passthrough|x64 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|x64.Build.0 = Release Passthrough|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|x64 Setup.ActiveCfg = Release Passthrough|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|x64 Setup.Build.0 = Release Passthrough|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.All|x86 Setup.ActiveCfg = Release Passthrough|x64 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|Win32.ActiveCfg = Debug|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|Win32.Build.0 = Debug|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|x64.ActiveCfg = Debug|x64 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|x64.Build.0 = Debug|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|Win32.ActiveCfg = Release|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|Win32.Build.0 = Release|Win32 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|x64.ActiveCfg = Release|x64 {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|x64.Build.0 = Release|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|x64 Setup.ActiveCfg = Release|x64 + {4D418176-3B33-47E6-A63E-01BA34ADD21C}.Release|x86 Setup.ActiveCfg = Release|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|Win32.ActiveCfg = Release|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|Win32.Build.0 = Release|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|x64.ActiveCfg = Release|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|x64 Setup.ActiveCfg = Release|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|x86 Setup.ActiveCfg = Release|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.All|x86 Setup.Build.0 = Release|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Debug|Win32.ActiveCfg = Debug|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Debug|x64.ActiveCfg = Debug|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Release|Win32.ActiveCfg = Release|Win32 {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Release|x64.ActiveCfg = Release|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Release|x64 Setup.ActiveCfg = Release|Win32 + {7D3122C7-C9D0-3748-81F8-F0DDCB40BF5E}.Release|x86 Setup.ActiveCfg = Release|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|Win32.ActiveCfg = Release|x64 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|x64.ActiveCfg = Release|x64 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|x64.Build.0 = Release|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|x64 Setup.ActiveCfg = Release|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|x64 Setup.Build.0 = Release|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.All|x86 Setup.ActiveCfg = Release|x64 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|Win32.ActiveCfg = Debug|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|Win32.Build.0 = Debug|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|x64.ActiveCfg = Debug|x64 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|x64.Build.0 = Debug|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|Win32.ActiveCfg = Release|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|Win32.Build.0 = Release|Win32 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|x64.ActiveCfg = Release|x64 {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|x64.Build.0 = Release|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|x64 Setup.ActiveCfg = Release|x64 + {EF300386-A8DF-4372-B6D8-FB9BFFCA9AED}.Release|x86 Setup.ActiveCfg = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|Win32.ActiveCfg = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|Win32.Build.0 = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|x64.ActiveCfg = Release|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|x64 Setup.ActiveCfg = Release|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|x86 Setup.ActiveCfg = Release|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.All|x86 Setup.Build.0 = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|Win32.ActiveCfg = Debug|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|Win32.Build.0 = Debug|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|x64.ActiveCfg = Debug|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|x64.Build.0 = Debug|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|Win32.ActiveCfg = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|Win32.Build.0 = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|x64.ActiveCfg = Release|Win32 {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|x64.Build.0 = Release|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|x64 Setup.ActiveCfg = Release|Win32 + {B808178B-82F0-4CF4-A2B1-921939FA24D0}.Release|x86 Setup.ActiveCfg = Release|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|Win32.ActiveCfg = Release|x64 {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|x64.ActiveCfg = Release|x64 {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|x64.Build.0 = Release|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|x64 Setup.ActiveCfg = Release|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|x64 Setup.Build.0 = Release|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.All|x86 Setup.ActiveCfg = Release|x64 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|Win32.ActiveCfg = Debug|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|Win32.Build.0 = Debug|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|x64.ActiveCfg = Debug|x64 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|x64.Build.0 = Debug|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|Win32.ActiveCfg = Release|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|Win32.Build.0 = Release|Win32 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|x64.ActiveCfg = Release|x64 {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|x64.Build.0 = Release|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|x64 Setup.ActiveCfg = Release|x64 + {9778F1C0-09BC-4698-8EBC-BD982247209A}.Release|x86 Setup.ActiveCfg = Release|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|Win32.ActiveCfg = Release|x64 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|x64.ActiveCfg = Release|x64 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|x64.Build.0 = Release|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|x64 Setup.ActiveCfg = Release|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|x64 Setup.Build.0 = Release|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.All|x86 Setup.ActiveCfg = Release|x64 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|Win32.ActiveCfg = Debug|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|Win32.Build.0 = Debug|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|x64.ActiveCfg = Debug|x64 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|x64.Build.0 = Debug|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|Win32.ActiveCfg = Release|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|Win32.Build.0 = Release|Win32 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|x64.ActiveCfg = Release|x64 {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|x64.Build.0 = Release|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|x64 Setup.ActiveCfg = Release|x64 + {AFA983D6-4569-4F88-BA94-555ED00FD9A8}.Release|x86 Setup.ActiveCfg = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|Win32.ActiveCfg = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|Win32.Build.0 = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|x64.ActiveCfg = Release|Win32 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|x64 Setup.ActiveCfg = Release|Win32 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|x86 Setup.ActiveCfg = Release|Win32 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.All|x86 Setup.Build.0 = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.ActiveCfg = Debug|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|Win32.Build.0 = Debug|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x64.ActiveCfg = Debug|x64 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x64.Build.0 = Debug|x64 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.ActiveCfg = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|Win32.Build.0 = Release|Win32 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x64.ActiveCfg = Release|x64 {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x64.Build.0 = Release|x64 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x64 Setup.ActiveCfg = Release|x64 + {56B91D01-9150-4BBF-AFA1-5B68AB991B76}.Release|x86 Setup.ActiveCfg = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|Win32.ActiveCfg = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|Win32.Build.0 = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|x64.ActiveCfg = Release|Win32 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|x64 Setup.ActiveCfg = Release|Win32 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|x86 Setup.ActiveCfg = Release|Win32 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.All|x86 Setup.Build.0 = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|Win32.ActiveCfg = Debug|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|Win32.Build.0 = Debug|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|x64.ActiveCfg = Debug|x64 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|x64.Build.0 = Debug|x64 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|Win32.ActiveCfg = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|Win32.Build.0 = Release|Win32 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|x64.ActiveCfg = Release|x64 {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|x64.Build.0 = Release|x64 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|x64 Setup.ActiveCfg = Release|x64 + {990BAA76-89D3-4E38-8479-C7B28784EFC8}.Release|x86 Setup.ActiveCfg = Release|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|Win32.ActiveCfg = Release|x64 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|x64.ActiveCfg = Release|x64 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|x64.Build.0 = Release|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|x64 Setup.ActiveCfg = Release|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|x64 Setup.Build.0 = Release|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.All|x86 Setup.ActiveCfg = Release|x64 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|Win32.ActiveCfg = Debug|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|Win32.Build.0 = Debug|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|x64.ActiveCfg = Debug|x64 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|x64.Build.0 = Debug|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|Win32.ActiveCfg = Release|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|Win32.Build.0 = Release|Win32 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|x64.ActiveCfg = Release|x64 {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|x64.Build.0 = Release|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|x64 Setup.ActiveCfg = Release|x64 + {1E21AFE0-6FDB-41D2-942D-863607C24B91}.Release|x86 Setup.ActiveCfg = Release|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|Win32.ActiveCfg = Release|x64 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|x64.ActiveCfg = Release|x64 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|x64.Build.0 = Release|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|x64 Setup.ActiveCfg = Release|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|x64 Setup.Build.0 = Release|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.All|x86 Setup.ActiveCfg = Release|x64 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|Win32.ActiveCfg = Debug|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|Win32.Build.0 = Debug|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|x64.ActiveCfg = Debug|x64 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|x64.Build.0 = Debug|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|Win32.ActiveCfg = Release|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|Win32.Build.0 = Release|Win32 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|x64.ActiveCfg = Release|x64 {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|x64.Build.0 = Release|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|x64 Setup.ActiveCfg = Release|x64 + {2E250296-0C08-4342-9C8A-BCBDD0E7DF65}.Release|x86 Setup.ActiveCfg = Release|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|Win32.ActiveCfg = Release|x64 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|x64.ActiveCfg = Release|x64 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|x64.Build.0 = Release|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|x64 Setup.ActiveCfg = Release|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|x64 Setup.Build.0 = Release|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.All|x86 Setup.ActiveCfg = Release|x64 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|Win32.ActiveCfg = Debug|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|Win32.Build.0 = Debug|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|x64.ActiveCfg = Debug|x64 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|x64.Build.0 = Debug|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|Win32.ActiveCfg = Release|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|Win32.Build.0 = Release|Win32 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|x64.ActiveCfg = Release|x64 {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|x64.Build.0 = Release|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|x64 Setup.ActiveCfg = Release|x64 + {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}.Release|x86 Setup.ActiveCfg = Release|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|Win32.ActiveCfg = Release|x64 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|x64.ActiveCfg = Release|x64 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|x64.Build.0 = Release|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|x64 Setup.ActiveCfg = Release|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|x64 Setup.Build.0 = Release|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.All|x86 Setup.ActiveCfg = Release|x64 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|Win32.ActiveCfg = Debug|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|Win32.Build.0 = Debug|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|x64.ActiveCfg = Debug|x64 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|x64.Build.0 = Debug|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|Win32.ActiveCfg = Release|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|Win32.Build.0 = Release|Win32 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|x64.ActiveCfg = Release|x64 {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|x64.Build.0 = Release|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|x64 Setup.ActiveCfg = Release|x64 + {B4B62169-5AD4-4559-8707-3D933AC5DB39}.Release|x86 Setup.ActiveCfg = Release|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|Win32.ActiveCfg = Release|x64 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|x64.ActiveCfg = Release|x64 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|x64.Build.0 = Release|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|x64 Setup.ActiveCfg = Release|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|x64 Setup.Build.0 = Release|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.All|x86 Setup.ActiveCfg = Release|x64 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|Win32.ActiveCfg = Debug|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|Win32.Build.0 = Debug|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|x64.ActiveCfg = Debug|x64 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|x64.Build.0 = Debug|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|Win32.ActiveCfg = Release|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|Win32.Build.0 = Release|Win32 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|x64.ActiveCfg = Release|x64 {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|x64.Build.0 = Release|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|x64 Setup.ActiveCfg = Release|x64 + {25BD39B1-C8BF-4676-A738-9CABD9C6BC79}.Release|x86 Setup.ActiveCfg = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|Win32.ActiveCfg = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|Win32.Build.0 = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|x64.ActiveCfg = Release|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|x64 Setup.ActiveCfg = Release|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|x86 Setup.ActiveCfg = Release|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.All|x86 Setup.Build.0 = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|Win32.ActiveCfg = Debug|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|Win32.Build.0 = Debug|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|x64.ActiveCfg = Debug|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|x64.Build.0 = Debug|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|x64 Setup.ActiveCfg = Debug|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|Win32.ActiveCfg = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|Win32.Build.0 = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|x64.ActiveCfg = Release|Win32 {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|x64.Build.0 = Release|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|x64 Setup.ActiveCfg = Release|Win32 + {D578E676-7EC8-4548-BD8B-845C635F14AD}.Release|x86 Setup.ActiveCfg = Release|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|Win32.ActiveCfg = Release|x64 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|x64.ActiveCfg = Release|x64 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|x64.Build.0 = Release|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|x64 Setup.ActiveCfg = Release|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|x64 Setup.Build.0 = Release|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.All|x86 Setup.ActiveCfg = Release|x64 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|Win32.ActiveCfg = Debug|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|Win32.Build.0 = Debug|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|x64.ActiveCfg = Debug|x64 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|x64.Build.0 = Debug|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|Win32.ActiveCfg = Release|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|Win32.Build.0 = Release|Win32 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|x64.ActiveCfg = Release|x64 {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|x64.Build.0 = Release|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|x64 Setup.ActiveCfg = Release|x64 + {70A49BC2-7500-41D0-B75D-EDCC5BE987A0}.Release|x86 Setup.ActiveCfg = Release|Win32 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|Win32.ActiveCfg = Release|x64 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|x64.ActiveCfg = Release|x64 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|x64.Build.0 = Release|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|x64 Setup.ActiveCfg = Release|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|x64 Setup.Build.0 = Release|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.All|x86 Setup.ActiveCfg = Release|x64 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Debug|Win32.ActiveCfg = Debug|Win32 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Debug|x64.ActiveCfg = Debug|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Release|Win32.ActiveCfg = Release|Win32 {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Release|x64.ActiveCfg = Release|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Release|x64 Setup.ActiveCfg = Release|x64 + {B889A18E-70A7-44B5-B2C9-47798D4F43B3}.Release|x86 Setup.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|Win32.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|Win32.Build.0 = Release|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|x64.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|x64 Setup.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|x86 Setup.ActiveCfg = Release|Win32 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.All|x86 Setup.Build.0 = Release|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.Debug|Win32.ActiveCfg = Debug|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.Debug|x64.ActiveCfg = Debug|x64 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|Win32.ActiveCfg = Release|Win32 {05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|x64.ActiveCfg = Release|x64 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|x64 Setup.ActiveCfg = Release|x64 + {05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|x86 Setup.ActiveCfg = Release|Win32 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|Win32.ActiveCfg = Release|x64 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|x64.ActiveCfg = Release|x64 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|x64.Build.0 = Release|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|x64 Setup.ActiveCfg = Release|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|x64 Setup.Build.0 = Release|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.All|x86 Setup.ActiveCfg = Release|x64 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Debug|Win32.ActiveCfg = Debug|Win32 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Debug|x64.ActiveCfg = Debug|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Debug|x86 Setup.ActiveCfg = Debug|Win32 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Release|Win32.ActiveCfg = Release|Win32 {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Release|x64.ActiveCfg = Release|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Release|x64 Setup.ActiveCfg = Release|x64 + {5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F}.Release|x86 Setup.ActiveCfg = Release|Win32 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.All|Win32.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.All|x64.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.All|x64 Setup.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.All|x86 Setup.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|Win32.ActiveCfg = Debug|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|x64.ActiveCfg = Debug|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|x64 Setup.ActiveCfg = Debug|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|x64 Setup.Build.0 = Debug|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|x86 Setup.ActiveCfg = Debug|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Debug|x86 Setup.Build.0 = Debug|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|Win32.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x64.ActiveCfg = Release|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x64 Setup.ActiveCfg = Release|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x64 Setup.Build.0 = Release|x64 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.ActiveCfg = Release|x86 + {47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Makefile.am b/Makefile.am index b11e3ff988..944511dac9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -267,7 +267,7 @@ src/include/switch_swigable_cpp.h: $(switch_srcdir)/src/include/switch_cpp.h ## ## Applications ## -bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav +bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode ## ## fs_cli () @@ -281,6 +281,14 @@ fs_cli_CFLAGS += -DHAVE_EDITLINE -I$(switch_srcdir)/libs/libedit/src fs_cli_LDADD = libs/libedit/src/.libs/libedit.a endif +## +## fs_encode () +## +fs_encode_SOURCES = src/fs_encode.c +fs_encode_CFLAGS = $(AM_CFLAGS) +fs_encode_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) +fs_encode_LDADD = libfreeswitch.la + ## ## tone2wav () ## diff --git a/bootstrap.sh b/bootstrap.sh index 4e65c5ca15..2dd76c409c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -148,7 +148,7 @@ if [ "x$libtoolize" = "x" ]; then exit 1 fi if [ ! -x "$libtoolize" ]; then - echo "$libtoolize does not exist or ist not executable" + echo "$libtoolize does not exist or is not executable" exit 1 fi diff --git a/build/modules.conf.in b/build/modules.conf.in index 35ec1bb8a3..87b4718bd4 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -105,5 +105,5 @@ say/mod_say_ru #say/mod_say_th ## Experimental Modules (don't cry if they're broken) -#../../contrib/mod/endpoints/mod_khomp +#endpoints/mod_khomp #../../contrib/mod/xml_int/mod_xml_odbc diff --git a/conf/autoload_configs/callcenter.conf.xml b/conf/autoload_configs/callcenter.conf.xml index 9140193b22..a069413ac6 100644 --- a/conf/autoload_configs/callcenter.conf.xml +++ b/conf/autoload_configs/callcenter.conf.xml @@ -13,6 +13,7 @@ + diff --git a/conf/autoload_configs/erlang_event.conf.xml b/conf/autoload_configs/erlang_event.conf.xml index ec14e21a25..62deb84f67 100644 --- a/conf/autoload_configs/erlang_event.conf.xml +++ b/conf/autoload_configs/erlang_event.conf.xml @@ -2,7 +2,16 @@ + + + + + diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 37e1b2f891..f5627fe965 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -1,15 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/conf/autoload_configs/switch.conf.xml b/conf/autoload_configs/switch.conf.xml index e861b1b61a..896dd0e712 100644 --- a/conf/autoload_configs/switch.conf.xml +++ b/conf/autoload_configs/switch.conf.xml @@ -86,6 +86,7 @@ + diff --git a/conf/autoload_configs/voicemail.conf.xml b/conf/autoload_configs/voicemail.conf.xml index 14ad98b41c..06bd6f6dca 100644 --- a/conf/autoload_configs/voicemail.conf.xml +++ b/conf/autoload_configs/voicemail.conf.xml @@ -33,9 +33,10 @@ - - - + --> + + + diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 8bdcfa0da2..42a3bcc31f 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -95,7 +95,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -260,6 +260,8 @@ + + diff --git a/debian/READ_BEFORE_CHANGING_ANYTHING_IN_HERE b/debian/READ_BEFORE_CHANGING_ANYTHING_IN_HERE new file mode 100644 index 0000000000..17480db19e --- /dev/null +++ b/debian/READ_BEFORE_CHANGING_ANYTHING_IN_HERE @@ -0,0 +1,29 @@ +Please do not change the maintainer (as found in the control file). + +Please DO send me a note before changing anything here. Also, PLEASE DO MAKE A +JIRA FIRST !!!! + +This request is the result of far too many sleepless nights and far too many +people breaking this far too often. So, HANDS OFF FOR NOW !!!! + +Again, to be perfectly clear: +1. Do not make any changes before verifying that they are OK with the current +maintainer (yes, that is me*). + +2. Before the mere idea of making a change crosses your mind, create a ticket in +Jira and assign it to the current maintainer. + +3. As current maintainer, I have other obligations besides fixing things people +break in the Debian build. So, please be patient; it can sometimes take a +bit for me to respond. + +4. Creating and maintaining this packages has been a lot of work. Please help +me maintain it by not fixing it to death. + +5. The maintainer is always right. + +6. If you believe the maintainer is wrong, please see item #5. + + + +* Michal Bielicki diff --git a/debian/changelog b/debian/changelog index 7f4e8d7749..8065d932e3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,53 @@ +freeswitch (1.0.head~git.master.20101015.1-1) unstable; urgency=low + + * reintroduced mod_flite + * disabled the patching stuff introduced by Julien ... needs an overwork + * reintroduced mod_tts_commandline + * cleaned up rules file and module make rules + * more trivial changes and updates :) + + -- Michal Bielicki Fri, 15 Oct 2010 13:14:02 +0200 + +freeswitch (1.0.head~git.master.20101014.1-1) unstable; urgency=low + + * replaced mod_openzap with mod_freetdm + * added mod_theora + * added mod_codec2 + * added mod_amrwb + * added mod_portaudio_stream + * cleaned up rules file and module make rules + * added patches from Julien Duqene (FS-369) + * Various trivial changes and updates :) + + -- Michal Bielicki Fri, 15 Oct 2010 05:05:02 +0200 + +freeswitch (1.0.head~git.master.20100601.2-1) unstable; urgency=low + + * Various trivial changes and updates. + * Change upstream package version numbering scheme for unreleased versions: + new format is major.minor.micro~git.branch.date.commits-1 + * Change source format to 3.0 (quilt). + * Upgrade debhelper compatibility to version 7. + * Update maintainer data and copyright file; now includes the full text + of the MPL since it is not (yet?) available in /usr/share/common-licenses/ + + * Build and install mod_file_string.so (FSBUILD-247) + * Work around build failure caused by clean rules for openzap. + + * Remove several libraries from explicit dependencies, there were no special + version requirements and they should be picked up by dh_shlibdeps. + * Add dh_makeshlibs and make dh_shlibsdeps work again. + * Move openssl to Suggests: as it is not a required package to install or + run freeswitch. + + * Add upstream-convert rule to apply patches, generate orig tarball + and set package version. + * Add check to ensure debian patches are applied before attempting build. + * Fix clean rule to avoid unwanted tree change before building orig.tar + archives with git-buildpackage. + + -- Julien Plissonneau Duquene Tue, 01 Jun 2010 09:53:44 -0400 + freeswitch (1.0.6-1ubuntu1) maverick; urgency=low [ Gabriel Gunderson ] @@ -15,7 +65,7 @@ freeswitch (1.0.4-1ubuntu2) karmic; urgency=low * upgrade: Add more verbosity when building to make it easier to find build errors. * upgrade: Remove the requirement for EXACTLY automake1.9 and change it to - need atleast automake 1.9 + need at least automake 1.9 * upgrade: Add the modules (directory, cluechoo, and valet_parking) to the build files. These are in the standard build, so they should be here too. @@ -574,7 +624,7 @@ freeswitch (1.0.1-1) unstable; urgency=low * ADD: reboot option for sip phones to flush_inboud_reg sofia profile api command * FIX: add small padding to end of mp3 to avoid cut off mp3 recording * FIX: patch multiple SDP connection lines in sdp for proxy media mode (MODENDP-109) - * FIX: don't parse ringback varable in proxy situations + * FIX: don't parse ringback variable in proxy situations * ADD: per call vm recording ext with vm_message_ext variable * ADD: sip_bye_h prefix to add headers to bye * ENHANCEMENT: more interfaces available in show fsapi command @@ -596,7 +646,7 @@ freeswitch (1.0.1~trunk) unstable; urgency=low - Added mod_say_es and mod_say_nl - Updated descriptions - Added mod_cdr_csv - * Fixed typos and some errors in the previus patch. + * Fixed typos and some errors in the previous patch. * Modified monit script. Now it should work. * The debian build system now bootstrap automagically if it's necessary and all scripts are in place. diff --git a/debian/compat b/debian/compat index b8626c4cff..7f8f011eb7 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -4 +7 diff --git a/debian/control b/debian/control index 92b4e6ada5..f5068bffe5 100644 --- a/debian/control +++ b/debian/control @@ -2,18 +2,22 @@ Source: freeswitch Section: comm Priority: extra Maintainer: FreeSWITCH developers -Uploaders: Michal Bielicki , Gabriel Gunderson , William King , Mathieu Parent -Build-Depends: debhelper (>= 5), fakeroot, wget, automake (>=1.9), autoconf, libtool, unixodbc-dev, libasound2-dev, libcurl3-openssl-dev|libcurl4-openssl-dev, libssl-dev, ncurses-dev, libogg-dev, libvorbis-dev, libperl-dev, libgdbm-dev, libdb-dev, libgnutls-dev, libtiff4-dev, python-dev, libx11-dev, uuid-dev +Uploaders: Michal Bielicki , Gabriel Gunderson , William King , Mathieu Parent +Build-Depends: debhelper (>= 7), wget, automake (>=1.9), autoconf, libtool, + unixodbc-dev, libasound2-dev, libcurl3-openssl-dev|libcurl4-openssl-dev, + libssl-dev, ncurses-dev, libogg-dev, libvorbis-dev, libperl-dev, libgdbm-dev, + libdb-dev, libgnutls-dev, libtiff4-dev, python-dev, libx11-dev, uuid-dev Homepage: http://freeswitch.org/ Standards-Version: 3.9.1 -Vcs-Svn: http://svn.freeswitch.org/svn/freeswitch/trunk/ -Vcs-Browser: http://fisheye.freeswitch.org/browse/FreeSWITCH +Vcs-Git: git://git.freeswitch.org/freeswitch.git +Vcs-Browser: http://fisheye.freeswitch.org/browse/freeswitch.git Package: freeswitch Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, adduser, unixodbc, libasound2, libcurl3, openssl, libncurses5, libvorbis0a, libuuid1 +Depends: ${shlibs:Depends}, ${misc:Depends} Recommends: freeswitch-lang-en -Suggests: freeswitch-spidermonkey, freeswitch-lua, freeswitch-perl, freeswitch-sounds-music-8000, monit +Suggests: freeswitch-spidermonkey, freeswitch-lua, freeswitch-perl, + freeswitch-sounds-music-8000, monit, openssl Description: open source telephony platform FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a @@ -48,8 +52,8 @@ Description: development libraries and header files for FreeSWITCH gateway or a media server to host IVR applications using simple scripts or XML to control the callflow. . - This package contains the include files used if you wish to compile a package which requires FreeSWITCH's - source file headers. + This package contains the include files used if you wish to compile a package + which require FreeSWITCH's source file headers. Package: freeswitch-spidermonkey Architecture: any @@ -123,6 +127,19 @@ Description: pass through AMR codec support for FreeSWITCH . This package contains the mod_amr codec module. +Package: freeswitch-codec-passthru-amrwb +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, freeswitch +Description: pass through AMRWB codec support for FreeSWITCH + FreeSWITCH is an open source telephony platform designed to facilitate the + creation of voice and chat driven products scaling from a soft-phone up to a + soft-switch. It can be used as a simple switching engine, a PBX, a media + gateway or a media server to host IVR applications using simple scripts or XML + to control the callflow. + . + This package contains the mod_amrwb codec module. + + Package: freeswitch-codec-passthru-g729 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, freeswitch @@ -139,7 +156,8 @@ Package: freeswitch-lang-en Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, freeswitch Recommends: freeswitch-sounds-en-us-callie-8000 -Suggests: freeswitch-sounds-en-us-callie-16000, freeswitch-sounds-en-us-callie-32000, freeswitch-sounds-en-us-callie-48000 +Suggests: freeswitch-sounds-en-us-callie-16000, freeswitch-sounds-en-us-callie-32000, + freeswitch-sounds-en-us-callie-48000 Description: English language files for FreeSWITCH FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a @@ -219,7 +237,8 @@ Package: freeswitch-lang-ru Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, freeswitch Recommends: freeswitch-sounds-ru-ru-elena-8000 -Suggests: freeswitch-sounds-ru-ru-elena-16000, freeswitch-sounds-ru-ru-elena-32000, freeswitch-sounds-ru-ru-elena-48000 +Suggests: freeswitch-sounds-ru-ru-elena-16000, freeswitch-sounds-ru-ru-elena-32000, + freeswitch-sounds-ru-ru-elena-48000 Description: Russian language files for FreeSWITCH FreeSWITCH is an open source telephony platform designed to facilitate the creation of voice and chat driven products scaling from a soft-phone up to a @@ -229,3 +248,18 @@ Description: Russian language files for FreeSWITCH . This package contains the mod_say_ru module and available language configuration files. + +Package: freeswitch-freetdm +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, freeswitch +Description: FreeTDM is a signaling and board API abstraction used mainly by the + FreeSWITCH project to place calls in TDM and analog telephony circuits. The library + was previously named "OpenZAP". Sangoma has worked along with the FreeSWITCH + developers in this library so Sangoma's customers can also use it to do custom + development. The library is still under heavy development but the overall API + does not change often. The intention of the library is to present a consistent + API for different telephony signaling stacks and board I/O APIs. FreeTDM can + either be used as a standalone API or along with FreeSWITCH as an endpoint + (mod_freetdm). If you want to use it as a part of FreeSWITCH remember following + the FreeSWITCH configuration section. + This package contains all the freetdm modules and libs and submodules diff --git a/debian/copyright b/debian/copyright index 45eb67b0c9..f95b7df2e0 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,51 +1,538 @@ This package was debianized by Michal Bielicki - on Now 25, 2007. - -The current Debian maintainer is Nicholas Amorim + on Nov 25, 2007. The source was downloaded from http://www.freewitch.org/ -Upstream authors: -Anthony Minessale II -Portions created by the Initial Developer are Copyright (C) 2006-2009 -the Initial Developer. All Rights Reserved. +Upstream maintainers: + Current: Michal Bielicki + Past: Nicholas Amorim +See changelog.Debian.gz for a full list of contributors. -The PRIMARY AUTHORS are (and/or have been): +The Initial Developer of the Original Code is +Anthony Minessale II +Portions created by the Initial Developer are Copyright (C) + the Initial Developer. All Rights Reserved. - Anthony Minessale II - Primary developer of all core components - and many of the included modules. Much of freeswitch is based on his work. - - Michael Jerris - Windows porter and responsible for the - windows\msvc build system. + The PRIMARY AUTHORS are (and/or have been): + + Anthony Minessale II - Primary developer of all core + components and many of the included modules. Much of freeswitch is based + on his work. + + Michael Jerris - Windows porter and responsible for the + windows\msvc build system. And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS -- people who have submitted patches, reported bugs, and generally made Freeswitch that much better: - Brian K. West - For countless hours of work on BSD and Mac support, finding countless bugs, and moral support. Xcode project files. - Joshua Colp - For his help making mod_exosip possible (which we are now getting rid of but oh well), - and for just being a swell guy! (until he backstabbed us, c'est la vie) - Michal "cypromis" Bielicki (michal.bielicki AT voiceworks.pl) - Solaris porting, and autotools enhancements, debian, rpm and solaris packaging. - James Martelletti - All around cool guy (mod_syslog) - Johny Kadarisman - Yossi Neiman of Cartis Solutions, Inc. - implementation of mod_cdr (perldd, mysql, csv) - Stefan Knoblich - Various patches and support. Thanks. - Justin Unger - Lots of help with patches and SIP testing. Thanks! - Paul D. Tinsley - Various patches and support. - Ken Rice - - xmlcdr, sofia improvements, load testing. - Neal Horman - conference improvements, switch_ivr menu additions and other tweaks. - Johny Kadarisman - mod_python fixups. - Michael Murdock - testing, documentation, bug finding and usability enhancements. - Matt Klein - Jonas Gauffin - Bugfixes and additions in mod_spidermonkey_odbc - Damjan Jovanovic - mod_java + Brian K. West - For countless hours of work on BSD and Mac support, finding + countless bugs, and moral support. Xcode project files. + Joshua Colp - For his help making mod_exosip possible (which we are now + getting rid of but oh well), and for just being a swell guy! + Michal "cypromis" Bielicki (michal.bielicki AT voiceworks.pl) - Solaris + porting, and autotools enhancements, debian, rpm and solaris packaging. + James Martelletti - All around cool guy (mod_syslog) + Johny Kadarisman + Yossi Neiman of Cartis Solutions, Inc. - + implementation of mod_cdr (perldd, mysql, csv) + Stefan Knoblich - Sofia TLS, various patches and support. Thanks. + Justin Unger - Lots of help with patches and + SIP testing. Thanks! + Paul D. Tinsley - Various patches and support. + Ken Rice - - xmlcdr, sofia improvements, load + testing, 1 liners here and there. + Neal Horman - conference improvements, switch_ivr + menu additions and other tweaks. + Johny Kadarisman - mod_python fixups. + Michael Murdock - testing, documentation, bug + finding and usability enhancements. + Matt Klein + Jonas Gauffin - mod_cdr_odbc, + mod_spidermonkey_socket, Bugfixes and additions in mod_spidermonkey_odbc and + mod_spidermonkey, .net event socket library. + Damjan Jovanovic - mod_java + Juan Jose Comellas - Patch to switch_utils for arg + parsing. + Dale Thatcher - Additions to + mod_conference. + Simon Perreault & Marc Blanchet from Viagenie.ca - IPv6 Support. A big THANK YOU goes to: -Justin Cassidy - Build related cleanups and automatic build setup. -Bret McDanel - Javascript Documentation, constant feedback and input, many other things I am sure I am forgetting. + Justin Cassidy - Build related cleanups and automatic build setup. + Bret McDanel - Javascript Documentation, constant feedback and input, many + other things I am sure I am forgetting. + + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + -You are free to distribute this software under the terms of -the MPL Mozilla Public License. On Debian systems, the complete -text of the GNU General Public License can be found in the file -'/usr/share/common-licenses/MPL'. diff --git a/debian/freeswitch-codec-passthru-amrwb.install b/debian/freeswitch-codec-passthru-amrwb.install new file mode 100644 index 0000000000..022462d001 --- /dev/null +++ b/debian/freeswitch-codec-passthru-amrwb.install @@ -0,0 +1 @@ +opt/freeswitch/mod/mod_amrwb.so* diff --git a/debian/freeswitch-freetdm.conffiles b/debian/freeswitch-freetdm.conffiles new file mode 100644 index 0000000000..f14e37f3db --- /dev/null +++ b/debian/freeswitch-freetdm.conffiles @@ -0,0 +1,6 @@ +opt/freeswitch/conf/tones.conf +opt/freeswitch/conf/autoload_configs/freetdm.conf.xml +opt/freeswitch/conf/pika.conf +opt/freeswitch/conf/freetdm.conf +opt/freeswitch/conf/wanpipe.conf +opt/freeswitch/conf/zt.conf diff --git a/debian/freeswitch-freetdm.install b/debian/freeswitch-freetdm.install new file mode 100644 index 0000000000..cdca887dd3 --- /dev/null +++ b/debian/freeswitch-freetdm.install @@ -0,0 +1,10 @@ +opt/freeswitch/conf/tones.conf +opt/freeswitch/conf/autoload_configs/freetdm.conf.xml +opt/freeswitch/conf/pika.conf +opt/freeswitch/conf/freetdm.conf +opt/freeswitch/conf/wanpipe.conf +opt/freeswitch/conf/zt.conf +opt/freeswitch/lib/libfreetdm.so* +opt/freeswitch/mod/mod_freetdm.so* +opt/freeswitch/mod/ftm*.so* + diff --git a/debian/freeswitch-python.config b/debian/freeswitch-python.config new file mode 100644 index 0000000000..1c1746c875 --- /dev/null +++ b/debian/freeswitch-python.config @@ -0,0 +1 @@ +opt/freeswitch/conf/autoload_configs/python.conf.xml diff --git a/debian/freeswitch-python.install b/debian/freeswitch-python.install new file mode 100644 index 0000000000..2773f0c780 --- /dev/null +++ b/debian/freeswitch-python.install @@ -0,0 +1,3 @@ +opt/freeswitch/conf/autoload_configs/python.conf.xml +opt/freeswitch/mod/mod_python.so* +usr/lib/python2.*/*-packages/freeswitch.py* diff --git a/debian/freeswitch.conffiles b/debian/freeswitch.conffiles index a6f9ce380f..20da33de15 100644 --- a/debian/freeswitch.conffiles +++ b/debian/freeswitch.conffiles @@ -83,10 +83,8 @@ /opt/freeswitch/conf/ivr_menus/demo_ivr.xml /opt/freeswitch/conf/jingle_profiles/client.xml /opt/freeswitch/conf/jingle_profiles/server.xml -/opt/freeswitch/conf/m3ua.conf /opt/freeswitch/conf/mime.types /opt/freeswitch/conf/notify-voicemail.tpl -/opt/freeswitch/conf/pika.conf /opt/freeswitch/conf/sip_profiles/external/example.xml /opt/freeswitch/conf/sip_profiles/external.xml /opt/freeswitch/conf/sip_profiles/internal/example.xml @@ -94,8 +92,6 @@ /opt/freeswitch/conf/sip_profiles/internal.xml /opt/freeswitch/conf/skinny_profiles/internal.xml /opt/freeswitch/conf/tetris.ttml -/opt/freeswitch/conf/tones.conf /opt/freeswitch/conf/vars.xml /opt/freeswitch/conf/voicemail.tpl /opt/freeswitch/conf/web-vm.tpl -/opt/freeswitch/conf/zt.conf diff --git a/debian/freeswitch.init b/debian/freeswitch.init index 36129cbe90..1eb71ac6d6 100755 --- a/debian/freeswitch.init +++ b/debian/freeswitch.init @@ -5,7 +5,7 @@ # Required-Stop: $network $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: The FreeSwitch Voice Switching System +# Short-Description: The FreeSWITCH Voice Switching System # Description: An advanced platform for voice services ### END INIT INFO @@ -16,7 +16,7 @@ # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin:/opt/freeswitch/bin -DESC="FreeSwitch Voice Switching System" +DESC="FreeSWITCH Voice Switching System" NAME=freeswitch DAEMON=/opt/freeswitch/bin/$NAME USER=freeswitch diff --git a/debian/freeswitch.install b/debian/freeswitch.install index 087d167859..3c838cde94 100644 --- a/debian/freeswitch.install +++ b/debian/freeswitch.install @@ -1,9 +1,9 @@ opt/freeswitch/bin/freeswitch opt/freeswitch/bin/fs_cli +opt/freeswitch/bin/fs_encode opt/freeswitch/bin/fs_ivrd opt/freeswitch/bin/fsxs opt/freeswitch/bin/gentls_cert -opt/freeswitch/bin/scripts/* opt/freeswitch/conf/autoload_configs/acl.conf.xml opt/freeswitch/conf/autoload_configs/alsa.conf.xml opt/freeswitch/conf/autoload_configs/callcenter.conf.xml @@ -31,7 +31,6 @@ opt/freeswitch/conf/autoload_configs/memcache.conf.xml opt/freeswitch/conf/autoload_configs/modules.conf.xml opt/freeswitch/conf/autoload_configs/nibblebill.conf.xml opt/freeswitch/conf/autoload_configs/opal.conf.xml -opt/freeswitch/conf/autoload_configs/openzap.conf.xml opt/freeswitch/conf/autoload_configs/pocketsphinx.conf.xml opt/freeswitch/conf/autoload_configs/portaudio.conf.xml opt/freeswitch/conf/autoload_configs/post_load_modules.conf.xml @@ -91,11 +90,8 @@ opt/freeswitch/conf/fur_elise.ttml opt/freeswitch/conf/ivr_menus/demo_ivr.xml opt/freeswitch/conf/jingle_profiles/client.xml opt/freeswitch/conf/jingle_profiles/server.xml -opt/freeswitch/conf/m3ua.conf opt/freeswitch/conf/mime.types opt/freeswitch/conf/notify-voicemail.tpl -opt/freeswitch/conf/openzap.conf -opt/freeswitch/conf/pika.conf opt/freeswitch/conf/sip_profiles/external/example.xml opt/freeswitch/conf/sip_profiles/external.xml opt/freeswitch/conf/sip_profiles/internal/example.xml @@ -103,69 +99,71 @@ opt/freeswitch/conf/sip_profiles/internal-ipv6.xml opt/freeswitch/conf/sip_profiles/internal.xml opt/freeswitch/conf/skinny_profiles/internal.xml opt/freeswitch/conf/tetris.ttml -opt/freeswitch/conf/tones.conf opt/freeswitch/conf/vars.xml opt/freeswitch/conf/voicemail.tpl -opt/freeswitch/conf/wanpipe.conf opt/freeswitch/conf/web-vm.tpl -opt/freeswitch/conf/zt.conf opt/freeswitch/htdocs/* opt/freeswitch/lib/libfreeswitch*.so* -opt/freeswitch/lib/libopenzap*.so* +opt/freeswitch/mod/mod_avmd.so* +opt/freeswitch/mod/mod_bv.so* opt/freeswitch/mod/mod_callcenter.so* opt/freeswitch/mod/mod_cdr_csv.so* opt/freeswitch/mod/mod_celt.so* opt/freeswitch/mod/mod_cidlookup.so* opt/freeswitch/mod/mod_cluechoo.so* +opt/freeswitch/mod/mod_console.so* +opt/freeswitch/mod/mod_codec2.so* opt/freeswitch/mod/mod_commands.so* opt/freeswitch/mod/mod_conference.so* opt/freeswitch/mod/mod_console.so* opt/freeswitch/mod/mod_curl.so* +opt/freeswitch/mod/mod_db.so* opt/freeswitch/mod/mod_dialplan*.so* opt/freeswitch/mod/mod_dingaling.so* opt/freeswitch/mod/mod_directory.so* +opt/freeswitch/mod/mod_distributor.so* opt/freeswitch/mod/mod_dptools.so* opt/freeswitch/mod/mod_easyroute.so* opt/freeswitch/mod/mod_enum.so* opt/freeswitch/mod/mod_esf.so* opt/freeswitch/mod/mod_event_*.so* opt/freeswitch/mod/mod_expr.so* -opt/freeswitch/mod/mod_spandsp.so* opt/freeswitch/mod/mod_fifo.so* +opt/freeswitch/mod/mod_file_string.so* +opt/freeswitch/mod/mod_flite.so* opt/freeswitch/mod/mod_fsv.so* +opt/freeswitch/mod/mod_hash.so* opt/freeswitch/mod/mod_h26x.so* opt/freeswitch/mod/mod_ilbc.so* opt/freeswitch/mod/mod_lcr.so* -opt/freeswitch/mod/mod_db.so* -opt/freeswitch/mod/mod_hash.so* +opt/freeswitch/mod/mod_limit.so* opt/freeswitch/mod/mod_local_stream.so* opt/freeswitch/mod/mod_logfile.so* opt/freeswitch/mod/mod_loopback.so* +opt/freeswitch/mod/mod_memcache.so* +opt/freeswitch/mod/mod_mp4v.so* opt/freeswitch/mod/mod_native_file.so* opt/freeswitch/mod/mod_nibblebill.so* -opt/freeswitch/mod/mod_openzap.so opt/freeswitch/mod/mod_portaudio.so* +opt/freeswitch/mod/mod_portaudio_stream.so* +opt/freeswitch/mod/mod_redis.so* opt/freeswitch/mod/mod_rss.so* opt/freeswitch/mod/mod_shout.so* +opt/freeswitch/mod/mod_silk.so* opt/freeswitch/mod/mod_siren.so* opt/freeswitch/mod/mod_skinny.so* opt/freeswitch/mod/mod_skypopen.so* opt/freeswitch/mod/mod_sndfile.so* opt/freeswitch/mod/mod_snom.so* opt/freeswitch/mod/mod_sofia.so* +opt/freeswitch/mod/mod_spandsp.so* opt/freeswitch/mod/mod_speex.so* opt/freeswitch/mod/mod_spy.so* opt/freeswitch/mod/mod_syslog.so* +opt/freeswitch/mod/mod_theora.so* opt/freeswitch/mod/mod_tone_stream.so* opt/freeswitch/mod/mod_tts_commandline.so* opt/freeswitch/mod/mod_valet_parking.so* opt/freeswitch/mod/mod_vmd.so* opt/freeswitch/mod/mod_voicemail.so* opt/freeswitch/mod/mod_xml_*.so* -opt/freeswitch/mod/ozmod_analog_em.so* -opt/freeswitch/mod/ozmod_analog.so* -opt/freeswitch/mod/ozmod_isdn.so* -opt/freeswitch/mod/ozmod_skel.so* -opt/freeswitch/mod/ozmod_ss7_boost.so* -opt/freeswitch/mod/ozmod_wanpipe.so* -opt/freeswitch/mod/ozmod_zt.so* diff --git a/debian/postinst b/debian/postinst index 31a2536d4e..696171eb5a 100755 --- a/debian/postinst +++ b/debian/postinst @@ -24,9 +24,16 @@ case "$1" in if ! getent passwd freeswitch >/dev/null; then adduser --disabled-password --quiet --system \ --home /opt/freeswitch \ - --gecos "FreeSwitch Voice Platform" --ingroup daemon \ + --gecos "FreeSWITCH Voice Platform" --ingroup daemon \ freeswitch adduser freeswitch audio + else + if [ "$(getent passwd freeswitch | cut -d : -f 6)" != "/opt/freeswitch" ]; then + echo "Error: pre-existing freeswitch user with non-standard home directory." >&2 + exit 1 + fi + usermod -d /opt/freeswitch -c "FreeSWITCH daemon,,," \ + -g daemon -G audio freeswitch fi mkdir -p /opt/freeswitch diff --git a/debian/postrm b/debian/postrm index 9dbbeb0246..97718dfacd 100755 --- a/debian/postrm +++ b/debian/postrm @@ -1,5 +1,5 @@ #!/bin/sh -# postrm script for openfire +# postrm script for freeswitch # # see: dh_installdeb(1) diff --git a/debian/rules b/debian/rules index 114ad64f34..94aee73a00 100755 --- a/debian/rules +++ b/debian/rules @@ -1,40 +1,40 @@ #!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# This file is public domain software, originally written by Joey Hess. # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 export DH_OPTIONS export DEB_DH_INSTALL_SOURCEDIR=debian/tmp -export PASSTHRU_CODEC_MODULES=codecs/mod_g729 codecs/mod_g723_1 codecs/mod_amr +export PASSTHRU_CODEC_MODULES=codecs/mod_g729 codecs/mod_g723_1 codecs/mod_amr codecs/mod_amrwb # Modules listed by those built by default, then those that are added in this package -export APPLICATIONS_MODULES=applications/mod_cluechoo applications/mod_commands applications/mod_conference applications/mod_dptools \ - applications/mod_enum applications/mod_esf applications/mod_expr applications/mod_fifo applications/mod_fsv \ - applications/mod_hash applications/mod_db applications/mod_valet_parking applications/mod_voicemail applications/mod_rss \ - applications/mod_spandsp applications/mod_cidlookup applications/mod_curl applications/mod_easyroute \ - applications/mod_lcr applications/mod_nibblebill applications/mod_snom \ - applications/mod_spy applications/mod_vmd applications/mod_directory applications/mod_callcenter -export ASR_TTS_MODULES=asr_tts/mod_tts_commandline -export CODECS_MODULES=codecs/mod_ilbc codecs/mod_h26x codecs/mod_speex codecs/mod_siren codecs/mod_celt -export DIALPLANS_MODULES=dialplans/mod_dialplan_asterisk dialplans/mod_dialplan_directory dialplans/mod_dialplan_xml -export DIRECTORIES_MODULES= -export DOTNET_MODULES= -export ENDPOINTS_MODULES=endpoints/mod_dingaling endpoints/mod_portaudio endpoints/mod_sofia \ - endpoints/mod_loopback ../../libs/openzap/mod_openzap endpoints/mod_skypopen \ - endpoints/mod_skinny +export APPLICATION_MODULES_AE= applications/mod_avmd applications/mod_callcenter applications/mod_cidlookup applications/mod_cluechoo \ + applications/mod_commands applications/mod_conference applications/mod_curl applications/mod_db applications/mod_directory \ + applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum \ + applications/mod_esf applications/mod_expr +export APPLICATION_MODULES_FM= applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit \ + applications/mod_memcache +export APPLICATION_MODULES_NY= applications/mod_nibblebill applications/mod_redis applications/mod_rss applications/mod_snom \ + applications/mod_spandsp applications/mod_spy applications/mod_stress \ + applications/mod_valet_parking applications/mod_vmd applications/mod_voicemail + +export APPLICATIONS_MODULES= $(APPLICATION_MODULES_AE) $(APPLICATION_MODULES_FM) $(APPLICATION_MODULES_NY) $(APPLICATION_MODULES_VZ) +export ASR_TTS_MODULES= asr_tts/mod_pocketsphinx asr_tts/mod_flite asr_tts/mod_tts_commandline +export CODECS_MODULES= codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod_celt codecs/mod_codec2 codecs/mod_ilbc codecs/mod_mp4v \ + codecs/mod_silk codecs/mod_siren codecs/mod_theora +export DIALPLANS_MODULES= dialplans/mod_dialplan_asterisk dialplans/mod_dialplan_directory dialplans/mod_dialplan_xml +export ENDPOINTS_MODULES= endpoints/mod_dingaling endpoints/mod_portaudio endpoints/mod_sofia endpoints/mod_loopback \ + ../../libs/freetdm/mod_freetdm endpoints/mod_skypopen endpoints/mod_skinny export EVENT_HANDLERS_MODULES=event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_cdr_csv -export FORMATS_MODULES=formats/mod_local_stream formats/mod_native_file formats/mod_sndfile formats/mod_tone_stream formats/mod_shout +export FORMATS_MODULES= formats/mod_file_string formats/mod_local_stream formats/mod_native_file formats/mod_portaudio_stream \ + formats/mod_shout formats/mod_sndfile formats/mod_tone_stream export LANGUAGES_MODULES=languages/mod_spidermonkey languages/mod_perl languages/mod_lua languages/mod_python export LOGGERS_MODULES=loggers/mod_console loggers/mod_logfile loggers/mod_syslog export SAY_MODULES=say/mod_say_en say/mod_say_it say/mod_say_de say/mod_say_fr say/mod_say_es say/mod_say_nl say/mod_say_ru -export TIMERS_MODULES= -export DISABLED_MODULES=applications/mod_memcache applications/mod_soundtouch directories/mod_ldap languages/mod_java \ - asr_tts/mod_cepstral asr_tts/mod_lumenvox endpoints/mod_wanpipe \ - event_handlers/mod_event_test event_handlers/mod_radius_cdr event_handlers/mod_zeroconf export XML_INT_MODULES=xml_int/mod_xml_rpc xml_int/mod_xml_curl xml_int/mod_xml_cdr -export MYMODULES=$(PASSTHRU_CODEC_MODULES) $(APPLICATIONS_MODULES) $(ASR_TTS_MODULES) $(CODECS_MODULES) $(DIALPLANS_MODULES) $(DIRECTORIES_MODULES) $(DOTNET_MODULES) $(ENDPOINTS_MODULES) $(EVENT_HANDLERS_MODULES) $(FORMATS_MODULES) $(LANGUAGES_MODULES) $(LOGGERS_MODULES) $(SAY_MODULES) $(TIMERS_MODULES) $(XML_INT_MODULES) +export MYMODULES= $(PASSTHRU_CODEC_MODULES) $(APPLICATIONS_MODULES) $(ASR_TTS_MODULES) $(CODECS_MODULES) $(DIALPLANS_MODULES) $(ENDPOINTS_MODULES) $(EVENT_HANDLERS_MODULES) $(FORMATS_MODULES) $(LANGUAGES_MODULES) $(LOGGERS_MODULES) $(SAY_MODULES) $(XML_INT_MODULES) export MODULES=$(MYMODULES) + + ifndef AUTOCONF AUTOCONFS := $(wildcard /usr/bin/autoconf*) AUTOCONF = $(shell which autoconf) @@ -57,6 +57,116 @@ ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) FEATURES += --disable-optimization endif +.pc/applied-patches: + @echo + @echo \ \ Sorry, currently this package cannot be built directly from upstream + @echo \ \ source git/tarball: patches are needed for policy compliance, and the + @echo \ \ "new 3.0 (quilt) source format requires patches to be already applied." + @echo + @echo \ \ Please first convert this tree by running: + @echo -e \\t./debian/rules upstream-convert + @echo + @echo \ \ Note that this will insert an entry in debian/changelog, rename the + @echo \ \ current directory to the version number there, create a .orig.tar.bz2 + @echo \ \ archive and apply all the patches in debian/patches/series. + @echo + @echo \ \ Using git-buildpackage is not recommended for now. + @echo + @exit 1 + +upstream-convert: + @dh_testdir + @test -s .pc/applied-patches && \ + echo "Aborted: patches are already applied." && \ + exit 1 || exit 0 + # update (or not) version number in debian/changelog + @set -e ; \ + echo Checking version number ; \ + v1="$$(dpkg-parsechangelog | sed -e '/^Version: / ! d' -e 's/^Version: //')" ; \ + v2="$${v1}" ; \ + echo " Current version: $${v1}" ; \ + if [ "$$(which git)" = "" -o ! -d .git ] ; then \ + echo Git not available. Keeping current version number. ; \ + exit 0 ; \ + fi ; \ + if [ "$$(which debchange)" = "" ] ; then \ + echo debchange not available. Keeping current version number. ; \ + exit 0 ; \ + fi ; \ + if echo -n "$${v1}" | grep -q '~git\.[a-z0-9]\+\.20[0-9]\{6\}\.[0-9]\+-[^-]\+$$' ; then \ + maj1="$$(echo -n "$${v1}" | sed -e 's/^\([^.]\+\)\..*$$/\1/')" ; \ + min1="$$(echo -n "$${v1}" | sed -e 's/^[^.]\+\.\([^.]\+\)\..*$$/\1/')" ; \ + mic1="$$(echo -n "$${v1}" | sed -e 's/^[^.]\+\.[^.]\+\.\([a-zA-Z0-9]\+\).*$$/\1/')" ; \ + b1="$$(echo -n "$${v1}" | sed -e 's/^.*~git\.\([a-z0-9]\+\)\.\(20[0-9]\{6\}\)\.[0-9]\+-[^-]\+$$/\1/')" ; \ + d1="$$(echo -n "$${v1}" | sed -e 's/^.*\.\(20[0-9]\{6\}\)\.[0-9]\+-[^-]\+$$/\1/')" ; \ + n1="$$(echo -n "$${v1}" | sed -e 's/^.*\.20[0-9]\{6\}\.\([0-9]\+\)-[^-]\+$$/\1/')" ; \ + maj2="$$(sed -e '/^AC_SUBST(SWITCH_VERSION_MAJOR/ ! d' -e 's/^.*\[\([^\[]\+\)\][^\]]*$$/\1/' configure.in)" ; \ + min2="$$(sed -e '/^AC_SUBST(SWITCH_VERSION_MINOR/ ! d' -e 's/^.*\[\([^\[]\+\)\][^\]]*$$/\1/' configure.in)" ; \ + mic2="$$(sed -e '/^AC_SUBST(SWITCH_VERSION_MICRO/ ! d' -e 's/^.*\[\([^\[]\+\)\][^\]]*$$/\1/' configure.in)" ; \ + b2="$$(git branch | sed -e '/^[^*]/ d' -e 's/* \(.*\)/\1/')" ; \ + d2="$$(TZ=UTC git log --date=local -1 --format='%ai' | sed -e 's/^\(....\).\(..\).\(..\).*$$/\1\2\3/')" ; \ + n2="$$(TZ=UTC git log --date=local --format=oneline --since="$${d2::4}-$${d2:4:2}-$${d2:6:2} 00:00" | wc -l)" ; \ + if [ "$${b2}" != "$$(echo "$${b2}" | tr -dc a-z0-9)" ] ; then \ + echo Invalid branch name "'$${b2}'". Aborted. ; \ + exit 1; \ + fi ; \ + if [ "$${b1}.$${d1}.$${n1}" != "$${b2}.$${d2}.$${n2}" \ + -o "$${maj1}.$${min1}.$${mic1}" != "$${maj2}.$${min2}.$${mic2}" ] ; then \ + v2="$$(echo -n "$${maj2}.$${min2}.$${mic2}")" ; \ + v2="$${v2}$$(echo -n "$${v1}" | sed -e 's/^[^.]\+\.[^.]\+\.[^.]\+\(.*\)~git\..*$$/\1/')" ; \ + v2="$${v2}~git.$${b2}.$${d2}.$${n2}-1" ; \ + echo " New version: $${v2}" ; \ + echo Updating debian/changelog with new version number ; \ + debchange -v "$${v2}" "New upstream release" ; \ + else \ + echo Version number already correct, no change. ; \ + fi ; \ + else \ + echo 'Not a ~git. version number. Keeping current version number.' ; \ + fi + # rename (or not) current directory to match packagename-version.number + @set -e ; \ + echo Checking directory name ; \ + d1="$$(basename "$$(cd . && echo "$$PWD")")" ; \ + d2="$$(dpkg-parsechangelog | sed -e '/^Source: / ! d' -e 's/^Source: //')" ; \ + d2="$${d2}-$$(dpkg-parsechangelog | sed -e '/^Version: / ! d' -e 's/^Version: \(.*\)-[^-]\+$$/\1/')" ; \ + if [ "$${d1}" != "$${d2}" ] ; then \ + if [ -e "../$${d2}" ] ; then \ + test . -ef "../$${d2}" && exit 0 ; \ + echo Aborted: directory "../$${d2}" already exists. ; \ + exit 1 ; \ + fi ; \ + echo Renaming current directory to "$${d2}" ; \ + mv ../$${d1} ../$${d2} ; \ + fi + # create .orig.tar.bz2 + @set -e ; \ + n="$$(dpkg-parsechangelog | sed -e '/^Source: / ! d' -e 's/^Source: //')" ; \ + d="$${n}-$$(dpkg-parsechangelog | sed -e '/^Version: / ! d' -e 's/^Version: \(.*\)-[^-]\+$$/\1/')" ; \ + n="$${n}_$$(dpkg-parsechangelog | sed -e '/^Version: / ! d' -e 's/^Version: \(.*\)-[^-]\+$$/\1/').orig.tar.bz2" ; \ + echo "Creating source archive $${n}" ; \ + cd .. && tar cjf "$${n}" --exclude='.git*' "$${d}" + # apply patches + @set -e ; \ + echo "Applying patches in debian/patches/series" ; \ + QUILT_PATCHES=debian/patches ; \ + export QUILT_PATCHES ; \ + while quilt next ; do \ + quilt push -v ; \ + quilt refresh ; \ + done + # remind user to change dir + @echo Done. + @echo + @if [ "$(CURDIR)" != "$$PWD" ] ; then \ + echo \ \ You should now tell your shell to update its current working directory: ; \ + echo -e \\t'cd $$(pwd)' ; \ + echo \ \ or ; \ + echo -e "\\tcd $$PWD" ; \ + echo ; \ + fi + + config.status: configure dh_testdir rm -f modules.conf @@ -65,15 +175,12 @@ config.status: configure for i in $(MODULES); do echo $$i >> modules.conf; done ./configure --prefix=/opt/freeswitch --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) ${FEATURES} -configure: - if test ! -f Makefile.in ; then \ - if test -f ./bootstrap.sh ; then \ - AUTOCONF=${AUTOCONF} ./bootstrap.sh ; \ - else \ - echo "No Makefile.in and no known way to bootstrap." ; \ - exit 1; \ - fi; \ - fi; +configure: bootstrap.sh # .pc/applied-patches + dh_testdir + test -e /usr/share/misc/config.sub && cp -f /usr/share/misc/config.sub build/config/config.sub + test -e /usr/share/misc/config.guess && cp -f /usr/share/misc/config.guess build/config/config.guess + AUTOCONF=${AUTOCONF} ./bootstrap.sh + build: build-stamp build-stamp: config.status @@ -83,19 +190,13 @@ build-stamp: config.status touch $@ -clean: +clean: # .pc/applied-patches dh_testdir dh_testroot rm -f build-stamp -$(MAKE) update-clean -ifneq "$(wildcard /usr/share/misc/config.sub)" "" - cp -f /usr/share/misc/config.sub build/config/config.sub -endif -ifneq "$(wildcard /usr/share/misc/config.guess)" "" - cp -f /usr/share/misc/config.guess build/config/config.guess -endif - rm -f config.status + rm -f configure config.status rm -f */*/config.status rm -f */*/*/config.status dh_clean @@ -103,8 +204,8 @@ endif install: build dh_testdir dh_testroot - dh_clean -k - dh_installdirs -A --sourcedir=debian/tmp + dh_prep + dh_installdirs -A VERBOSE=1 $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install @@ -123,11 +224,12 @@ binary-arch: build install cp debian/monit/freeswitch.monitrc debian/freeswitch/etc/monit/freeswitch.monitrc dh_install --sourcedir=debian/tmp dh_link - dh_strip --dbg-package=freeswitch + dh_strip --dbg-package=freeswitch-dbg dh_compress dh_fixperms --exclude /opt/freeswitch/conf + dh_makeshlibs + dh_shlibdeps dh_installdeb - dh_shlibdeps --exclude=/opt/freeswitch dh_gencontrol dh_md5sums dh_builddeb diff --git a/debian/sounds/freeswitch-sounds-en-us-callie/debian/changelog b/debian/sounds/freeswitch-sounds-en-us-callie/debian/changelog index adb1dfc517..9ca1d1a933 100644 --- a/debian/sounds/freeswitch-sounds-en-us-callie/debian/changelog +++ b/debian/sounds/freeswitch-sounds-en-us-callie/debian/changelog @@ -1,3 +1,12 @@ +freeswitch-sounds-en-us-callie (1.0.head-git.master,20101014.1-1) unstable; urgency=low + + * Change upstream package version numbering scheme for unreleased versions: + new format is major.minor.micro~git.branch.date.commits-1 + * Change source format to 3.0 (quilt). + * Upgrade debhelper compatibility to version 7. + + -- Michal Bielicki Fr, 14 Oct 2010 05:05:02 +0200 + freeswitch-sounds-en-us-callie (1.0.12-0ubuntu1) jaunty; urgency=low * Initial: This is the initial working build of the en-us-callie sounds diff --git a/debian/sounds/freeswitch-sounds-en-us-callie/debian/control b/debian/sounds/freeswitch-sounds-en-us-callie/debian/control index 1af616adb8..3408328ca1 100644 --- a/debian/sounds/freeswitch-sounds-en-us-callie/debian/control +++ b/debian/sounds/freeswitch-sounds-en-us-callie/debian/control @@ -2,8 +2,9 @@ Source: freeswitch-sounds-en-us-callie Maintainer: Freeswitch Debian Team Section: net Priority: extra -Build-Depends: debhelper (>= 5), fakeroot, sox -Standards-Version: 3.7.3 +Build-Depends: debhelper (>= 7), sox +Homepage: http://www.freeswitch.org/ +Standards-Version: 3.8.4 Package: freeswitch-sounds-en-us-callie-8000 Architecture: all @@ -47,14 +48,18 @@ Description: English language sounds for the FreeSWITCH(TM) (48000) Package: freeswitch-sounds-en-us-callie Architecture: all Depends: sox, freeswitch-sounds-en-us-callie-48000 -Conflicts: freeswitch-sounds-en-us-callie-omega, freeswitch-sounds-en-us-callie-8000, freeswitch-sounds-en-us-callie-16000, freeswitch-sounds-en-us-callie-32000 +Conflicts: freeswitch-sounds-en-us-callie-omega, + freeswitch-sounds-en-us-callie-8000, freeswitch-sounds-en-us-callie-16000, + freeswitch-sounds-en-us-callie-32000 Description: English language files for FreeSWITCH(TM) This package generates the 8k, 16k, and 32k from the installed 48k sounds. You can select which ones you want. Package: freeswitch-sounds-en-us-callie-omega Architecture: all -Depends: freeswitch-sounds-en-us-callie-48000, freeswitch-sounds-en-us-callie-32000, freeswitch-sounds-en-us-callie-16000, freeswitch-sounds-en-us-callie-8000 +Depends: freeswitch-sounds-en-us-callie-48000, + freeswitch-sounds-en-us-callie-32000, freeswitch-sounds-en-us-callie-16000, + freeswitch-sounds-en-us-callie-8000 Conflicts: freeswitch-sounds-en-us-callie Description: English language files for FreeSWITCH(TM) This package depends on the pregenerated 8khz, 16khz, 32khz, and 48khz sounds diff --git a/debian/sounds/freeswitch-sounds-music/debian/changelog b/debian/sounds/freeswitch-sounds-music/debian/changelog index 5f18ff3277..2d639c0691 100644 --- a/debian/sounds/freeswitch-sounds-music/debian/changelog +++ b/debian/sounds/freeswitch-sounds-music/debian/changelog @@ -1,3 +1,12 @@ +freeswitch-sounds-music (1.0.head-git.master,20101014.1-1) unstable; urgency=low + + * Change upstream package version numbering scheme for unreleased versions: + new format is major.minor.micro~git.branch.date.commits-1 + * Change source format to 3.0 (quilt). + * Upgrade debhelper compatibility to version 7. + + -- Michal Bielicki Fr, 14 Oct 2010 05:05:02 +0200 + freeswitch-sounds-music (1.0.8-0ubuntu3) jaunty; urgency=low * Fixed: empty binary files for some packages diff --git a/debian/sounds/freeswitch-sounds-music/debian/control b/debian/sounds/freeswitch-sounds-music/debian/control index d03c2aa64e..20cfd5e3df 100644 --- a/debian/sounds/freeswitch-sounds-music/debian/control +++ b/debian/sounds/freeswitch-sounds-music/debian/control @@ -1,9 +1,10 @@ Source: freeswitch-sounds-music -Maintainer: Freeswitch Debian Team +Maintainer: Freeswitch development Team Section: net Priority: extra -Build-Depends: debhelper (>= 5), fakeroot, sox -Standards-Version: 3.7.3 +Build-Depends: debhelper (>= 7), sox +Homepage: http://www.freeswitch.org/ +Standards-Version: 3.8.4 Package: freeswitch-sounds-music-8000 Architecture: all @@ -47,14 +48,18 @@ Description: music for FreeSWITCH(TM) (48000) Package: freeswitch-sounds-music Architecture: all Depends: sox, freeswitch-sounds-music-48000 -Conflicts: freeswitch-sounds-music-omega, freeswitch-sounds-music-8000, freeswitch-sounds-music-16000, freeswitch-sounds-music-32000 +Conflicts: freeswitch-sounds-music-omega, + freeswitch-sounds-music-8000, freeswitch-sounds-music-16000, + freeswitch-sounds-music-32000 Description: Music for FreeSWITCH(TM) This package generates the 8k, 16k, and 32k from the installed 48k sounds. You can select which ones you want. Package: freeswitch-sounds-music-omega Architecture: all -Depends: freeswitch-sounds-music-48000, freeswitch-sounds-music-32000, freeswitch-sounds-music-16000, freeswitch-sounds-music-8000 +Depends: freeswitch-sounds-music-48000, + freeswitch-sounds-music-32000, freeswitch-sounds-music-16000, + freeswitch-sounds-music-8000 Conflicts: freeswitch-sounds-music Description: Music for FreeSWITCH(TM) This package depends on the pregenerated 8khz, 16khz, 32khz, and 48khz sounds diff --git a/debian/sounds/freeswitch-sounds-ru-RU-elena/debian/changelog b/debian/sounds/freeswitch-sounds-ru-RU-elena/debian/changelog index b7de59226e..38cc529ef6 100644 --- a/debian/sounds/freeswitch-sounds-ru-RU-elena/debian/changelog +++ b/debian/sounds/freeswitch-sounds-ru-RU-elena/debian/changelog @@ -1,3 +1,12 @@ +freeswitch-sounds-ru-ru-elena (1.0.head-git.master,20101014.1-1) unstable; urgency=low + + * Change upstream package version numbering scheme for unreleased versions: + new format is major.minor.micro~git.branch.date.commits-1 + * Change source format to 3.0 (quilt). + * Upgrade debhelper compatibility to version 7. + + -- Michal Bielicki Fr, 14 Oct 2010 05:05:02 +0200 + freeswitch-sounds-ru-ru-elena (1.0.12-0ubuntu3) jaunty; urgency=low * Fixed: Empty binary package bug caused by the second ru folder being diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/substvars b/debian/substvars index 62293246ae..e69de29bb2 100644 --- a/debian/substvars +++ b/debian/substvars @@ -1 +0,0 @@ -shlibs:Depends=libc6 (>= 2.3.6-6), libdb4.4, libgcc1 (>= 1:4.1.1-12), libsasl2-2, libssl0.9.8 (>= 0.9.8c-1), libstdc++6 (>= 4.1.1-12), libuuid1, zlib1g (>= 1:1.2.1) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index 318aba18dd..a028a2aae0 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -384,14 +384,14 @@ - + - + @@ -403,27 +403,30 @@ - + - + - + + + + @@ -435,7 +438,7 @@ - + diff --git a/freeswitch.spec b/freeswitch.spec index a2c975b5a9..ceacfbafb2 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -331,7 +331,7 @@ export QA_RPATHS=$[ 0x0001|0x0002 ] # ###################################################################################################################### APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_callcenter applications/mod_cidlookup applications/mod_cluechoo \ - applications/mod_commands applications/mod_conference applications/mod_db applications/mod_directory \ + applications/mod_commands applications/mod_conference applications/mod_curl applications/mod_db applications/mod_directory \ applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum \ applications/mod_esf applications/mod_expr" APPLICATION_MODULES_FM="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit \ @@ -753,6 +753,7 @@ fi %{prefix}/mod/mod_console.so* %{prefix}/mod/mod_commands.so* %{prefix}/mod/mod_conference.so* +%{prefix}/mod/mod_curl.so* %{prefix}/mod/mod_db.so* %{prefix}/mod/mod_dialplan_asterisk.so* %{prefix}/mod/mod_dialplan_directory.so* @@ -949,6 +950,8 @@ fi # ###################################################################################################################### %changelog +* Fri Oct 15 2010 - michal.bielicki@seventhsignal.de +- added mod_curl * Sat Oct 09 2010 - michal.bielicki@seventhsignal.de - added mod_silk - added mod_codec2 diff --git a/libs/esl/java/Makefile b/libs/esl/java/Makefile index a1e5f93294..9474a83276 100644 --- a/libs/esl/java/Makefile +++ b/libs/esl/java/Makefile @@ -1,4 +1,4 @@ -LOCAL_CFLAGS=-I../src/include -I/usr/java/jdk1.6.0_14/include -I/usr/java/jdk1.6.0_14/include/linux +LOCAL_CFLAGS=-I../src/include -I/usr/java/jdk1.6.0_14/include -I/usr/java/jdk1.6.0_14/include/linux -I/usr/lib/jvm/java-6-openjdk/include/ GCC_WARNING_JUNK=-w CLASSES=org/freeswitch/esl/* diff --git a/libs/freetdm/.gitignore b/libs/freetdm/.gitignore index 5018c5311b..2b06b30218 100644 --- a/libs/freetdm/.gitignore +++ b/libs/freetdm/.gitignore @@ -11,6 +11,20 @@ config.* configure libtool aclocal.m4 +build/libtool.m4 +build/ltoptions.m4 +build/ltsugar.m4 +build/ltversion.m4 +build/lt~obsolete.m4 + +testanalog +testapp +testboost +testcid +testpri +testr2 +testsangomaboost +testtones !/sample/boost/Makefile !/sample/dso/Makefile diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index d14013ab9b..bc92e1db58 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -29,29 +29,34 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -PREFIX = $(prefix) -SRC = src +ACLOCAL_AMFLAGS = -I build +AUTOMAKE_OPTIONS = foreign + +SRC = src moddir = @modinstdir@ libdir = @libdir@ -library_includedir = $(PREFIX)/include +library_includedir = $(prefix)/include -INCS = -I$(FT_SRCDIR)/$(SRC)/include -I$(FT_SRCDIR)/$(SRC)/isdn/include -I$(FT_SRCDIR)/$(SRC)/include/private -INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost -if SNGSS7 -INCS += -I/usr/include/sng_ss7/ -endif -if SNGISDN -INCS += -I/usr/include/sng_isdn/ +INCS = -I$(FT_SRCDIR)/$(SRC)/include -I$(FT_SRCDIR)/$(SRC)/include/private +INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost + +if HAVE_SNG_SS7 +INCS += -I/usr/include/sng_ss7 endif -MY_CFLAGS = $(INCS) $(FTDM_CFLAGS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@ -COMPILE = $(CC) $(MY_CFLAGS) $(INCS) +if HAVE_SNG_ISDN +INCS += -I/usr/include/sng_isdn +endif + +FTDM_COMPAT_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_COMPAT_CFLAGS@ @DEFS@ +FTDM_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@ +COMPILE = $(CC) $(FTDM_CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(COMPILE) -LINK = $(LIBTOOL) --mode=link --tag=CC $(CC) $(MY_CFLAGS) $(LDFLAGS) -o $@ +LINK = $(LIBTOOL) --mode=link --tag=CC $(CC) $(FTDM_CFLAGS) $(LDFLAGS) -o $@ -if DEBUGDTMF -MY_CFLAGS += -DFTDM_DEBUG_DTMF +if WANT_DEBUGDTMF +FTDM_CFLAGS += -DFTDM_DEBUG_DTMF endif @@ -68,265 +73,226 @@ pkgconfig_DATA = freetdm.pc # libfreetdm # libfreetdm_la_SOURCES = \ -$(SRC)/hashtable.c \ -$(SRC)/hashtable_itr.c \ -$(SRC)/ftdm_io.c \ -$(SRC)/ftdm_queue.c \ -$(SRC)/ftdm_sched.c \ -$(SRC)/ftdm_call_utils.c \ -$(SRC)/ftdm_config.c \ -$(SRC)/ftdm_callerid.c \ -$(SRC)/fsk.c \ -$(SRC)/uart.c \ -$(SRC)/g711.c \ -$(SRC)/libteletone_detect.c \ -$(SRC)/libteletone_generate.c \ -$(SRC)/ftdm_buffer.c \ -$(SRC)/ftdm_threadmutex.c \ -$(SRC)/ftdm_dso.c \ -$(SRC)/ftdm_cpu_monitor.c + $(SRC)/hashtable.c \ + $(SRC)/hashtable_itr.c \ + $(SRC)/ftdm_io.c \ + $(SRC)/ftdm_queue.c \ + $(SRC)/ftdm_sched.c \ + $(SRC)/ftdm_call_utils.c \ + $(SRC)/ftdm_config.c \ + $(SRC)/ftdm_callerid.c \ + $(SRC)/fsk.c \ + $(SRC)/uart.c \ + $(SRC)/g711.c \ + $(SRC)/libteletone_detect.c \ + $(SRC)/libteletone_generate.c \ + $(SRC)/ftdm_buffer.c \ + $(SRC)/ftdm_threadmutex.c \ + $(SRC)/ftdm_dso.c \ + $(SRC)/ftdm_cpu_monitor.c library_include_HEADERS = \ -$(SRC)/include/freetdm.h \ -$(SRC)/include/ftdm_declare.h \ -$(SRC)/include/ftdm_threadmutex.h \ -$(SRC)/include/ftdm_os.h \ -$(SRC)/include/ftdm_dso.h + $(SRC)/include/freetdm.h \ + $(SRC)/include/ftdm_declare.h \ + $(SRC)/include/ftdm_threadmutex.h \ + $(SRC)/include/ftdm_os.h \ + $(SRC)/include/ftdm_dso.h lib_LTLIBRARIES = libfreetdm.la -libfreetdm_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +libfreetdm_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) libfreetdm_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS) libfreetdm_la_LIBADD = $(LIBS) -MYLIB = libfreetdm.la - core: libfreetdm.la core-install: install-libLTLIBRARIES # # tools & test programs # -noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog testapp testcid #testisdn -if HAVE_SCTP -noinst_PROGRAMS += testboost -endif +noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog testapp testcid noinst_PROGRAMS += testsangomaboost testapp_SOURCES = $(SRC)/testapp.c testapp_LDADD = libfreetdm.la -testapp_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testapp_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) testcid_SOURCES = $(SRC)/testcid.c testcid_LDADD = libfreetdm.la -testcid_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testcid_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) testtones_SOURCES = $(SRC)/testtones.c testtones_LDADD = libfreetdm.la -testtones_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testtones_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) detect_tones_SOURCES = $(SRC)/detect_tones.c detect_tones_LDADD = libfreetdm.la -detect_tones_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +detect_tones_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) detect_dtmf_SOURCES = $(SRC)/detect_dtmf.c detect_dtmf_LDADD = libfreetdm.la -detect_dtmf_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +detect_dtmf_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) #testisdn_SOURCES = $(SRC)/testisdn.c #testisdn_LDADD = libfreetdm.la -#testisdn_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +#testisdn_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) testpri_SOURCES = $(SRC)/testpri.c testpri_LDADD = libfreetdm.la -testpri_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testpri_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) testr2_SOURCES = $(SRC)/testr2.c testr2_LDADD = libfreetdm.la -testr2_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testr2_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) if HAVE_SCTP +noinst_PROGRAMS += testboost testboost_SOURCES = $(SRC)/testboost.c testboost_LDADD = libfreetdm.la -testboost_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testboost_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) endif testsangomaboost_SOURCES = $(SRC)/testsangomaboost.c testsangomaboost_LDADD = libfreetdm.la -testsangomaboost_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testsangomaboost_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) testanalog_SOURCES = $(SRC)/testanalog.c testanalog_LDADD = libfreetdm.la -testanalog_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +testanalog_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) # # ftmod modules # -mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_analog.la ftmod_analog_em.la #ftmod_isdn.la - - -if HAVE_SCTP -mod_LTLIBRARIES += ftmod_sangoma_boost.la -endif - -if LIBSANGOMA -mod_LTLIBRARIES += ftmod_wanpipe.la -endif - -if LIBPRI -mod_LTLIBRARIES += ftmod_libpri.la -endif - -if PRITAP -mod_LTLIBRARIES += ftmod_pritap.la -endif - -if SNGSS7 -mod_LTLIBRARIES += ftmod_sangoma_ss7.la -endif - -if SNGISDN -mod_LTLIBRARIES += ftmod_sangoma_isdn.la -endif - -if OPENR2 -mod_LTLIBRARIES += ftmod_r2.la -endif +mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_analog.la ftmod_analog_em.la ftmod_zt_la_SOURCES = $(SRC)/ftmod/ftmod_zt/ftmod_zt.c -ftmod_zt_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_zt_la_LDFLAGS = -module -avoid-version -ftmod_zt_la_LIBADD = $(MYLIB) +ftmod_zt_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_zt_la_LDFLAGS = -shared -module -avoid-version +ftmod_zt_la_LIBADD = libfreetdm.la ftmod_skel_la_SOURCES = $(SRC)/ftmod/ftmod_skel/ftmod_skel.c -ftmod_skel_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) +ftmod_skel_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) ftmod_skel_la_LDFLAGS = -module -avoid-version -ftmod_skel_la_LIBADD = $(MYLIB) - -if LIBSANGOMA -ftmod_wanpipe_la_SOURCES = $(SRC)/ftmod/ftmod_wanpipe/ftmod_wanpipe.c -ftmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe -ftmod_wanpipe_la_LDFLAGS = -module -avoid-version -lsangoma -ftmod_wanpipe_la_LIBADD = $(MYLIB) -endif - -#ftmod_isdn_la_SOURCES = \ -#$(SRC)/isdn/EuroISDNStateNT.c \ -#$(SRC)/isdn/EuroISDNStateTE.c \ -#$(SRC)/isdn/mfifo.c \ -#$(SRC)/isdn/Q921.c \ -#$(SRC)/isdn/Q931api.c \ -#$(SRC)/isdn/Q931.c \ -#$(SRC)/isdn/Q931ie.c \ -#$(SRC)/isdn/Q931mes.c \ -#$(SRC)/isdn/Q931StateNT.c \ -#$(SRC)/isdn/Q931StateTE.c \ -#$(SRC)/isdn/nationalmes.c \ -#$(SRC)/isdn/nationalStateNT.c \ -#$(SRC)/isdn/nationalStateTE.c \ -#$(SRC)/isdn/DMSmes.c \ -#$(SRC)/isdn/DMSStateNT.c \ -#$(SRC)/isdn/DMSStateTE.c \ -#$(SRC)/isdn/5ESSmes.c \ -#$(SRC)/isdn/5ESSStateNT.c \ -#$(SRC)/isdn/5ESSStateTE.c \ -#$(SRC)/isdn/Q932mes.c \ -#$(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c - -#ftmod_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE -#ftmod_isdn_la_LDFLAGS = $(PCAP_LIB_FLAGS) -module -avoid-version -#ftmod_isdn_la_LIBADD = $(MYLIB) +ftmod_skel_la_LIBADD = libfreetdm.la ftmod_analog_la_SOURCES = $(SRC)/ftmod/ftmod_analog/ftmod_analog.c -ftmod_analog_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_analog_la_LDFLAGS = -module -avoid-version -ftmod_analog_la_LIBADD = $(MYLIB) +ftmod_analog_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_analog_la_LDFLAGS = -shared -module -avoid-version +ftmod_analog_la_LIBADD = libfreetdm.la ftmod_analog_em_la_SOURCES = $(SRC)/ftmod/ftmod_analog_em/ftmod_analog_em.c -ftmod_analog_em_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_analog_em_la_LDFLAGS = -module -avoid-version -ftmod_analog_em_la_LIBADD = $(MYLIB) +ftmod_analog_em_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_analog_em_la_LDFLAGS = -shared -module -avoid-version +ftmod_analog_em_la_LIBADD = libfreetdm.la + +if HAVE_LIBSANGOMA +mod_LTLIBRARIES += ftmod_wanpipe.la +ftmod_wanpipe_la_SOURCES = $(SRC)/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +#some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe +#without c99 flags +ftmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(FTDM_COMPAT_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe +ftmod_wanpipe_la_LDFLAGS = -shared -module -avoid-version -lsangoma +ftmod_wanpipe_la_LIBADD = libfreetdm.la +endif + +if HAVE_LIBISDN +mod_LTLIBRARIES += ftmod_isdn.la +ftmod_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c +ftmod_isdn_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE $(LIBISDN_CPPFLAGS) $(PCAP_CPPFLAGS) +ftmod_isdn_la_LDFLAGS = -shared -module -avoid-version $(LIBISDN_LDFLAGS) $(PCAP_LDFLAGS) +ftmod_isdn_la_LIBADD = libfreetdm.la $(LIBISDN_LIBS) $(PCAP_LIBS) +endif if HAVE_SCTP +mod_LTLIBRARIES += ftmod_sangoma_boost.la ftmod_sangoma_boost_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_boost/sangoma_boost_client.c $(SRC)/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c -ftmod_sangoma_boost_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_sangoma_boost_la_LDFLAGS = -module -avoid-version -ftmod_sangoma_boost_la_LIBADD = $(MYLIB) +ftmod_sangoma_boost_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_sangoma_boost_la_LDFLAGS = -shared -module -avoid-version +ftmod_sangoma_boost_la_LIBADD = libfreetdm.la endif -if LIBPRI +if HAVE_LIBPRI +mod_LTLIBRARIES += ftmod_libpri.la ftmod_libpri_la_SOURCES = $(SRC)/ftmod/ftmod_libpri/ftmod_libpri.c $(SRC)/ftmod/ftmod_libpri/lpwrap_pri.c -ftmod_libpri_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_libpri_la_LDFLAGS = -module -avoid-version -lpri -ftmod_libpri_la_LIBADD = $(MYLIB) +ftmod_libpri_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_libpri_la_LDFLAGS = -shared -module -avoid-version -lpri +ftmod_libpri_la_LIBADD = libfreetdm.la endif -if PRITAP +if HAVE_PRITAP +mod_LTLIBRARIES += ftmod_pritap.la ftmod_pritap_la_SOURCES = $(SRC)/ftmod/ftmod_pritap/ftmod_pritap.c -ftmod_pritap_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_pritap_la_LDFLAGS = -module -avoid-version -lpri -ftmod_pritap_la_LIBADD = $(MYLIB) +ftmod_pritap_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_pritap_la_LDFLAGS = -shared -module -avoid-version -lpri +ftmod_pritap_la_LIBADD = libfreetdm.la endif -if SNGSS7 -ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c -ftmod_sangoma_ss7_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE -ftmod_sangoma_ss7_la_LDFLAGS = -module -avoid-version -lsng_ss7 -ftmod_sangoma_ss7_la_LIBADD = $(MYLIB) +if HAVE_SNG_SS7 +mod_LTLIBRARIES += ftmod_sangoma_ss7.la +ftmod_sangoma_ss7_la_SOURCES = \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c + +ftmod_sangoma_ss7_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE +ftmod_sangoma_ss7_la_LDFLAGS = -shared -module -avoid-version -lsng_ss7 +ftmod_sangoma_ss7_la_LIBADD = libfreetdm.la endif -if SNGISDN -ftmod_sangoma_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \ - $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +if HAVE_SNG_ISDN +mod_LTLIBRARIES += ftmod_sangoma_isdn.la +ftmod_sangoma_isdn_la_SOURCES = \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \ + $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c - -ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE -ftmod_sangoma_isdn_la_LDFLAGS = -module -avoid-version -lsng_isdn -ftmod_sangoma_isdn_la_LIBADD = $(MYLIB) +ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE +ftmod_sangoma_isdn_la_LDFLAGS = -shared -module -avoid-version -lsng_isdn +ftmod_sangoma_isdn_la_LIBADD = libfreetdm.la endif -if OPENR2 +if HAVE_OPENR2 +mod_LTLIBRARIES += ftmod_r2.la ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c -ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -ftmod_r2_la_LDFLAGS = -module -avoid-version -lopenr2 -ftmod_r2_la_LIBADD = $(MYLIB) +ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) +ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -lopenr2 +ftmod_r2_la_LIBADD = libfreetdm.la endif dox doxygen: doxygen $(FT_SRCDIR)/docs/Doxygen.conf -mod_freetdm/mod_freetdm.$(DYNAMIC_LIB_EXTEN): $(MYLIB) mod_freetdm/mod_freetdm.c - cd mod_freetdm && make +mod_freetdm/mod_freetdm.$(DYNAMIC_LIB_EXTEN): libfreetdm.la mod_freetdm/mod_freetdm.c + $(MAKE) -C mod_freetdm mod_freetdm: mod_freetdm/mod_freetdm.$(DYNAMIC_LIB_EXTEN) mod_freetdm-install: mod_freetdm - cd mod_freetdm && make install + $(MAKE) -C mod_freetdm install mod_freetdm-clean: - @if [ -f mod_freetdm/mod_freetdm.$(DYNAMIC_LIB_EXTEN) ] ; then cd mod_freetdm && make clean ; fi + @if [ -f mod_freetdm/mod_freetdm.$(DYNAMIC_LIB_EXTEN) ] ; then \ + $(MAKE) -C mod_freetdm clean ; \ + fi install-data-local: - $(mkinstalldirs) $(DESTDIR)$(PREFIX) + $(mkinstalldirs) $(DESTDIR)$(prefix) $(mkinstalldirs) $(DESTDIR)@confdir@ @[ -f "$(DESTDIR)@confdir@/freetdm.conf" ] || ( cp conf/*.conf $(DESTDIR)@confdir@) @echo FreeTDM Installed diff --git a/libs/freetdm/build/ax_compiler_vendor.m4 b/libs/freetdm/build/ax_compiler_vendor.m4 new file mode 100644 index 0000000000..a24a58da0f --- /dev/null +++ b/libs/freetdm/build/ax_compiler_vendor.m4 @@ -0,0 +1,15 @@ +AC_DEFUN([AX_COMPILER_VENDOR], +[ +AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown + # note: don't check for gcc first since some other compilers define __GNUC__ + for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do + vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ +#if !($vencpp) + thisisanerror; +#endif +])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) + done + ]) +]) diff --git a/libs/freetdm/build/libpcap.m4 b/libs/freetdm/build/libpcap.m4 index c20d345ca6..ea7581e69b 100644 --- a/libs/freetdm/build/libpcap.m4 +++ b/libs/freetdm/build/libpcap.m4 @@ -2,6 +2,10 @@ dnl libpcap.m4--PCAP libraries and includes dnl Derrick Brashear dnl from KTH krb and Arla dnl $Id: libpcap.m4,v 1.4 2006/01/20 20:21:09 snsimon Exp $ +dnl 2010/10/31 (stkn): +dnl rename: PCAP_INC_FLAGS -> PCAP_CPPFLAGS +dnl rename: PCAP_LIB_FLAGS -> PCAP_LDFLAGS (-L flags only) +dnl add: PCAP_LIBS (libs only) AC_DEFUN([PCAP_INC_WHERE1], [ ac_cv_found_pcap_inc=no @@ -129,12 +133,14 @@ AC_ARG_WITH(pcap-include, AC_MSG_RESULT(yes) PCAP_INC_DIR=$ac_cv_pcap_where_inc PCAP_LIB_DIR=$ac_cv_pcap_where_lib - PCAP_INC_FLAGS="-I${PCAP_INC_DIR}" - PCAP_LIB_FLAGS="-L${PCAP_LIB_DIR} -lpcap" + PCAP_CPPFLAGS="-I${PCAP_INC_DIR}" + PCAP_LDFLAGS="-L${PCAP_LIB_DIR}" + PCAP_LIBS="-lpcap" AC_SUBST(PCAP_INC_DIR) AC_SUBST(PCAP_LIB_DIR) - AC_SUBST(PCAP_INC_FLAGS) - AC_SUBST(PCAP_LIB_FLAGS) + AC_SUBST(PCAP_CPPFLAGS) + AC_SUBST(PCAP_LDFLAGS) + AC_SUBST(PCAP_LIBS) AC_DEFINE([HAVE_LIBPCAP],[1],[libpcap]) else ac_cv_found_pcap=no diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 18f83d8f1d..8b878edc09 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -1,119 +1,120 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_PREREQ(2.59) -AC_INIT([freetdm],[pre-alpha],[bugs@freeswitch.org]) +AC_PREREQ([2.59]) +AC_INIT([freetdm], [pre-alpha], [bugs@freeswitch.org]) AC_CONFIG_SRCDIR([src/ftdm_io.c]) -AC_CONFIG_AUX_DIR(build) -AM_INIT_AUTOMAKE(libfreetdm,0.1) +AC_CONFIG_AUX_DIR([build]) +AC_CONFIG_MACRO_DIR([build]) +AM_INIT_AUTOMAKE([libfreetdm], [0.1]) + +# >=automake-1.11 +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# override some default libtool behavior and invoke AC_PROG_LIBTOOL +# (see http://lists.gnu.org/archive/html/libtool/2007-03/msg00000.html) +m4_defun([_LT_AC_LANG_F77_CONFIG], [:]) +m4_defun([_LT_AC_LANG_GCJ_CONFIG], [:]) +m4_defun([_LT_AC_LANG_RC_CONFIG], [:]) # Checks for programs. AC_PROG_CC AC_PROG_MAKE_SET AM_PROG_CC_C_O +AC_PROG_LIBTOOL +AC_PROG_INSTALL +PKG_PROG_PKG_CONFIG -AC_PREFIX_DEFAULT(/usr/local/freetdm) -# AC_PREFIX_DEFAULT does not get expanded until too late so we need to do this to use prefix in this script -if test "x$prefix" = "xNONE" ; then - prefix='/usr/local/freetdm' +AX_COMPILER_VENDOR + +# AC_PREFIX_DEFAULT does not get expanded until too late so we need +# to do this to use prefix in this script +AC_PREFIX_DEFAULT([/usr/local/freetdm]) +if test "x${prefix}" = "xNONE" ; then + prefix='/usr/local/freetdm' fi # Absolute source/build directory FT_SRCDIR=`(cd $srcdir && pwd)` ft_builddir=`pwd` -AC_SUBST(FT_SRCDIR) -AC_SUBST(ft_builddir) +AC_SUBST([FT_SRCDIR]) +AC_SUBST([ft_builddir]) if test "$sysconfdir" = "\${prefix}/etc" ; then - confdir="$prefix/conf" + confdir="$prefix/conf" else - confdir="$sysconfdir" + confdir="$sysconfdir" fi -AC_SUBST(confdir) +AC_SUBST([confdir]) -#override some default libtool behavior and invoke AC_PROG_LIBTOOL (see http://lists.gnu.org/archive/html/libtool/2007-03/msg00000.html) -m4_defun([_LT_AC_LANG_F77_CONFIG], [:]) -m4_defun([_LT_AC_LANG_GCJ_CONFIG], [:]) -m4_defun([_LT_AC_LANG_RC_CONFIG], [:]) -#AM_PROG_CC_C_O -AC_PROG_LIBTOOL -AC_PROG_INSTALL +# Where to install the modules +AC_ARG_WITH([modinstdir], + [AS_HELP_STRING([--with-modinstdir=DIR], [Install modules into this location (default: ${prefix}/mod)])], + [case "${withval}" in + no|yes) AC_MSG_ERROR([Invalid value \"${withval}\", option requires a valid path]) ;; + *) modinstdir="${withval}" ;; + esac], + [modinstdir="${prefix}/mod"] +) +AC_SUBST([modinstdir]) -# Check for com;iler type -AC_DEFUN([AX_COMPILER_VENDOR], -[ -AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, - [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown - # note: don't check for GCC first, since some other compilers define __GNUC__ - for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do - vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ -#if !($vencpp) - thisisanerror; -#endif -])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break]) - done - ]) -]) -AC_ARG_ENABLE([enable_64], [AS_HELP_STRING([--enable-64], [Enable 64bit compilation])], [enable_64="$enableval"], [enable_64="no"]) - -AX_COMPILER_VENDOR +AC_ARG_ENABLE([enable_64], + [AS_HELP_STRING([--enable-64], [Enable 64bit compilation])], + [enable_64="${enableval}"], + [enable_64="no"] +) case "${ax_cv_c_compiler_vendor}" in gnu) - COMP_VENDOR_CFLAGS="-ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -O0" - ;; + COMP_VENDOR_CFLAGS="-ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -O0" + ;; sun) - COMP_VENDOR_CFLAGS="-xc99=all -mt -xCC -D__FUNCTION__=__func__ -xvpara" - if test "$enable_64" = "yes" ; then - COMP_VENDOR_CFLAGS="-m64 $COMP_VENDOR_CFLAGS" - fi - ;; + COMP_VENDOR_CFLAGS="-xc99=all -mt -xCC -D__FUNCTION__=__func__ -xvpara" + if test "$enable_64" != "no" ; then + COMP_VENDOR_CFLAGS="-m64 $COMP_VENDOR_CFLAGS" + fi + ;; *) - COMP_VENDOR_CFLAGS="-std=c99 -Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" - ;; + COMP_VENDOR_COMPAT_CFLAGS="-Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes" + COMP_VENDOR_CFLAGS="-std=c99 $COMP_VENDOR_COMPAT_CFLAGS" + ;; esac +AC_SUBST([COMP_VENDOR_COMPAT_CFLAGS]) +AC_SUBST([COMP_VENDOR_CFLAGS]) -#set SOLINK variable based on compiler and host -if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then - SOLINK="-Bdynamic -dy -G" -elif test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then - case "$host" in - *darwin*) - SOLINK="-dynamic -bundle -force-flat-namespace" - ;; - *-solaris2*) - SOLINK="-shared -Xlinker" - ;; - *) - SOLINK="-shared -Xlinker -x" - ;; - esac -else - AC_ERROR([Please update configure.in with SOLINK values for your compiler]) +# Enable debugging +AC_ARG_ENABLE([debug], + [AC_HELP_STRING([--enable-debug], [build with debug information])], + [enable_debug="${enableval}"], + [enable_debug="yes"] +) +if test "${enable_debug}" != "no"; then + AC_DEFINE([DEBUG], [], [Enable extra debugging.]) + + if test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then + COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS -g -ggdb" + fi fi +AC_SUBST([COMP_VENDOR_CFLAGS]) # set DYNAMIC_LIB_EXTEN # we should really be using libtool so we don't need to do this case "$host" in - *cygwin* | *mingw*) - DYNAMIC_LIB_EXTEN="dll" - ;; - *) - DYNAMIC_LIB_EXTEN="so" - ;; +*cygwin* | *mingw*) + DYNAMIC_LIB_EXTEN="dll" + ;; +*) + DYNAMIC_LIB_EXTEN="so" + ;; esac - -AC_SUBST(SOLINK) -AC_SUBST(DYNAMIC_LIB_EXTEN) +AC_SUBST([DYNAMIC_LIB_EXTEN]) AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pthread], [pthread_create]) AC_CHECK_LIB([m], [cos]) -AX_LIB_PCAP AC_CHECK_HEADERS([netinet/sctp.h netdb.h sys/select.h]) AM_CONDITIONAL([HAVE_SCTP],[test "${ac_cv_header_netinet_sctp_h}" = "yes"]) @@ -121,105 +122,252 @@ AM_CONDITIONAL([HAVE_SCTP],[test "${ac_cv_header_netinet_sctp_h}" = "yes"]) AC_CHECK_FUNC([gethostbyname_r], [], [AC_CHECK_LIB([nsl], [gethostbyname_r])] ) -if test "$ac_cv_func_gethostbyname_r" = "yes" -o "$ac_cv_lib_nsl_gethostbyname_r" = "yes" ; then +if test "$ac_cv_func_gethostbyname_r" = "yes" -o "$ac_cv_lib_nsl_gethostbyname_r" = "yes" +then + AC_MSG_CHECKING([whether gethostbyname_r requires five arguments]) -AC_MSG_CHECKING([whether gethostbyname_r requires five arguments]) + ac_cv_func_gethostbyname_r_five_args="no" -ac_cv_func_gethostbyname_r_five_args="no" + AC_TRY_COMPILE([#include ], + [char *name; + struct hostent *he, *res; + char buffer[2048]; + int buflen = 2048; + (void)gethostbyname_r(name, he, buffer, buflen, &res)], + [ac_cv_func_gethostbyname_r_five_args="yes" + AC_DEFINE([HAVE_GETHOSTBYNAME_R_FIVE], [1], [gethostbyname_r has five arguments])] + ) -AC_TRY_COMPILE([#include ], - [char *name; - struct hostent *he, *res; - char buffer[2048]; - int buflen = 2048; - (void)gethostbyname_r(name, he, buffer, buflen, &res)], - [ac_cv_func_gethostbyname_r_five_args="yes" - AC_DEFINE([HAVE_GETHOSTBYNAME_R_FIVE], [1], [gethostbyname_r has five arguments])] -) - - AC_MSG_RESULT([$ac_cv_func_gethostbyname_r_five_args]) - AC_DEFINE([HAVE_GETHOSTBYNAME_R],[1],[threadsafe gethostbyname]) + AC_MSG_RESULT([$ac_cv_func_gethostbyname_r_five_args]) + AC_DEFINE([HAVE_GETHOSTBYNAME_R], [1], [threadsafe gethostbyname]) fi -# Enable debugging -AC_ARG_ENABLE(debug, -[AC_HELP_STRING([--enable-debug],[build with debug information])],[enable_debug="$enableval"],[enable_debug="yes"]) +## +## Modules and optional features +## +AC_MSG_RESULT([${as_nl}<<>> Modules and optional features]) -if test "${enable_debug}" = "yes"; then - AC_DEFINE([DEBUG],[],[Enable extra debugging.]) - - if test "x${ax_cv_c_compiler_vendor}" = "xgnu" ; then - COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS -g -ggdb" - fi -fi - -# Where to install the modules -AC_ARG_WITH([modinstdir], - [AS_HELP_STRING([--with-modinstdir=DIR], [Install modules into this location (default: $prefix/mod)])], [modinstdir="$withval"], [modinstdir="${prefix}/mod"]) - -AC_SUBST(modinstdir) - - -# libpri? -AC_ARG_WITH([libpri], - [AS_HELP_STRING([--with-libpri], [Install ftmod_libpri])], [enable_libpri="yes"], [enable_libpri="no"]) -AC_SUBST(enable_libpri) - -# pritap? +## +# pritap (TODO: add checks) +# +HAVE_PRITAP="no" AC_ARG_WITH([pritap], - [AS_HELP_STRING([--with-pritap], [Install ftmod_pritap])], [enable_pritap="yes"], [enable_pritap="no"]) -AC_SUBST(enable_pritap) + [AS_HELP_STRING([--with-pritap], [Install ftmod_pritap])], + [case "${withval}" in + no) enable_pritap="no" ;; + *) enable_pritab="yes" ;; + esac], + [enable_pritap="no"] +) +HAVE_PRITAP="${enable_pritap}" +AM_CONDITIONAL([HAVE_PRITAP],[test "${enable_pritap}" = "yes"]) # debug dtmf? AC_ARG_WITH([debugdtmf], - [AS_HELP_STRING([--with-debugdtmf], [Debug DTMF])], [enable_debugdtmf="yes"], [enable_debugdtmf="no"]) -AC_SUBST(enable_debugdtmf) + [AS_HELP_STRING([--with-debugdtmf], [Debug DTMF])], + [case "${withval}" in + no) enable_debugdtmf="no" ;; + *) enable_debugdtmf="yes" ;; + esac], + [enable_debugdtmf="no"] +) +AM_CONDITIONAL([WANT_DEBUGDTMF], [test "${enable_debugdtmf}" = "yes"]) -AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [have_libsangoma="yes"]) -AM_CONDITIONAL([LIBSANGOMA],[test "${have_libsangoma}" = "yes"]) +## +# OpenR2 stack +# +HAVE_OPENR2="no" +AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [HAVE_OPENR2="yes"]) +AC_MSG_RESULT([checking whether to build ftmod_r2... ${HAVE_OPENR2}]) +AM_CONDITIONAL([HAVE_OPENR2], [test "${HAVE_OPENR2}" = "yes"]) -AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"]) +## +# Digium libpri (TODO: add checks) +# +HAVE_LIBPRI="no" +AC_ARG_WITH([libpri], + [AS_HELP_STRING([--with-libpri], [Install ftmod_libpri])], + [case "${withval}" in + no) enable_libpri="no" ;; + *) enable_libpri="yes" ;; + esac], + [enable_libpri="no"] +) +if test "${enable_libpri}" != "no" +then + AC_MSG_RESULT([${as_nl}<<>> Digium libpri]) -AM_CONDITIONAL([PRITAP],[test "${enable_pritap}" = "yes"]) + save_LIBS="${LIBS}" + LIBS="${LIBS} -lpri" + AC_MSG_CHECKING([whether libpri is usable]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include ], + [const char *version = pri_get_version();] + )], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([libpri is not installed or unusable (see config.log for details)])] + ) -AM_CONDITIONAL([DEBUGDTMF],[test "${enable_debugdtmf}" = "yes"]) + AC_MSG_CHECKING([whether libpri has BRI support]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [extern void pri_new_bri_cb(void);], + [pri_new_bri_cb();] + )], + [AC_DEFINE([HAVE_LIBPRI_BRI], [1], [libpri has BRI support]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_NOTICE([You will need libpri-1.4.12_beta1 or newer for BRI support])] + ) -AC_CHECK_LIB([sng_ss7], [sng_isup_init], [have_sng_ss7="yes"]) -AM_CONDITIONAL([SNGSS7],[test "${have_sng_ss7}" = "yes"]) + AC_MSG_CHECKING([whether libpri has AOC event support]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [extern void pri_aoc_events_enable(void);], + [pri_aoc_events_enable();] + )], + [AC_DEFINE([HAVE_LIBPRI_AOC], [1], [libpri has AOC event support]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_NOTICE([You will need libpri-1.4.12_beta1 or newer for AOC event support])] + ) + LIBS="${save_LIBS}" +fi +HAVE_LIBPRI="${enable_libpri}" +AM_CONDITIONAL([HAVE_LIBPRI],[test "${enable_libpri}" = "yes"]) -AC_CHECK_LIB([sng_isdn], [sng_isdn_init], [have_sng_isdn="yes"]) -AM_CONDITIONAL([SNGISDN],[test "${have_sng_isdn}" = "yes"]) +## +# Sangoma Wanpipe +# +HAVE_LIBSANGOMA="no" +AC_MSG_RESULT([${as_nl}<<>> Sangoma Wanpipe]) +AC_CHECK_LIB([sangoma], [sangoma_span_chan_toif], [HAVE_LIBSANGOMA="yes"]) +AC_MSG_RESULT([checking whether to build ftmod_wanpipe... ${HAVE_LIBSANGOMA}]) +AM_CONDITIONAL([HAVE_LIBSANGOMA], [test "${HAVE_LIBSANGOMA}" = "yes"]) -AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"]) -AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"]) +## +# Sangoma ISDN stack +# +HAVE_SNG_ISDN="no" +AC_MSG_RESULT([${as_nl}<<>> Sangoma ISDN stack]) +AC_CHECK_LIB([sng_isdn], [sng_isdn_init], [HAVE_SNG_ISDN="yes"]) +AC_MSG_RESULT([checking whether to build ftmod_sangoma_isdn... ${HAVE_SNG_ISDN}]) +AM_CONDITIONAL([HAVE_SNG_ISDN], [test "${HAVE_SNG_ISDN}" = "yes"]) -if test "${have_sng_isdn}" = "yes"; then +if test "${HAVE_SNG_ISDN}" = "yes"; then if test "${build}" == "${host}" then case "${host}" in x86_64-*) - # X86_64 machines need additional flags when compiling against libsng_isdn - CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" - ;; + # X86_64 machines need additional flags when compiling against libsng_isdn + CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" + ;; esac fi fi -if test "${have_sng_ss7}" = "yes"; then +## +# Sangoma SS7 stack +# +HAVE_SNG_SS7="no" +AC_MSG_RESULT([${as_nl}<<>> Sangoma SS7 stack]) +AC_CHECK_LIB([sng_ss7], [sng_isup_init], [HAVE_SNG_SS7="yes"]) +AC_MSG_RESULT([checking whether to build ftmod_sangoma_ss7... ${HAVE_SNG_SS7}]) +AM_CONDITIONAL([HAVE_SNG_SS7], [test "${HAVE_SNG_SS7}" = "yes"]) + +if test "${HAVE_SNG_SS7}" = "yes"; then if test "${build}" == "${host}" then case "${host}" in x86_64-*) - # X86_64 machines need additional flags when compiling against libsng_isdn - CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" - ;; + # X86_64 machines need additional flags when compiling against libsng_isdn + CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT" + ;; esac fi fi -COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS" -AC_SUBST(COMP_VENDOR_CFLAGS) -AC_CONFIG_FILES([Makefile - freetdm.pc - mod_freetdm/Makefile]) +## +# libisdn +# +HAVE_LIBISDN="no" +AC_ARG_WITH([libisdn], + [AS_HELP_STRING([--with-libisdn], [Install ftmod_isdn (libisdn stack)])], + [case "${withval}" in + no) with_libisdn="no" ;; + *) with_libisdn="yes" ;; + esac + ], + [with_libisdn="no"] +) +if test "${with_libisdn}" != "no" +then + AC_MSG_RESULT([${as_nl}<<>> ftmod_isdn (libisdn stack)]) + PKG_CHECK_MODULES([libisdn], + [libisdn >= 0.0.1], + [AC_MSG_CHECKING([libisdn version]) + LIBISDN_VERSION="`${PKG_CONFIG} --modversion libisdn`" + if test -z "${LIBISDN_VERSION}"; then + AC_MSG_ERROR([Failed to retrieve libisdn version]) + fi + AC_MSG_RESULT([${LIBISDN_VERSION}]) + + # check features + AC_MSG_CHECKING([for new experimental API]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [#include + #if !LIBISDN_FEATURE(API2) + #error "libisdn API v2 not available" + #endif + ], + [;] + )], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])] + ) + + HAVE_LIBISDN="yes" + AC_DEFINE([HAVE_LIBISDN], [1], [libisdn support]) + AC_SUBST([LIBISDN_CFLAGS], [${libisdn_CFLAGS}]) + AC_SUBST([LIBISDN_CPPFLAGS],[${libisdn_CPPFLAGS}]) + AC_SUBST([LIBISDN_LDFLAGS], [${libisdn_LDFLAGS}]) + AC_SUBST([LIBISDN_LIBS], [${libisdn_LIBS}]) + AC_SUBST([LIBISDN_VERSION]) + ], + [AC_MSG_ERROR([Need libisdn-0.0.1 or higher])] + ) + AX_LIB_PCAP +fi +AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"]) + +AC_MSG_RESULT([${as_nl}<<>> Creating output files]) +AC_CONFIG_FILES([ + Makefile + freetdm.pc + mod_freetdm/Makefile +]) AC_OUTPUT + +# +# summary screen +# +AC_MSG_RESULT([ +============================ FreeTDM configuration ============================ + ++ Modules + + Signalling: + ftmod_isdn......................... ${HAVE_LIBISDN} + ftmod_libpri....................... ${HAVE_LIBPRI} + ftmod_sangoma_isdn................. ${HAVE_SNG_ISDN} + ftmod_sangoma_ss7.................. ${HAVE_SNG_SS7} + ftmod_r2........................... ${HAVE_OPENR2} + ftmod_pritap....................... ${HAVE_PRITAP} + I/O: + ftmod_wanpipe...................... ${HAVE_LIBSANGOMA} + +=============================================================================== +]) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index b7b8e040d6..0a35913ec4 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -657,7 +657,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk); if (status == FTDM_FAIL) { - ftdm_log(FTDM_LOG_WARNING, "failed to wait for I/O\n"); + ftdm_log(FTDM_LOG_ERROR, "Failed to wait for I/O\n"); goto fail; } @@ -3088,85 +3088,44 @@ static switch_status_t load_config(void) if ((spans = switch_xml_child(cfg, "libpri_spans"))) { for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - char *id = (char *) switch_xml_attr(myspan, "id"); char *name = (char *) switch_xml_attr(myspan, "name"); + ftdm_conf_parameter_t spanparameters[10]; ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; + const char *context = "default"; const char *dialplan = "XML"; - - const char *o_node = "cpe"; - const char *o_switch = "dms100"; - const char *o_dp = "unknown"; - const char *o_l1 = "ulaw"; - const char *o_debug = "none"; - const char* opts = "none"; - - uint32_t span_id = 0; + unsigned paramindex = 0; ftdm_span_t *span = NULL; + uint32_t span_id = 0; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { + if (!name) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n"); + continue; + } + + for (param = switch_xml_child(myspan, "param"); param && paramindex < 10; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); - if (!strcasecmp(var, "node")) { - o_node = val; - } else if (!strcasecmp(var, "switch")) { - o_switch = val; - } else if (!strcasecmp(var, "dp")) { - o_dp = val; - } else if (!strcasecmp(var, "l1")) { - o_l1 = val; - } else if (!strcasecmp(var, "debug")) { - o_debug = val; - } else if (!strcasecmp(var, "context")) { + if (!strcasecmp(var, "context")) { context = val; - } else if (!strcasecmp(var, "opts")) { - opts = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; - } - } - - if (!id && !name) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n"); - continue; - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); + } else { + spanparameters[paramindex].var = var; + spanparameters[paramindex].val = val; + paramindex++; } } + zstatus = ftdm_span_find_by_name(name, &span); if (zstatus != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); + ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name); continue; } - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - - if (ftdm_configure_span(span, "libpri", on_clear_channel_signal, - "node", o_node, - "switch", o_switch, - "dp", o_dp, - "l1", o_l1, - "debug", o_debug, - "opts", opts, - FTDM_TAG_END) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d node: %s switch: %s dp: %s l1: %s debug: %s error: %s\n", - span_id, switch_str_nil(o_node), switch_str_nil(o_switch), switch_str_nil(o_dp), switch_str_nil(o_l1), switch_str_nil(o_debug), - ftdm_span_get_last_error(span)); + span_id = ftdm_span_get_id(span); + if (ftdm_configure_span_signaling(span, "libpri", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name); continue; } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index f02c9c48db..1ede703a41 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1751,7 +1751,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan) goto done; } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) { snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n"); goto done; @@ -3927,6 +3927,11 @@ static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex) ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id); return FTDM_FAIL; } + if (span->channels[chan_index]->alarm_flags) { + ftdm_set_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM); + } else { + ftdm_clear_flag_locked(span->channels[chan_index], FTDM_CHANNEL_IN_ALARM); + } } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index d64e711e73..23e67426ca 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -1,23 +1,23 @@ /* * Copyright (c) 2007, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -30,266 +30,267 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -/** - * Workaround for missing u_int / u_short types on solaris - */ -#if defined(HAVE_LIBPCAP) && defined(__SunOS) -#define __EXTENSIONS__ +#ifdef HAVE_CONFIG_H +#include "config.h" #endif +#include +#include +#include -#include "private/ftdm_core.h" -#include "Q931.h" -#include "Q921.h" #ifdef WIN32 #include #else #include #endif -#include "ftdm_isdn.h" +#include "ftmod_isdn.h" #define LINE "--------------------------------------------------------------------------------" -//#define IODEBUG /* helper macros */ #define FTDM_SPAN_IS_NT(x) (((ftdm_isdn_data_t *)(x)->signal_data)->mode == Q921_NT) +#define DEFAULT_NATIONAL_PREFIX "0" +#define DEFAULT_INTERNATIONAL_PREFIX "00" -#ifdef HAVE_LIBPCAP -/*-------------------------------------------------------------------------*/ -/*Q931ToPcap functions*/ +/***************************************************************************************** + * PCAP + * Based on Helmut Kuper's () implementation, + * but using a different approach (needs a recent libpcap + wireshark) + *****************************************************************************************/ +#ifdef HAVE_PCAP +#include /* htons() */ #include -#endif -#define SNAPLEN 1522 -#define MAX_ETHER_PAYLOAD_SIZE 1500 -#define MIN_ETHER_PAYLOAD_SIZE 42 -#define SIZE_ETHERNET 18 -#define VLANID_OFFSET 15 -#define SIZE_IP 20 -#define SIZE_TCP 20 -#define SIZE_TPKT 4 -#define SIZE_ETHERNET_CRC 4 -#define OVERHEAD SIZE_ETHERNET+SIZE_IP+SIZE_TCP+SIZE_TPKT -#define MAX_Q931_SIZE MAX_ETHER_PAYLOAD_SIZE-SIZE_IP-SIZE_TCP-SIZE_TPKT -#define TPKT_SIZE_OFFSET SIZE_ETHERNET+SIZE_IP+SIZE_TCP+2 -#define IP_SIZE_OFFSET SIZE_ETHERNET+2 -#define TCP_SEQ_OFFSET SIZE_ETHERNET+SIZE_IP+4 +#define PCAP_SNAPLEN 1500 -#ifdef HAVE_LIBPCAP -/*Some globals*/ -unsigned long pcapfilesize = 0; -unsigned long tcp_next_seq_no_send = 0; -unsigned long tcp_next_seq_no_rec = 0; -pcap_dumper_t *pcapfile = NULL; -struct pcap_pkthdr pcaphdr; -pcap_t *pcaphandle = NULL; -char *pcapfn = NULL; -int do_q931ToPcap= 0; +struct pcap_context { + pcap_dumper_t *dump; /*!< pcap file handle */ + pcap_t *handle; /*!< pcap lib context */ + char *filename; /*!< capture file name */ +}; -/*Predefined Ethernet Frame with Q931-over-IP encapsulated - From remote TDM host to FreeSWITCH*/ -L3UCHAR recFrame[SNAPLEN]= { - /*IEEE 802.3 VLAN 802.1q Ethernet Frame Header*/ - 2,0,1,0xAA,0xAA,0xAA,2,0,1,0xBB,0xBB,0xBB,0x81,0,0xE0,0,0x08,0, - /*IPv4 Header (minimal size; no options)*/ - 0x45,0,0,44,0,0,0,0,64,6,0,0,2,2,2,2,1,1,1,1, - /*TCP-Header*/ - 0,0x66,0,0x66,0,0,0,0,0,0,0,0,0x50,0,0,1,0,0,0,0, - /*TPKT-Header RFC 1006*/ - 3,0,0,0 - }; - -/*Predefined Ethernet Frame with Q931-over-IP encapsulated - Frome FreeSWITCH to remote TDM host*/ -L3UCHAR sendFrame[SNAPLEN]= { - /*IEEE 802.3 VLAN 802.1q Ethernet Frame Header*/ - 2,0,1,0xBB,0xBB,0xBB,2,0,1,0xAA,0xAA,0xAA,0x81,0,0xE0,0,0x08,0, - /*IPv4 Header (minimal size; no options)*/ - 0x45,0,0,44,0,0,0,0,64,6,0,0,1,1,1,1,2,2,2,2, - /*TCP-Header*/ - 0,0x66,0,0x66,0,0,0,0,0,0,0,0,0x50,0,0,1,0,0,0,0, - /*TPKT-Header RFC 1006*/ - 3,0,0,0 - }; - -/** - * \brief Opens a pcap file for capture - * \return Success or failure - */ -static ftdm_status_t openPcapFile(void) +static inline ftdm_status_t isdn_pcap_is_open(struct ftdm_isdn_data *isdn) { - if(!pcaphandle) - { - pcaphandle = pcap_open_dead(DLT_EN10MB, SNAPLEN); - if (!pcaphandle) - { - ftdm_log(FTDM_LOG_ERROR, "Can't open pcap session: (%s)\n", pcap_geterr(pcaphandle)); - return FTDM_FAIL; - } - } - - if(!pcapfile){ - /* Open the dump file */ - if(!(pcapfile=pcap_dump_open(pcaphandle, pcapfn))){ - ftdm_log(FTDM_LOG_ERROR, "Error opening output file (%s)\n", pcap_geterr(pcaphandle)); - return FTDM_FAIL; - } - } - else{ - ftdm_log(FTDM_LOG_WARNING, "Pcap file is already open!\n"); - return FTDM_FAIL; - } - - ftdm_log(FTDM_LOG_DEBUG, "Pcap file '%s' successfully opened!\n", pcapfn); - - pcaphdr.ts.tv_sec = 0; - pcaphdr.ts.tv_usec = 0; - pcapfilesize = 24; /*current pcap file header seems to be 24 bytes*/ - tcp_next_seq_no_send = 0; - tcp_next_seq_no_rec = 0; - - return FTDM_SUCCESS; + return (isdn->pcap) ? 1 : 0; } -/** - * \brief Closes a pcap file - * \return Success - */ -static ftdm_status_t closePcapFile(void) +static inline ftdm_status_t isdn_pcap_capture_both(struct ftdm_isdn_data *isdn) { - if (pcapfile) { - pcap_dump_close(pcapfile); - if (pcaphandle) pcap_close(pcaphandle); + return ((isdn->flags & (FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY)) == FTDM_ISDN_CAPTURE) ? 1 : 0; +} - ftdm_log(FTDM_LOG_DEBUG, "Pcap file closed! File size is %lu bytes.\n", pcapfilesize); +static inline ftdm_status_t isdn_pcap_capture_l3only(struct ftdm_isdn_data *isdn) +{ + return ((isdn->flags & FTDM_ISDN_CAPTURE) && (isdn->flags & FTDM_ISDN_CAPTURE_L3ONLY)) ? 1 : 0; +} - pcaphdr.ts.tv_sec = 0; - pcaphdr.ts.tv_usec = 0; - pcapfile = NULL; - pcaphandle = NULL; - pcapfilesize = 0; - tcp_next_seq_no_send = 0; - tcp_next_seq_no_rec = 0; +static ftdm_status_t isdn_pcap_open(struct ftdm_isdn_data *isdn, char *filename) +{ + struct pcap_context *pcap = NULL; + + if (!isdn) { + return FTDM_FAIL; } - /*We have allways success with this? I think so*/ + if (ftdm_strlen_zero(filename)) { + return FTDM_FAIL; + } + + pcap = malloc(sizeof(struct pcap_context)); + if (!pcap) { + ftdm_log(FTDM_LOG_ERROR, "Failed to allocate isdn pcap context\n"); + return FTDM_FAIL; + } + + memset(pcap, 0, sizeof(struct pcap_context)); + + pcap->filename = strdup(filename); + + pcap->handle = pcap_open_dead(DLT_LINUX_LAPD, PCAP_SNAPLEN); + if (!pcap->handle) { + ftdm_log(FTDM_LOG_ERROR, "Failed to open pcap handle\n"); + goto error; + } + + pcap->dump = pcap_dump_open(pcap->handle, pcap->filename); + if (!pcap->dump) { + ftdm_log(FTDM_LOG_ERROR, "Failed to open capture file: %s\n", pcap_geterr(pcap->handle)); + goto error; + } + + ftdm_log(FTDM_LOG_INFO, "Capture file \"%s\" opened\n", pcap->filename); + + isdn->pcap = pcap; + + return FTDM_SUCCESS; + +error: + if (pcap->handle) { + pcap_close(pcap->handle); + } + if (pcap->filename) { + free(pcap->filename); + } + + free(pcap); + + return FTDM_FAIL; +} + +static ftdm_status_t isdn_pcap_close(struct ftdm_isdn_data *isdn) +{ + struct pcap_context *pcap = NULL; + long size; + + if (!isdn || !isdn->pcap) { + return FTDM_FAIL; + } + pcap = isdn->pcap; + + isdn->flags &= ~(FTDM_ISDN_CAPTURE | FTDM_ISDN_CAPTURE_L3ONLY); + isdn->pcap = NULL; + + pcap_dump_flush(pcap->dump); + + size = pcap_dump_ftell(pcap->dump); + ftdm_log(FTDM_LOG_INFO, "File \"%s\" captured %ld bytes of data\n", pcap->filename, size); + + pcap_dump_close(pcap->dump); + pcap_close(pcap->handle); + + free(pcap->filename); + free(pcap); + return FTDM_SUCCESS; } -/** - * \brief Writes a Q931 packet to a pcap file - * \return Success or failure - */ -static ftdm_status_t writeQ931PacketToPcap(L3UCHAR* q931buf, L3USHORT q931size, L3ULONG span_id, L3USHORT direction) +static inline void isdn_pcap_start(struct ftdm_isdn_data *isdn) { - L3UCHAR *frame = NULL; - struct timeval ts; - u_char spanid = (u_char)span_id; - unsigned long *tcp_next_seq_no = NULL; + if (!isdn->pcap) + return; - spanid=span_id; - - /*The total length of the ethernet frame generated by this function has a min length of 66 - so we don't have to care about padding :)*/ + isdn->flags |= FTDM_ISDN_CAPTURE; +} +static inline void isdn_pcap_stop(struct ftdm_isdn_data *isdn) +{ + isdn->flags &= ~FTDM_ISDN_CAPTURE; +} - /*FS is sending the packet*/ - if(direction==0){ - frame=sendFrame; - tcp_next_seq_no = &tcp_next_seq_no_send; - } - /*FS is receiving the packet*/ - else{ - frame=recFrame; - tcp_next_seq_no = &tcp_next_seq_no_rec; +#ifndef ETH_P_LAPD +#define ETH_P_LAPD 0x0030 +#endif + +struct isdn_sll_hdr { + uint16_t slltype; + uint16_t sllhatype; + uint16_t slladdrlen; + uint8_t slladdr[8]; + uint16_t sllproto; +}; + +/* Fake Q.921 I-frame */ +//static const char q921_fake_frame[] = { 0x00, 0x00, 0x00, 0x00 }; + +enum { + ISDN_PCAP_INCOMING = 0, + ISDN_PCAP_INCOMING_BCAST = 1, + ISDN_PCAP_OUTGOING = 4, +}; + +static ftdm_status_t isdn_pcap_write(struct ftdm_isdn_data *isdn, unsigned char *buf, ftdm_ssize_t len, int direction) +{ + unsigned char frame[PCAP_SNAPLEN]; + struct pcap_context *pcap; + struct isdn_sll_hdr *sll_hdr = (struct isdn_sll_hdr *)frame; + struct pcap_pkthdr hdr; + int offset = sizeof(struct isdn_sll_hdr); + int nbytes; + + if (!isdn || !isdn->pcap || !buf || !len) { + return FTDM_FAIL; } - /*Set spanid in VLAN-ID tag*/ - frame[VLANID_OFFSET] = spanid; + pcap = isdn->pcap; - /*** Write sent packet ***/ - if(q931size > MAX_Q931_SIZE) - { - /*WARNING*/ - ftdm_log(FTDM_LOG_WARNING, "Q931 packet size is too big (%u)! Ignoring it!\n", q931size); - return FTDM_FAIL; - } - - /*Copy q931 buffer into frame*/ - memcpy(frame+OVERHEAD,q931buf,q931size); - - /*Store TCP sequence number in TCP header*/ - frame[TCP_SEQ_OFFSET]=(*tcp_next_seq_no>>24)&0xFF; - frame[TCP_SEQ_OFFSET+1]=(*tcp_next_seq_no>>16)&0xFF; - frame[TCP_SEQ_OFFSET+2]=(*tcp_next_seq_no>>8)&0xFF; - frame[TCP_SEQ_OFFSET+3]=*tcp_next_seq_no & 0xFF; - - /*Store size of TPKT packet*/ - q931size+=4; - frame[TPKT_SIZE_OFFSET]=(q931size>>8)&0xFF; - frame[TPKT_SIZE_OFFSET+1]=q931size&0xFF; - - /*Calc next TCP sequence number*/ - *tcp_next_seq_no+=q931size; - - /*Store size of IP packet*/ - q931size+=SIZE_IP+SIZE_TCP; - frame[IP_SIZE_OFFSET]=(q931size>>8)&0xFF; - frame[IP_SIZE_OFFSET+1]=q931size&0xFF; - - pcaphdr.caplen = SIZE_ETHERNET+SIZE_ETHERNET_CRC+q931size; - pcaphdr.len = pcaphdr.caplen; - - /* Set Timestamp */ - /* Get Time in ms. usecs would be better ... */ - gettimeofday(&ts, NULL); - /*Write it into packet header*/ - pcaphdr.ts.tv_sec = ts.tv_sec; - pcaphdr.ts.tv_usec = ts.tv_usec; - - pcap_dump((u_char*)pcapfile, &pcaphdr, frame); - pcap_dump_flush(pcapfile); - - /*Maintain pcap file size*/ - pcapfilesize+=pcaphdr.caplen; - pcapfilesize+=sizeof(struct pcap_pkthdr); - - ftdm_log(FTDM_LOG_DEBUG, "Added %u bytes to pcap file. File size is now %lu, \n", q931size, pcapfilesize); - - return FTDM_SUCCESS; -} + /* Update SLL header */ + sll_hdr->slltype = htons(direction); + sll_hdr->sllhatype = 0; + sll_hdr->slladdrlen = 1; + sll_hdr->slladdr[0] = (isdn->mode == Q921_NT) ? 1 : 0; /* TODO: NT/TE */ + sll_hdr->sllproto = htons(ETH_P_LAPD); +#if 0 + /* Q.931-only mode: copy fake Q.921 header */ + if (isdn->flags & FTDM_ISDN_CAPTURE_L3ONLY) { + /* copy fake q921 header */ + memcpy(frame + offset, q921_fake_frame, sizeof(q921_fake_frame)); + offset += sizeof(q921_fake_frame); + } #endif -/** - * \brief Unloads pcap IO - * \return Success or failure - */ -static FIO_IO_UNLOAD_FUNCTION(close_pcap) -{ -#ifdef HAVE_LIBPCAP - return closePcapFile(); -#else + /* Copy data */ + nbytes = (len > (PCAP_SNAPLEN - offset)) ? (PCAP_SNAPLEN - offset) : len; + memcpy(frame + offset, buf, nbytes); + + /* Update timestamp */ + memset(&hdr, 0, sizeof(struct pcap_pkthdr)); + gettimeofday(&hdr.ts, NULL); + hdr.caplen = offset + nbytes; + hdr.len = hdr.caplen; + + /* Write packet */ + pcap_dump((unsigned char *)pcap->dump, &hdr, frame); + return FTDM_SUCCESS; -#endif } +#endif /* HAVE_PCAP */ -/*Q931ToPcap functions DONE*/ -/*-------------------------------------------------------------------------*/ -/** - * \brief Gets current time - * \return Current time (in ms) - */ static L2ULONG ftdm_time_now(void) { return (L2ULONG)ftdm_current_time_in_ms(); } /** - * \brief Initialises an ISDN channel (outgoing call) - * \param ftdmchan Channel to initiate call on - * \return Success or failure + * \brief Returns the signalling status on a channel + * \param ftdmchan Channel to get status on + * \param status Pointer to set signalling status + * \return Success or failure + */ +static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(isdn_get_channel_sig_status) +{ + *status = FTDM_SIG_STATE_DOWN; + + ftdm_isdn_data_t *isdn_data = ftdmchan->span->signal_data; + if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { + *status = FTDM_SIG_STATE_UP; + } + return FTDM_SUCCESS; +} + +/** + * \brief Returns the signalling status on a span + * \param span Span to get status on + * \param status Pointer to set signalling status + * \return Success or failure + */ +static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status) +{ + *status = FTDM_SIG_STATE_DOWN; + + ftdm_isdn_data_t *isdn_data = span->signal_data; + if (ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { + *status = FTDM_SIG_STATE_UP; + } + return FTDM_SUCCESS; +} + +/** + * \brief Create outgoing channel + * \param ftdmchan Channel to create outgoing call on + * \return Success or failure */ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) { @@ -300,14 +301,12 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call) } /** - * \brief Requests an ISDN channel on a span (outgoing call) - * \param span Span where to get a channel - * \param chan_id Specific channel to get (0 for any) - * \param direction Call direction (inbound, outbound) - * \param caller_data Caller information - * \param ftdmchan Channel to initialise - * \return Success or failure + * \brief Create outgoing channel, let module select the channel to use + * \param span Span to create outgoing call on + * \param caller_data + * \return Success or failure */ +#ifdef __TODO__ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) { Q931mes_Generic *gen = (Q931mes_Generic *) caller_data->raw_data; @@ -347,7 +346,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) BearerCap.ITR = Q931_ITR_64K; /* 64k */ BearerCap.Layer1Ident = 1; BearerCap.UIL1Prot = (codec == FTDM_CODEC_ALAW) ? Q931_UIL1P_G711A : Q931_UIL1P_G711U; /* U-law = 2, A-law = 3 */ - gen->BearerCap = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &BearerCap); + gen->BearerCap = Q931AppendIE(gen, (L3UCHAR *) &BearerCap); /* * Channel ID IE @@ -355,20 +354,20 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) Q931InitIEChanID(&ChanID); ChanID.IntType = FTDM_SPAN_IS_BRI(span) ? 0 : 1; /* PRI = 1, BRI = 0 */ - if(!FTDM_SPAN_IS_NT(span)) { + if (!FTDM_SPAN_IS_NT(span)) { ChanID.PrefExcl = (isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL) ? 0 : 1; /* 0 = preferred, 1 exclusive */ } else { ChanID.PrefExcl = 1; /* always exclusive in NT-mode */ } - if(ChanID.IntType) { + if (ChanID.IntType) { ChanID.InfoChanSel = 1; /* None = 0, See Slot = 1, Any = 3 */ ChanID.ChanMapType = 3; /* B-Chan */ ChanID.ChanSlot = (unsigned char)chan_id; } else { ChanID.InfoChanSel = (unsigned char)chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } - gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID); + gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); /* * Progress IE @@ -377,15 +376,15 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */ Progress.Location = 0; /* 0 = User, 1 = Private Network */ Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */ - gen->ProgInd = Q931AppendIE((L3UCHAR *)gen, (L3UCHAR *)&Progress); + gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *)&Progress); /* * Display IE */ - if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE)) { + if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(span)) { Q931InitIEDisplay(&Display); Display.Size = Display.Size + (unsigned char)strlen(caller_data->cid_name); - gen->Display = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &Display); + gen->Display = Q931AppendIE(gen, (L3UCHAR *) &Display); ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf); ftdm_copy_string((char *)ptrDisplay->Display, caller_data->cid_name, strlen(caller_data->cid_name)+1); } @@ -399,7 +398,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) CallingNum.PresInd = Q931_PRES_ALLOWED; CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED; CallingNum.Size = CallingNum.Size + (unsigned char)strlen(caller_data->cid_num.digits); - gen->CallingNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CallingNum); + gen->CallingNum = Q931AppendIE(gen, (L3UCHAR *) &CallingNum); ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf); ftdm_copy_string((char *)ptrCallingNum->Digit, caller_data->cid_num.digits, strlen(caller_data->cid_num.digits)+1); @@ -410,10 +409,10 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) Q931InitIECalledNum(&CalledNum); CalledNum.TypNum = Q931_TON_UNKNOWN; CalledNum.NumPlanID = Q931_NUMPLAN_E164; - CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->dnis.digits); - gen->CalledNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CalledNum); + CalledNum.Size = CalledNum.Size + (unsigned char)strlen(caller_data->ani.digits); + gen->CalledNum = Q931AppendIE(gen, (L3UCHAR *) &CalledNum); ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf); - ftdm_copy_string((char *)ptrCalledNum->Digit, caller_data->dnis.digits, strlen(caller_data->dnis.digits)+1); + ftdm_copy_string((char *)ptrCalledNum->Digit, caller_data->ani.digits, strlen(caller_data->ani.digits)+1); /* * High-Layer Compatibility IE (Note: Required for AVM FritzBox) @@ -423,28 +422,28 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) HLComp.Interpret = 4; /* only possible value */ HLComp.PresMeth = 1; /* High-layer protocol profile */ HLComp.HLCharID = 1; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */ - gen->HLComp = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &HLComp); + gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp); caller_data->call_state = FTDM_CALLER_STATE_DIALING; - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); - + Q931Rx43(&isdn_data->q931, gen, gen->Size); + isdn_data->outbound_crv[gen->CRV] = caller_data; //isdn_data->channels_local_crv[gen->CRV] = ftdmchan; while(ftdm_running() && caller_data->call_state == FTDM_CALLER_STATE_DIALING) { ftdm_sleep(1); - + if (!--sanity) { caller_data->call_state = FTDM_CALLER_STATE_FAIL; break; } } isdn_data->outbound_crv[gen->CRV] = NULL; - + if (caller_data->call_state == FTDM_CALLER_STATE_SUCCESS) { ftdm_channel_t *new_chan = NULL; int fail = 1; - + new_chan = NULL; if (caller_data->chan_id < FTDM_MAX_CHANNELS_SPAN && caller_data->chan_id <= span->chan_count) { new_chan = span->channels[caller_data->chan_id]; @@ -455,7 +454,7 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) if (new_chan->state == FTDM_CHANNEL_STATE_DOWN || new_chan->state >= FTDM_CHANNEL_STATE_TERMINATING) { int x = 0; ftdm_log(FTDM_LOG_WARNING, "Channel %d:%d ~ %d:%d is already in use waiting for it to become available.\n"); - + for (x = 0; x < 200; x++) { if (!ftdm_test_flag(new_chan, FTDM_CHANNEL_INUSE)) { break; @@ -492,9 +491,9 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) } fail = 0; - } + } } - + if (!fail) { *ftdmchan = new_chan; return FTDM_SUCCESS; @@ -509,13 +508,13 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) //should we be casting here.. or do we need to translate value? cause.Value = (unsigned char) FTDM_CAUSE_WRONG_CALL_STATE; *cause.Diag = '\0'; - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); + Q931Rx43(&isdn_data->q931, gen, gen->Size); if (gen->CRV) { Q931ReleaseCRV(&isdn_data->q931, gen->CRV); } - + if (new_chan) { ftdm_log(FTDM_LOG_CRIT, "Channel is busy\n"); } else { @@ -523,20 +522,13 @@ static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request) } } } - + *ftdmchan = NULL; return FTDM_FAIL; } +#endif /* __TODO__ */ -/** - * \brief Handler for Q931 error - * \param pvt Private structure (span?) - * \param id Error number - * \param p1 ?? - * \param p2 ?? - * \return 0 - */ static L3INT ftdm_isdn_931_err(void *pvt, L3INT id, L3INT p1, L3INT p2) { ftdm_log(FTDM_LOG_ERROR, "ERROR: [%s] [%d] [%d]\n", q931_error_to_name(id), p1, p2); @@ -544,21 +536,218 @@ static L3INT ftdm_isdn_931_err(void *pvt, L3INT id, L3INT p1, L3INT p2) } /** - * \brief Handler for Q931 event message - * \param pvt Span to handle - * \param msg Message string - * \param mlen Message string length - * \return 0 + * \brief The new call event handler + * \note W000t!!! \o/ ;D + * \todo A lot */ -static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) +static void ftdm_isdn_call_event(struct Q931_Call *call, struct Q931_CallEvent *event, void *priv) +{ + Q931_TrunkInfo_t *trunk = NULL; + ftdm_isdn_data_t *isdn_data = NULL; + ftdm_span_t *zspan = NULL; + assert(call); + assert(event); + + trunk = Q931CallGetTrunk(call); + assert(trunk); + + zspan = Q931CallGetPrivate(call); + if (!zspan) { + zspan = priv; + Q931CallSetPrivate(call, zspan); + } + assert(zspan); + + isdn_data = zspan->signal_data; + + if (Q931CallIsGlobal(call)) { + /* + * Global event + */ + + ftdm_log(FTDM_LOG_DEBUG, "Received global event from Q.931\n"); + } + else { + ftdm_channel_t *ftdmchan = NULL; + ftdm_sigmsg_t sig; + int call_crv = Q931CallGetCRV(call); + int type; + + /* + * Call-specific event + */ + ftdm_log(FTDM_LOG_DEBUG, "Received call-specific event from Q.931 for call %d [%hu]\n", Q931CallGetCRV(call), Q931CallGetCRV(call)); + + /* + * Try to get associated zap channel + * and init sigmsg struct if there is one + */ + ftdmchan = Q931CallIsOutgoing(call) ? isdn_data->channels_local_crv[call_crv] : isdn_data->channels_remote_crv[call_crv]; + if (ftdmchan) { + memset(&sig, 0, sizeof(ftdm_sigmsg_t)); + sig.chan_id = ftdmchan->chan_id; + sig.span_id = ftdmchan->span_id; + sig.channel = ftdmchan; + } + + type = Q931CallEventGetType(event); + + if (type == Q931_EVENT_TYPE_CRV) { + + ftdm_log(FTDM_LOG_DEBUG, "\tCRV event\n"); + + switch (Q931CallEventGetId(event)) { + case Q931_EVENT_RELEASE_CRV: + { + /* WARNING contains old interface code, yuck! */ + if (!ftdmchan) { + ftdm_log(FTDM_LOG_DEBUG, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); + return; + } + + if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { + ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d not in DOWN state, cleaning up\n", + ftdmchan->span_id, ftdmchan->chan_id); + + /* + * Send hangup signal to mod_openzap + */ + if (!sig.channel->caller_data.hangup_cause) { + sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; + } + + sig.event_id = FTDM_SIGEVENT_STOP; + isdn_data->sig_cb(&sig); + + /* Release zap channel */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } + return; + } + break; + default: + ftdm_log(FTDM_LOG_ERROR, "Unknown CRV event: %d\n", Q931CallEventGetId(event)); + return; + } + } + else if (type == Q931_EVENT_TYPE_TIMER) { + struct Q931_CallTimerEvent *timer_evt = Q931CallEventGetData(event); + + ftdm_log(FTDM_LOG_DEBUG, "\tTimer event\n"); + assert(timer_evt->id); + + switch (timer_evt->id) { + case Q931_TIMER_T303: + /* + * SETUP timeout + * + * TE-mode: Q931_EVENT_SETUP_CONFIRM (error) + * NT-mode: Q931_EVENT_RELEASE_INDICATION + */ + { + /* WARNING contains old interface code, yuck! */ + if (!ftdmchan) { + ftdm_log(FTDM_LOG_ERROR, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); + return; + } + + ftdm_log(FTDM_LOG_DEBUG, "Call setup failed on channel %d:%d\n", ftdmchan->span_id, ftdmchan->chan_id); + + /* + * Send signal to mod_openzap + */ + sig.channel->caller_data.hangup_cause = FTDM_CAUSE_NETWORK_OUT_OF_ORDER; + + sig.event_id = FTDM_SIGEVENT_STOP; + isdn_data->sig_cb(&sig); + + /* Release zap channel */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + return; + } + break; + + default: + ftdm_log(FTDM_LOG_ERROR, "Unhandled timer event %d\n", timer_evt->id); + } + } + else if (type == Q931_EVENT_TYPE_MESSAGE) { + struct Q931_CallMessageEvent *msg_evt = Q931CallEventGetData(event); + + ftdm_log(FTDM_LOG_DEBUG, "\tMessage event\n"); + assert(msg_evt); + + /* + * Slowly move stuff from the old event handler into this part... + */ + switch (Q931CallEventGetId(event)) { + case Q931_EVENT_SETUP_CONFIRM: + case Q931_EVENT_SETUP_COMPLETE_INDICATION: /* CONNECT */ + { + /* WARNING contains old interface code, yuck! */ + if (!ftdmchan) { + ftdm_log(FTDM_LOG_ERROR, "Call %d [0x%x] not associated to zap channel\n", call_crv, call_crv); + return; + } + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + } + break; + + default: + ftdm_log(FTDM_LOG_DEBUG, "Not yet handled message event %d\n", Q931CallEventGetId(event)); + } + } + else { + ftdm_log(FTDM_LOG_ERROR, "Unknown event type %d\n", type); + } + } +} + +/** + * Copy callednum, readding prefix as needed + */ +static void __isdn_get_number(const char *digits, const int ton, char *buf, int size) +{ + int offset = 0; + + if (!digits || !buf || size <= 0) { + return; + } + + switch (ton) { + case Q931_TON_NATIONAL: + offset = strlen(DEFAULT_NATIONAL_PREFIX); + memcpy(buf, DEFAULT_NATIONAL_PREFIX, offset); + break; + case Q931_TON_INTERNATIONAL: + offset = strlen(DEFAULT_INTERNATIONAL_PREFIX); + memcpy(buf, DEFAULT_INTERNATIONAL_PREFIX, offset); + break; + default: + break; + } + + strncpy(&buf[offset], digits, size - (offset + 1)); + buf[size - 1] = '\0'; +} + +#define isdn_get_number(num, buf) \ + __isdn_get_number((const char *)(num)->Digit, (num)->TypNum, (char *)buf, sizeof(buf)) + + +/** + * \brief The old call event handler (err, call message handler) + * \todo This one must die! + */ +static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic *msg, int mlen) { ftdm_span_t *span = (ftdm_span_t *) pvt; ftdm_isdn_data_t *isdn_data = span->signal_data; Q931mes_Generic *gen = (Q931mes_Generic *) msg; - uint32_t chan_id = 0; + int chan_id = 0; int chan_hunt = 0; ftdm_channel_t *ftdmchan = NULL; - ftdm_caller_data_t *caller_data = NULL; +// ftdm_caller_data_t *caller_data = NULL; if (Q931IsIEPresent(gen->ChanID)) { Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf); @@ -579,9 +768,30 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) assert(span != NULL); assert(isdn_data != NULL); - + + /* + * Support code for the new event handling system + * Remove this as soon as we have the new api to set up calls + */ +#ifdef __OLD__ + if (gen->CRV) { + struct Q931_Call *call; + + call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV); + if (call && !Q931CallGetPrivate(call)) { + ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV); + Q931CallSetPrivate(call, span); + } + } +#else + if (call && !Q931CallGetPrivate(call)) { + ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV); + Q931CallSetPrivate(call, span); + } +#endif ftdm_log(FTDM_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d] CRV: %d (%#hx, CTX: %s)\n", gen->MesType, gen->Size, gen->CRV, gen->CRV, gen->CRVFlag ? "Terminator" : "Originator"); +#ifdef __TODO_OR_REMOVE__ if (gen->CRVFlag && (caller_data = isdn_data->outbound_crv[gen->CRV])) { if (chan_id) { caller_data->chan_id = chan_id; @@ -602,9 +812,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) caller_data->call_state = FTDM_CALLER_STATE_FAIL; break; } - + return 0; } +#endif if (gen->CRVFlag) { ftdmchan = isdn_data->channels_local_crv[gen->CRV]; @@ -629,7 +840,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } break; - case 1: + case 1: { /* change status to "maintenance" */ ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_SUSPENDED); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); @@ -663,7 +874,12 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); } else { uint32_t i; + for (i = 1; i < span->chan_count; i++) { + /* Skip channels that are down and D-Channels (#OpenZAP-39) */ + if (span->channels[i]->state == FTDM_CHANNEL_STATE_DOWN || span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) + continue; + ftdm_set_state_locked((span->channels[i]), FTDM_CHANNEL_STATE_RESTART); } } @@ -698,7 +914,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) sig.channel->caller_data.hangup_cause = (cause) ? cause->Value : FTDM_CAUSE_NORMAL_UNSPECIFIED; sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(ftdmchan->span, &sig); + status = isdn_data->sig_cb(&sig); ftdm_log(FTDM_LOG_DEBUG, "Received %s in state %s, requested hangup for channel %d:%d\n", what, ftdm_channel_state2str(ftdmchan->state), ftdmchan->span_id, chan_id); } @@ -740,17 +956,21 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) } break; case Q931mes_CONNECT: +#if 0 /* Handled by new event code */ { if (ftdmchan) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); +#if 0 /* Auto-Ack is enabled, we actually don't need this */ gen->MesType = Q931mes_CONNECT_ACKNOWLEDGE; gen->CRVFlag = 0; /* outbound */ - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); +#endif } else { ftdm_log(FTDM_LOG_CRIT, "Received Connect with no matching channel %d\n", chan_id); } } +#endif break; case Q931mes_SETUP: { @@ -770,13 +990,13 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) ftdm_channel_state2str(ftdmchan->state)); break; } - + ftdmchan = NULL; /* * Channel selection for incoming calls: */ if (FTDM_SPAN_IS_NT(span) && chan_hunt) { - uint32_t x; + int x; /* * In NT-mode with channel selection "any", @@ -864,14 +1084,21 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) memset(ftdmchan->mod_data, 0, sizeof(ftdm_isdn_bchan_data_t)); } - ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)callingnum->Digit); - ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)callingnum->Digit); - ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)callingnum->Digit); - if (!overlap_dial) { - ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)callednum->Digit); - } + /* copy number readd prefix as needed */ + isdn_get_number(callingnum, ftdmchan->caller_data.cid_num.digits); + isdn_get_number(callingnum, ftdmchan->caller_data.cid_name); + isdn_get_number(callingnum, ftdmchan->caller_data.ani.digits); +// ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)callingnum->Digit); +// ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)callingnum->Digit); +// ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)callingnum->Digit); + if (!overlap_dial) { +// ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)callednum->Digit); + isdn_get_number(callednum, ftdmchan->caller_data.dnis.digits); + } +#ifdef __TODO_OR_REMOVE__ ftdmchan->caller_data.CRV = gen->CRV; +#endif if (cplen > sizeof(ftdmchan->caller_data.raw_data)) { cplen = sizeof(ftdmchan->caller_data.raw_data); } @@ -879,8 +1106,8 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) memcpy(ftdmchan->caller_data.raw_data, msg, cplen); ftdmchan->caller_data.raw_data_len = cplen; fail = 0; - } - } + } + } if (fail) { Q931ie_Cause cause; @@ -894,8 +1121,8 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) //should we be casting here.. or do we need to translate value? cause.Value = (unsigned char)((fail_cause) ? fail_cause : FTDM_CAUSE_WRONG_CALL_STATE); *cause.Diag = '\0'; - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); + Q931Rx43(&isdn_data->q931, gen, gen->Size); if (gen->CRV) { Q931ReleaseCRV(&isdn_data->q931, gen->CRV); @@ -906,7 +1133,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) } else { ftdm_log(FTDM_LOG_CRIT, "Failed to open channel for new setup message\n"); } - + } else { Q931ie_ChanID ChanID; @@ -923,7 +1150,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) } else { ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } - gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID); + gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); if (overlap_dial) { Q931ie_ProgInd progress; @@ -933,17 +1160,17 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) */ progress.IEId = Q931ie_PROGRESS_INDICATOR; progress.Size = sizeof(Q931ie_ProgInd); - progress.CodStand = Q931_CODING_ITU; /* ITU */ + progress.CodStand = Q931_CODING_ITU; /* ITU */ progress.Location = 1; /* private network serving the local user */ progress.ProgDesc = 8; /* call is not end-to-end isdn = 1, in-band information available = 8 */ - gen->ProgInd = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &progress); + gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *) &progress); /* * Send SETUP ACK */ gen->MesType = Q931mes_SETUP_ACKNOWLEDGE; gen->CRVFlag = 1; /* inbound call */ - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALTONE); } else { @@ -998,7 +1225,7 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) } /* TODO: make this more safe with strncat() */ - pos = (int)strlen(ftdmchan->caller_data.dnis.digits); + pos = strlen(ftdmchan->caller_data.dnis.digits); strcat(&ftdmchan->caller_data.dnis.digits[pos], (char *)callednum->Digit); /* update timer */ @@ -1019,61 +1246,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) } break; - case Q931mes_STATUS_ENQUIRY: - { - /* - * !! HACK ALERT !! - * - * Map FreeTDM channel states to Q.931 states - */ - Q931ie_CallState state; - Q931ie_Cause cause; - - gen->MesType = Q931mes_STATUS; - gen->CRVFlag = gen->CRVFlag ? 0 : 1; - - state.CodStand = Q931_CODING_ITU; /* ITU-T */ - state.CallState = Q931_U0; /* Default: Null */ - - cause.IEId = Q931ie_CAUSE; - cause.Size = sizeof(Q931ie_Cause); - cause.CodStand = Q931_CODING_ITU; /* ITU */ - cause.Location = 1; /* private network */ - cause.Recom = 1; /* */ - *cause.Diag = '\0'; - - if(ftdmchan) { - switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_UP: - state.CallState = Q931_U10; /* Active */ - break; - case FTDM_CHANNEL_STATE_RING: - state.CallState = Q931_U6; /* Call present */ - break; - case FTDM_CHANNEL_STATE_DIALING: - state.CallState = Q931_U1; /* Call initiated */ - break; - case FTDM_CHANNEL_STATE_DIALTONE: - state.CallState = Q931_U25; /* Overlap receiving */ - break; - - /* TODO: map missing states */ - - default: - state.CallState = Q931_U0; - } - - cause.Value = 30; /* response to STATUS ENQUIRY */ - } else { - cause.Value = 98; /* */ - } - - gen->CallState = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &state); - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); - } - break; - default: ftdm_log(FTDM_LOG_CRIT, "Received unhandled message %d (%#x)\n", (int)gen->MesType, (int)gen->MesType); break; @@ -1083,17 +1255,10 @@ static L3INT ftdm_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) return 0; } -/** - * \brief Handler for Q921 read event - * \param pvt Span were message is coming from - * \param ind Q921 indication - * \param tei Terminal Endpoint Identifier - * \param msg Message string - * \param mlen Message string length - * \return 0 on success, 1 on failure - */ static int ftdm_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *msg, L2INT mlen) { + ftdm_span_t *span = pvt; + ftdm_isdn_data_t *isdn_data = span->signal_data; int ret, offset = (ind == Q921_DL_DATA) ? 4 : 3; char bb[4096] = ""; @@ -1101,20 +1266,14 @@ static int ftdm_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *ms case Q921_DL_DATA: case Q921_DL_UNIT_DATA: print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb)); -#ifdef HAVE_LIBPCAP - /*Q931ToPcap*/ - if(do_q931ToPcap==1){ - ftdm_span_t *span = (ftdm_span_t *) pvt; - if(writeQ931PacketToPcap(msg + offset, mlen - offset, span->span_id, 1) != FTDM_SUCCESS){ - ftdm_log(FTDM_LOG_WARNING, "Couldn't write Q931 buffer to pcap file!\n"); - } - } - /*Q931ToPcap done*/ + ftdm_log(FTDM_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb); +#ifdef HAVE_PCAP + if (isdn_pcap_capture_l3only(isdn_data)) { + isdn_pcap_write(isdn_data, msg, mlen, (ind == Q921_DL_UNIT_DATA) ? ISDN_PCAP_INCOMING_BCAST : ISDN_PCAP_INCOMING); + } #endif - ftdm_log(FTDM_LOG_DEBUG, "READ %d\n%s\n%s\n\n\n", (int)mlen - offset, LINE, bb); - default: - ret = Q931Rx23(pvt, ind, tei, msg, mlen); + ret = Q931Rx23(&isdn_data->q931, ind, tei, msg, mlen); if (ret != 0) ftdm_log(FTDM_LOG_DEBUG, "931 parse error [%d] [%s]\n", ret, q931_error_to_name(ret)); break; @@ -1123,35 +1282,22 @@ static int ftdm_isdn_921_23(void *pvt, Q921DLMsg_t ind, L2UCHAR tei, L2UCHAR *ms return ((ret >= 0) ? 1 : 0); } -/** - * \brief Handler for Q921 write event - * \param pvt Span were message is coming from - * \param msg Message string - * \param mlen Message string length - * \return 0 on success, -1 on failure - */ static int ftdm_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen) { ftdm_span_t *span = (ftdm_span_t *) pvt; ftdm_size_t len = (ftdm_size_t) mlen; ftdm_isdn_data_t *isdn_data = span->signal_data; -#ifdef IODEBUG - char bb[4096] = ""; - print_hex_bytes(msg, len, bb, sizeof(bb)); - print_bits(msg, (int)len, bb, sizeof(bb), FTDM_ENDIAN_LITTLE, 0); - ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)len, LINE, bb); - -#endif - assert(span != NULL); + +#ifdef HAVE_PCAP + if (isdn_pcap_capture_both(isdn_data)) { + isdn_pcap_write(isdn_data, msg, mlen, ISDN_PCAP_OUTGOING); + } +#endif return ftdm_channel_write(isdn_data->dchan, msg, len, &len) == FTDM_SUCCESS ? 0 : -1; } -/** - * \brief Handler for channel state change - * \param ftdmchan Channel to handle - */ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { Q931mes_Generic *gen = (Q931mes_Generic *) ftdmchan->caller_data.raw_data; @@ -1159,7 +1305,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) ftdm_sigmsg_t sig; ftdm_status_t status; - ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", + ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state)); memset(&sig, 0, sizeof(sig)); @@ -1185,11 +1331,15 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS; - if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { + if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { + int crv = gen->CRV; + + Q931InitMesGeneric(gen); gen->MesType = Q931mes_CALL_PROCEEDING; + gen->CRV = crv; gen->CRVFlag = 1; /* inbound */ if (FTDM_SPAN_IS_NT(ftdmchan->span)) { @@ -1209,10 +1359,10 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) } else { ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } - gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID); + gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); } - Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); } } break; @@ -1229,7 +1379,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_START; - if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { + if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } @@ -1239,7 +1389,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED; sig.event_id = FTDM_SIGEVENT_RESTART; - status = ftdm_span_send_signal(ftdmchan->span, &sig); + status = isdn_data->sig_cb(&sig); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; @@ -1247,7 +1397,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA; - if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { + if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { @@ -1259,7 +1409,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) } gen->MesType = Q931mes_ALERTING; gen->CRVFlag = 1; /* inbound call */ - Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); } } break; @@ -1267,7 +1417,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { sig.event_id = FTDM_SIGEVENT_UP; - if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) { + if ((status = isdn_data->sig_cb(&sig) != FTDM_SUCCESS)) { ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } } else { @@ -1280,7 +1430,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) gen->MesType = Q931mes_CONNECT; gen->BearerCap = 0; gen->CRVFlag = 1; /* inbound call */ - Q931Rx43(&isdn_data->q931, (void *)gen, ftdmchan->caller_data.raw_data_len); + Q931Rx43(&isdn_data->q931, gen, ftdmchan->caller_data.raw_data_len); } } break; @@ -1304,7 +1454,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) /* * Q.931 Setup Message - */ + */ Q931InitMesGeneric(gen); gen->MesType = Q931mes_SETUP; gen->CRVFlag = 0; /* outbound(?) */ @@ -1319,7 +1469,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) BearerCap.ITR = Q931_ITR_64K; /* 64k = 16, Packet mode = 0 */ BearerCap.Layer1Ident = 1; BearerCap.UIL1Prot = (codec == FTDM_CODEC_ALAW) ? 3 : 2; /* U-law = 2, A-law = 3 */ - gen->BearerCap = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &BearerCap); + gen->BearerCap = Q931AppendIE(gen, (L3UCHAR *) &BearerCap); /* * ChannelID IE @@ -1334,7 +1484,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) } else { ChanID.InfoChanSel = (unsigned char)ftdmchan->chan_id & 0x03; /* None = 0, B1 = 1, B2 = 2, Any = 3 */ } - gen->ChanID = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &ChanID); + gen->ChanID = Q931AppendIE(gen, (L3UCHAR *) &ChanID); /* * Progress IE @@ -1343,29 +1493,29 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) Progress.CodStand = Q931_CODING_ITU; /* 0 = ITU */ Progress.Location = 0; /* 0 = User, 1 = Private Network */ Progress.ProgDesc = 3; /* 1 = Not end-to-end ISDN */ - gen->ProgInd = Q931AppendIE((L3UCHAR *)gen, (L3UCHAR *)&Progress); + gen->ProgInd = Q931AppendIE(gen, (L3UCHAR *)&Progress); /* * Display IE */ - if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE)) { + if (!(isdn_data->opts & FTDM_ISDN_OPT_OMIT_DISPLAY_IE) && FTDM_SPAN_IS_NT(ftdmchan->span)) { Q931InitIEDisplay(&Display); Display.Size = Display.Size + (unsigned char)strlen(ftdmchan->caller_data.cid_name); - gen->Display = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &Display); + gen->Display = Q931AppendIE(gen, (L3UCHAR *) &Display); ptrDisplay = Q931GetIEPtr(gen->Display, gen->buf); ftdm_copy_string((char *)ptrDisplay->Display, ftdmchan->caller_data.cid_name, strlen(ftdmchan->caller_data.cid_name)+1); } /* * CallingNum IE - */ + */ Q931InitIECallingNum(&CallingNum); CallingNum.TypNum = ftdmchan->caller_data.ani.type; CallingNum.NumPlanID = Q931_NUMPLAN_E164; CallingNum.PresInd = Q931_PRES_ALLOWED; CallingNum.ScreenInd = Q931_SCREEN_USER_NOT_SCREENED; CallingNum.Size = CallingNum.Size + (unsigned char)strlen(ftdmchan->caller_data.cid_num.digits); - gen->CallingNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CallingNum); + gen->CallingNum = Q931AppendIE(gen, (L3UCHAR *) &CallingNum); ptrCallingNum = Q931GetIEPtr(gen->CallingNum, gen->buf); ftdm_copy_string((char *)ptrCallingNum->Digit, ftdmchan->caller_data.cid_num.digits, strlen(ftdmchan->caller_data.cid_num.digits)+1); @@ -1373,12 +1523,12 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) * CalledNum IE */ Q931InitIECalledNum(&CalledNum); - CalledNum.TypNum = ftdmchan->caller_data.dnis.type; + CalledNum.TypNum = Q931_TON_UNKNOWN; CalledNum.NumPlanID = Q931_NUMPLAN_E164; - CalledNum.Size = CalledNum.Size + (unsigned char)strlen(ftdmchan->caller_data.dnis.digits); - gen->CalledNum = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &CalledNum); + CalledNum.Size = CalledNum.Size + (unsigned char)strlen(ftdmchan->caller_data.ani.digits); + gen->CalledNum = Q931AppendIE(gen, (L3UCHAR *) &CalledNum); ptrCalledNum = Q931GetIEPtr(gen->CalledNum, gen->buf); - ftdm_copy_string((char *)ptrCalledNum->Digit, ftdmchan->caller_data.dnis.digits, strlen(ftdmchan->caller_data.dnis.digits)+1); + ftdm_copy_string((char *)ptrCalledNum->Digit, ftdmchan->caller_data.ani.digits, strlen(ftdmchan->caller_data.ani.digits)+1); /* * High-Layer Compatibility IE (Note: Required for AVM FritzBox) @@ -1388,10 +1538,24 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) HLComp.Interpret = 4; /* only possible value */ HLComp.PresMeth = 1; /* High-layer protocol profile */ HLComp.HLCharID = Q931_HLCHAR_TELEPHONY; /* Telephony = 1, Fax G2+3 = 4, Fax G4 = 65 (Class I)/ 68 (Class II or III) */ /* TODO: make accessible from user layer */ - gen->HLComp = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &HLComp); + gen->HLComp = Q931AppendIE(gen, (L3UCHAR *) &HLComp); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); isdn_data->channels_local_crv[gen->CRV] = ftdmchan; + + /* + * Support code for the new event handling system + * Remove this as soon as we have the new api to set up calls + */ + if (gen->CRV) { + struct Q931_Call *call; + + call = Q931GetCallByCRV(&isdn_data->q931, gen->CRV); + if (call) { + ftdm_log(FTDM_LOG_DEBUG, "Storing reference to current span in call %d [0x%x]\n", gen->CRV, gen->CRV); + Q931CallSetPrivate(call, ftdmchan->span); + } + } } break; case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: @@ -1400,7 +1564,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) if(ftdmchan->last_state == FTDM_CHANNEL_STATE_HANGUP) { gen->MesType = Q931mes_RELEASE_COMPLETE; - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); } ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } @@ -1433,8 +1597,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) //cause.Value = (unsigned char) FTDM_CAUSE_UNALLOCATED; cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; *cause.Diag = '\0'; - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); + Q931Rx43(&isdn_data->q931, gen, gen->Size); /* we're done, release channel */ //ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); @@ -1448,8 +1612,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; *cause.Diag = '\0'; - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size); + gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); + Q931Rx43(&isdn_data->q931, gen, gen->Size); /* this will be triggered by the RELEASE_COMPLETE reply */ /* ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); */ @@ -1462,8 +1626,8 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) cause.Value = (unsigned char) ftdmchan->caller_data.hangup_cause; *cause.Diag = '\0'; - gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); - Q931Rx43(&isdn_data->q931, (L3UCHAR *) gen, gen->Size); + gen->Cause = Q931AppendIE(gen, (L3UCHAR *) &cause); + Q931Rx43(&isdn_data->q931, gen, gen->Size); } } break; @@ -1472,20 +1636,16 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) ftdm_log(FTDM_LOG_DEBUG, "Terminating: Direction %s\n", ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? "Outbound" : "Inbound"); sig.event_id = FTDM_SIGEVENT_STOP; - status = ftdm_span_send_signal(ftdmchan->span, &sig); + status = isdn_data->sig_cb(&sig); gen->MesType = Q931mes_RELEASE; gen->CRVFlag = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? 0 : 1; - Q931Rx43(&isdn_data->q931, (void *)gen, gen->Size); + Q931Rx43(&isdn_data->q931, gen, gen->Size); } default: break; } } -/** - * \brief Checks current state on a span - * \param span Span to check status on - */ static __inline__ void check_state(ftdm_span_t *span) { if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { @@ -1503,56 +1663,79 @@ static __inline__ void check_state(ftdm_span_t *span) } } -/** - * \brief Processes FreeTDM event on a span - * \param span Span to process event on - * \param event Event to process - * \return Success or failure - */ + static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) { - ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", + ftdm_isdn_data_t *isdn_data = span->signal_data; + ftdm_alarm_flag_t alarmbits; + ftdm_sigmsg_t sig; + + memset(&sig, 0, sizeof(sig)); + sig.chan_id = event->channel->chan_id; + sig.span_id = event->channel->span_id; + sig.channel = event->channel; + + ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d:%d] STATE [%s]\n", ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); switch(event->enum_id) { case FTDM_OOB_ALARM_TRAP: { + sig.event_id = FTDM_OOB_ALARM_TRAP; if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) { - if (event->channel->type == FTDM_CHAN_TYPE_B) { - ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); - } + ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); } - - ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - - - ftdm_channel_get_alarms(event->channel); - ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n", - event->channel->span_id, event->channel->chan_id, - event->channel->physical_span_id, event->channel->physical_chan_id, + ftdm_channel_get_alarms(event->channel, &alarmbits); + isdn_data->sig_cb(&sig); + ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms [%s]\n", + event->channel->span_id, event->channel->chan_id, + event->channel->physical_span_id, event->channel->physical_chan_id, event->channel->last_error); } break; case FTDM_OOB_ALARM_CLEAR: { - - ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id, - event->channel->physical_span_id, event->channel->physical_chan_id); - + sig.event_id = FTDM_OOB_ALARM_CLEAR; ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel); + ftdm_channel_get_alarms(event->channel, &alarmbits); + isdn_data->sig_cb(&sig); } break; +#ifdef __BROKEN_BY_FREETDM_CONVERSION__ + case FTDM_OOB_DTMF: /* Taken from ozmod_analog, minus the CALLWAITING state handling */ + { + const char * digit_str = (const char *)event->data; + + if(digit_str) { + fio_event_cb_t event_callback = NULL; + + ftdm_channel_queue_dtmf(event->channel, digit_str); + if (span->event_callback) { + event_callback = span->event_callback; + } else if (event->channel->event_callback) { + event_callback = event->channel->event_callback; + } + + if (event_callback) { + event->channel->event_header.channel = event->channel; + event->channel->event_header.e_type = FTDM_EVENT_DTMF; + event->channel->event_header.data = (void *)digit_str; + event_callback(event->channel, &event->channel->event_header); + event->channel->event_header.e_type = FTDM_EVENT_NONE; + event->channel->event_header.data = NULL; + } + ftdm_safe_free(event->data); + } + } + break; +#endif } return FTDM_SUCCESS; } -/** - * \brief Checks for events on a span - * \param span Span to check for events - */ + static __inline__ void check_events(ftdm_span_t *span) { ftdm_status_t status; @@ -1583,12 +1766,7 @@ static __inline__ void check_events(ftdm_span_t *span) } } -/** - * \brief Retrieves tone generation output to be sent - * \param ts Teletone generator - * \param map Tone map - * \return -1 on error, 0 on success - */ + static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) { ftdm_buffer_t *dt_buffer = ts->user_data; @@ -1602,20 +1780,14 @@ static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map return 0; } -/** - * \brief Main thread function for tone generation on a span - * \param me Current thread - * \param obj Span to generate tones on - */ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) { ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_isdn_data_t *isdn_data = span->signal_data; ftdm_buffer_t *dt_buffer = NULL; - teletone_generation_session_t ts = {{{{0}}}}; + teletone_generation_session_t ts = {{{{0}}}};; unsigned char frame[1024]; - uint32_t x; - int interval = 0; + int x, interval; int offset = 0; ftdm_log(FTDM_LOG_DEBUG, "ISDN tones thread starting.\n"); @@ -1646,7 +1818,7 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj) ts.duration = ts.rate; /* main loop */ - while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_TONES_RUNNING) && !ftdm_test_flag(isdn_data, FTDM_ISDN_STOP)) { + while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_wait_flag_t flags; ftdm_status_t status; int last_chan_state = 0; @@ -1798,11 +1970,6 @@ done: return NULL; } -/** - * \brief Main thread function for an ISDN span - * \param me Current thread - * \param obj Span to monitor - */ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) { ftdm_span_t *span = (ftdm_span_t *) obj; @@ -1812,15 +1979,16 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) int errs = 0; #ifdef WIN32 - timeBeginPeriod(1); + timeBeginPeriod(1); #endif ftdm_log(FTDM_LOG_DEBUG, "ISDN thread starting.\n"); ftdm_set_flag(isdn_data, FTDM_ISDN_RUNNING); Q921Start(&isdn_data->q921); + Q931Start(&isdn_data->q931); - while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING) && !ftdm_test_flag(isdn_data, FTDM_ISDN_STOP)) { + while(ftdm_running() && ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_wait_flag_t flags = FTDM_READ; ftdm_status_t status = ftdm_channel_wait(isdn_data->dchan, &flags, 100); @@ -1852,20 +2020,13 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) { errs = 0; if (flags & FTDM_READ) { - - if (ftdm_test_flag(isdn_data->dchan, FTDM_CHANNEL_SUSPENDED)) { - ftdm_clear_flag_all(span, FTDM_CHANNEL_SUSPENDED); - } len = sizeof(frame); if (ftdm_channel_read(isdn_data->dchan, frame, &len) == FTDM_SUCCESS) { -#ifdef IODEBUG - char bb[4096] = ""; - print_hex_bytes(frame, len, bb, sizeof(bb)); - - print_bits(frame, (int)len, bb, sizeof(bb), FTDM_ENDIAN_LITTLE, 0); - ftdm_log(FTDM_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)len, LINE, bb); +#ifdef HAVE_PCAP + if (isdn_pcap_capture_both(isdn_data)) { + isdn_pcap_write(isdn_data, frame, len, ISDN_PCAP_INCOMING); + } #endif - Q921QueueHDLCFrame(&isdn_data->q921, frame, (int)len); Q921Rx12(&isdn_data->q921); } @@ -1876,45 +2037,28 @@ static void *ftdm_isdn_run(ftdm_thread_t *me, void *obj) break; } } - - done: + +done: ftdm_channel_close(&isdn_data->dchans[0]); ftdm_channel_close(&isdn_data->dchans[1]); ftdm_clear_flag(isdn_data, FTDM_ISDN_RUNNING); #ifdef WIN32 - timeEndPeriod(1); + timeEndPeriod(1); +#endif +#ifdef HAVE_PCAP + if (isdn_pcap_is_open(isdn_data)) { + isdn_pcap_close(isdn_data); + } #endif - ftdm_log(FTDM_LOG_DEBUG, "ISDN thread ended.\n"); return NULL; } -/** - * \brief FreeTDM ISDN signaling module initialisation - * \return Success - */ -static FIO_SIG_LOAD_FUNCTION(ftdm_isdn_init) -{ - Q931Initialize(); - - Q921SetGetTimeCB(ftdm_time_now); - Q931SetGetTimeCB(ftdm_time_now); - - return FTDM_SUCCESS; -} - -/** - * \brief Receives a Q931 indication message - * \param pvt Span were message is coming from - * \param ind Q931 indication - * \param tei Terminal Endpoint Identifier - * \param msg Message string - * \param mlen Message string length - * \return 0 on success - */ static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3INT mlen) { + ftdm_span_t *span = pvt; + ftdm_isdn_data_t *isdn_data = span->signal_data; int offset = 4; char bb[4096] = ""; @@ -1924,16 +2068,6 @@ static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3I case Q921_DL_DATA: print_hex_bytes(msg + offset, mlen - offset, bb, sizeof(bb)); -#ifdef HAVE_LIBPCAP - /*Q931ToPcap*/ - if(do_q931ToPcap==1){ - ftdm_span_t *span = (ftdm_span_t *) pvt; - if(writeQ931PacketToPcap(msg + offset, mlen - offset, span->span_id, 0) != FTDM_SUCCESS){ - ftdm_log(FTDM_LOG_WARNING, "Couldn't write Q931 buffer to pcap file!\n"); - } - } - /*Q931ToPcap done*/ -#endif ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)mlen - offset, LINE, bb); break; @@ -1941,17 +2075,14 @@ static int q931_rx_32(void *pvt, Q921DLMsg_t ind, L3UCHAR tei, L3UCHAR *msg, L3I break; } - return Q921Rx32(pvt, ind, tei, msg, mlen); +#ifdef HAVE_PCAP + if (isdn_pcap_capture_l3only(isdn_data)) { + isdn_pcap_write(isdn_data, msg, mlen, ISDN_PCAP_OUTGOING); + } +#endif + return Q921Rx32(&isdn_data->q921, ind, tei, msg, mlen); } -/** - * \brief Logs Q921 message - * \param pvt Span were message is coming from - * \param level Q921 log level - * \param msg Message string - * \param size Message string length - * \return 0 - */ static int ftdm_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT size) { ftdm_span_t *span = (ftdm_span_t *) pvt; @@ -1960,14 +2091,6 @@ static int ftdm_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT return 0; } -/** - * \brief Logs Q931 message - * \param pvt Span were message is coming from - * \param level Q931 log level - * \param msg Message string - * \param size Message string length - * \return 0 - */ static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, char *msg, L3INT size) { ftdm_span_t *span = (ftdm_span_t *) pvt; @@ -1975,9 +2098,7 @@ static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, char *msg, L3IN ftdm_log("Span", "Q.931", span->span_id, (int)level, "%s", msg); return 0; } -/** - * \brief ISDN state map - */ + static ftdm_state_map_t isdn_state_map = { { { @@ -2002,7 +2123,7 @@ static ftdm_state_map_t isdn_state_map = { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END} + {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_DOWN, FTDM_END} }, { ZSD_OUTBOUND, @@ -2076,7 +2197,7 @@ static ftdm_state_map_t isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END}, }, { @@ -2085,17 +2206,11 @@ static ftdm_state_map_t isdn_state_map = { {FTDM_CHANNEL_STATE_UP, FTDM_END}, {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, }, - - } }; /** - * \brief Stops an ISDN span - * \param span Span to halt - * \return Success - * - * Sets a stop flag and waits for the threads to end + * \brief Stop signalling on span */ static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) { @@ -2104,9 +2219,9 @@ static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) if (!ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { return FTDM_FAIL; } - + ftdm_set_flag(isdn_data, FTDM_ISDN_STOP); - + while(ftdm_test_flag(isdn_data, FTDM_ISDN_RUNNING)) { ftdm_sleep(100); } @@ -2116,15 +2231,10 @@ static ftdm_status_t ftdm_isdn_stop(ftdm_span_t *span) } return FTDM_SUCCESS; - } /** - * \brief Starts an ISDN span - * \param span Span to halt - * \return Success or failure - * - * Launches a thread to monitor the span and a thread to generate tones on the span + * \brief Start signalling on span */ static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span) { @@ -2148,19 +2258,46 @@ static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span) return ret; } -/** - * \brief Parses an option string to flags - * \param in String to parse for configuration options - * \return Flags - */ + +/*###################################################################* + * (text) value parsing / translation + *###################################################################*/ + +static int32_t parse_loglevel(const char *level) +{ + if (!level) { + return -1; + } + + if (!strcasecmp(level, "debug")) { + return FTDM_LOG_LEVEL_DEBUG; + } else if (!strcasecmp(level, "info")) { + return FTDM_LOG_LEVEL_INFO; + } else if (!strcasecmp(level, "notice")) { + return FTDM_LOG_LEVEL_NOTICE; + } else if (!strcasecmp(level, "warning")) { + return FTDM_LOG_LEVEL_WARNING; + } else if (!strcasecmp(level, "error")) { + return FTDM_LOG_LEVEL_ERROR; + } else if (!strcasecmp(level, "alert")) { + return FTDM_LOG_LEVEL_ALERT; + } else if (!strcasecmp(level, "crit")) { + return FTDM_LOG_LEVEL_CRIT; + } else if (!strcasecmp(level, "emerg")) { + return FTDM_LOG_LEVEL_EMERG; + } else { + return -1; + } +} + static uint32_t parse_opts(const char *in) { uint32_t flags = 0; - + if (!in) { return 0; } - + if (strstr(in, "suggest_channel")) { flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL; } @@ -2176,17 +2313,259 @@ static uint32_t parse_opts(const char *in) return flags; } +static uint32_t parse_dialect(const char *in) +{ + if (!in) { + return Q931_Dialect_Count; + } + +#if __UNSUPPORTED__ + if (!strcasecmp(in, "national")) { + return Q931_Dialect_National; + } + if (!strcasecmp(in, "dms")) { + return Q931_Dialect_DMS; + } +#endif + if (!strcasecmp(in, "5ess")) { + return Q931_Dialect_5ESS; + } + if (!strcasecmp(in, "dss1")) { + return Q931_Dialect_DSS1; + } + if (!strcasecmp(in, "q931")) { + return Q931_Dialect_Q931; + } + return Q931_Dialect_Count; +} + + +/*###################################################################* + * API commands + *###################################################################*/ + +static const char isdn_api_usage[] = +#ifdef HAVE_PCAP + "isdn capture [q931only]\n" + "isdn capture \n" +#endif + "isdn loglevel \n" + "isdn dump calls\n" + "isdn help"; + + /** - * \brief Initialises an ISDN span from configuration variables - * \param span Span to configure - * \param sig_cb Callback function for event signals - * \param ap List of configuration variables - * \return Success or failure + * isdn_api */ -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) +static FIO_API_FUNCTION(isdn_api) +{ + char *mycmd = NULL, *argv[10] = { 0 }; + int argc = 0; + + if (data) { + mycmd = strdup(data); + argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (!argc || !strcasecmp(argv[0], "help")) { + stream->write_function(stream, "%s\n", isdn_api_usage); + goto done; + } + else if (!strcasecmp(argv[0], "dump")) { + ftdm_isdn_data_t *isdn_data = NULL; + ftdm_span_t *span = NULL; + int span_id = 0; + + /* dump calls */ + + if (argc < 3) { + stream->write_function(stream, "-ERR not enough arguments.\n"); + goto done; + } + + span_id = atoi(argv[1]); + + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { + isdn_data = span->signal_data; + } else { + stream->write_function(stream, "-ERR invalid span.\n"); + goto done; + } + + if (!strcasecmp(argv[2], "calls")) { + /* dump all calls to log */ + Q931DumpAllCalls(&isdn_data->q931); + stream->write_function(stream, "+OK call information dumped to log\n"); + goto done; + } + } + else if (!strcasecmp(argv[0], "loglevel")) { + ftdm_isdn_data_t *isdn_data = NULL; + ftdm_span_t *span = NULL; + int span_id = 0; + int layer = 0; + int level = 0; + + /* loglevel [level] */ + + if (argc < 3) { + stream->write_function(stream, "-ERR not enough arguments.\n"); + goto done; + } + + span_id = atoi(argv[1]); + + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { + isdn_data = span->signal_data; + } else { + stream->write_function(stream, "-ERR invalid span.\n"); + goto done; + } + + if (!strcasecmp(argv[2], "q921")) { + layer = 0x01; + } else if(!strcasecmp(argv[2], "q931")) { + layer = 0x02; + } else if (!strcasecmp(argv[2], "all")) { + layer = 0x03; + } else { + stream->write_function(stream, "-ERR invalid layer\n"); + goto done; + } + + if (argc > 3) { + /* set loglevel */ + if ((level = parse_loglevel(argv[3])) < 0) { + stream->write_function(stream, "-ERR invalid loglevel\n"); + goto done; + } + + if (layer & 0x01) { /* q921 */ + Q921SetLogLevel(&isdn_data->q921, (Q921LogLevel_t)level); + } + if (layer & 0x02) { /* q931 */ + Q931SetLogLevel(&isdn_data->q931, (Q931LogLevel_t)level); + } + stream->write_function(stream, "+OK loglevel set"); + } else { + /* get loglevel */ + if (layer & 0x01) { + stream->write_function(stream, "Q.921 loglevel: %s\n", + Q921GetLogLevelName(&isdn_data->q921)); + } + if (layer & 0x02) { + stream->write_function(stream, "Q.931 loglevel: %s\n", + Q931GetLogLevelName(&isdn_data->q931)); + } + stream->write_function(stream, "+OK"); + } + goto done; + } +#ifdef HAVE_PCAP + else if (!strcasecmp(argv[0], "capture")) { + ftdm_isdn_data_t *isdn_data = NULL; + ftdm_span_t *span = NULL; + int span_id = 0; + + /* capture [q931only] */ + /* capture */ + + if (argc < 3) { + stream->write_function(stream, "-ERR not enough arguments.\n"); + goto done; + } + + span_id = atoi(argv[1]); + + if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) { + isdn_data = span->signal_data; + } else { + stream->write_function(stream, "-ERR invalid span.\n"); + goto done; + } + + if (!strcasecmp(argv[2], "start")) { + char *filename = NULL; + + if (argc < 4) { + stream->write_function(stream, "-ERR not enough parameters.\n"); + goto done; + } + + if (isdn_pcap_is_open(isdn_data)) { + stream->write_function(stream, "-ERR capture is already running.\n"); + goto done; + } + + filename = argv[3]; + + if (isdn_pcap_open(isdn_data, filename) != FTDM_SUCCESS) { + stream->write_function(stream, "-ERR failed to open capture file.\n"); + goto done; + } + + if (argc > 4 && !strcasecmp(argv[4], "q931only")) { + isdn_data->flags |= FTDM_ISDN_CAPTURE_L3ONLY; + } + isdn_pcap_start(isdn_data); + + stream->write_function(stream, "+OK capture started.\n"); + goto done; + } + else if(!strcasecmp(argv[2], "stop")) { + + if (!isdn_pcap_is_open(isdn_data)) { + stream->write_function(stream, "-ERR capture is not running.\n"); + goto done; + } + + isdn_pcap_stop(isdn_data); + isdn_pcap_close(isdn_data); + + stream->write_function(stream, "+OK capture stopped.\n"); + goto done; + } + else if(!strcasecmp(argv[2], "suspend")) { + + if (!isdn_pcap_is_open(isdn_data)) { + stream->write_function(stream, "-ERR capture is not running.\n"); + goto done; + } + isdn_pcap_stop(isdn_data); + + stream->write_function(stream, "+OK capture suspended.\n"); + goto done; + } + else if(!strcasecmp(argv[2], "resume")) { + + if (!isdn_pcap_is_open(isdn_data)) { + stream->write_function(stream, "-ERR capture is not running.\n"); + goto done; + } + isdn_pcap_start(isdn_data); + + stream->write_function(stream, "+OK capture resumed.\n"); + goto done; + } + else { + stream->write_function(stream, "-ERR wrong action.\n"); + goto done; + } + } +#endif + else { + stream->write_function(stream, "-ERR invalid command.\n"); + } +done: + ftdm_safe_free(mycmd); + + return FTDM_SUCCESS; +} + +static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span) { uint32_t i, x = 0; - ftdm_channel_t *dchans[2] = {0}; + ftdm_channel_t *dchans[2] = { 0 }; ftdm_isdn_data_t *isdn_data; const char *tonemap = "us"; char *var, *val; @@ -2194,40 +2573,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) int32_t digit_timeout = 0; int q921loglevel = -1; int q931loglevel = -1; -#ifdef HAVE_LIBPCAP - int q931topcap = -1; /*Q931ToPcap*/ - int openPcap = 0; /*Flag: open Pcap file please*/ -#endif if (span->signal_type) { -#ifdef HAVE_LIBPCAP - /*Q931ToPcap: Get the content of the q931topcap and pcapfilename args given by mod_freetdm */ - while((var = va_arg(ap, char *))) { - if (!strcasecmp(var, "q931topcap")) { - q931topcap = va_arg(ap, int); - if(q931topcap==1) { - /*PCAP on*/; - openPcap=1; - } else if (q931topcap==0) { - /*PCAP off*/ - if (closePcapFile() != FTDM_SUCCESS) return FTDM_FAIL; - do_q931ToPcap=0; - return FTDM_SUCCESS; - } - } - if (!strcasecmp(var, "pcapfilename")) { - /*Put filename into global var*/ - pcapfn = va_arg(ap, char*); - } - } - /*We know now, that user wants to enable Q931ToPcap and what file name he wants, so open it please*/ - if(openPcap==1){ - if(openPcapFile() != FTDM_SUCCESS) return FTDM_FAIL; - do_q931ToPcap=1; - return FTDM_SUCCESS; - } - /*Q931ToPcap done*/ -#endif snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type); return FTDM_FAIL; } @@ -2236,34 +2583,33 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type)); span->trunk_type = FTDM_TRUNK_T1; } - + for(i = 1; i <= span->chan_count; i++) { if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { if (x > 1) { snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!"); return FTDM_FAIL; - } else { - if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id); - dchans[x]->state = FTDM_CHANNEL_STATE_UP; - x++; - } + } + + if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id); + dchans[x]->state = FTDM_CHANNEL_STATE_UP; + x++; } } } - if (!x) { snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!"); return FTDM_FAIL; } - isdn_data = ftdm_malloc(sizeof(*isdn_data)); + isdn_data = malloc(sizeof(*isdn_data)); assert(isdn_data != NULL); memset(isdn_data, 0, sizeof(*isdn_data)); - + isdn_data->mode = Q931_TE; - dialect = Q931_Dialect_National; - + dialect = Q931_Dialect_Q931; + while((var = va_arg(ap, char *))) { if (!strcasecmp(var, "mode")) { if (!(val = va_arg(ap, char *))) { @@ -2274,8 +2620,9 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) if (!(val = va_arg(ap, char *))) { break; } - dialect = q931_str2Q931Dialect_type(val); + dialect = parse_dialect(val); if (dialect == Q931_Dialect_Count) { + snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val); return FTDM_FAIL; } } else if (!strcasecmp(var, "opts")) { @@ -2314,7 +2661,6 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) } } - if (!digit_timeout) { digit_timeout = DEFAULT_DIGIT_TIMEOUT; } @@ -2327,7 +2673,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) if (isdn_data->mode == Q931_NT) { ftdm_isdn_bchan_data_t *data; - data = ftdm_malloc((span->chan_count - 1) * sizeof(ftdm_isdn_bchan_data_t)); + data = malloc(span->chan_count * sizeof(ftdm_isdn_bchan_data_t)); if (!data) { return FTDM_FAIL; } @@ -2339,15 +2685,13 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) } } } - - span->start = ftdm_isdn_start; - span->stop = ftdm_isdn_stop; - span->signal_cb = sig_cb; + + isdn_data->sig_cb = sig_cb; isdn_data->dchans[0] = dchans[0]; isdn_data->dchans[1] = dchans[1]; - isdn_data->dchan = isdn_data->dchans[0]; + isdn_data->dchan = isdn_data->dchans[0]; isdn_data->digit_timeout = digit_timeout; - + Q921_InitTrunk(&isdn_data->q921, 0, 0, @@ -2357,55 +2701,104 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_isdn_configure_span) ftdm_isdn_921_21, (Q921Tx23CB_t)ftdm_isdn_921_23, span, - &isdn_data->q931); + span); - Q921SetLogCB(&isdn_data->q921, &ftdm_isdn_q921_log, isdn_data); + Q921SetLogCB(&isdn_data->q921, &ftdm_isdn_q921_log, span); Q921SetLogLevel(&isdn_data->q921, (Q921LogLevel_t)q921loglevel); - - Q931Api_InitTrunk(&isdn_data->q931, + + Q931InitTrunk(&isdn_data->q931, dialect, isdn_data->mode, span->trunk_type, ftdm_isdn_931_34, (Q931Tx32CB_t)q931_rx_32, ftdm_isdn_931_err, - &isdn_data->q921, + span, span); - Q931SetLogCB(&isdn_data->q931, &ftdm_isdn_q931_log, isdn_data); + Q931SetLogCB(&isdn_data->q931, &ftdm_isdn_q931_log, span); Q931SetLogLevel(&isdn_data->q931, (Q931LogLevel_t)q931loglevel); - isdn_data->q931.autoRestartAck = 1; - isdn_data->q931.autoConnectAck = 0; - isdn_data->q931.autoServiceAck = 1; - span->signal_data = isdn_data; - span->signal_type = FTDM_SIGTYPE_ISDN; + /* Register new event hander CB */ + Q931SetCallEventCB(&isdn_data->q931, ftdm_isdn_call_event, span); + + /* TODO: hmm, maybe drop the "Trunk" prefix */ + Q931TrunkSetAutoRestartAck(&isdn_data->q931, 1); + Q931TrunkSetAutoConnectAck(&isdn_data->q931, 1); + Q931TrunkSetAutoServiceAck(&isdn_data->q931, 1); + Q931TrunkSetStatusEnquiry(&isdn_data->q931, 0); + + span->state_map = &isdn_state_map; + span->signal_data = isdn_data; + span->signal_type = FTDM_SIGTYPE_ISDN; + span->start = ftdm_isdn_start; + span->stop = ftdm_isdn_stop; span->outgoing_call = isdn_outgoing_call; + span->get_channel_sig_status = isdn_get_channel_sig_status; + span->get_span_sig_status = isdn_get_span_sig_status; + +#ifdef __TODO__ if ((isdn_data->opts & FTDM_ISDN_OPT_SUGGEST_CHANNEL)) { span->channel_request = isdn_channel_request; - ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID); + span->flags |= FTDM_SPAN_SUGGEST_CHAN_ID; } - span->state_map = &isdn_state_map; - +#endif ftdm_span_load_tones(span, tonemap); return FTDM_SUCCESS; } /** - * \brief FreeTDM ISDN signaling module definition + * ISDN module io interface + * \note This is really ugly... */ -EX_DECLARE_DATA ftdm_module_t ftdm_module = { - "isdn", - NULL, - close_pcap, - ftdm_isdn_init, - ftdm_isdn_configure_span, - NULL +static ftdm_io_interface_t isdn_interface = { + .name = "isdn", + .api = isdn_api }; +/** + * \brief ISDN module io interface init callback + */ +static FIO_IO_LOAD_FUNCTION(isdn_io_load) +{ + assert(fio != NULL); + *fio = &isdn_interface; + + return FTDM_SUCCESS; +} + +/** + * \brief ISDN module load callback + */ +static FIO_SIG_LOAD_FUNCTION(isdn_load) +{ + Q931Initialize(); + + Q921SetGetTimeCB(ftdm_time_now); + Q931SetGetTimeCB(ftdm_time_now); + + return FTDM_SUCCESS; +} + +/** + * \brief ISDN module shutdown callback + */ +static FIO_SIG_UNLOAD_FUNCTION(isdn_unload) +{ + return FTDM_SUCCESS; +}; + +ftdm_module_t ftdm_module = { + .name = "isdn", + .io_load = isdn_io_load, + .io_unload = NULL, + .sig_load = isdn_load, + .sig_unload = isdn_unload, + .sig_configure = isdn_configure_span +}; /* For Emacs: * Local Variables: @@ -2415,5 +2808,5 @@ EX_DECLARE_DATA ftdm_module_t ftdm_module = { * c-basic-offset:4 * End: * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: */ diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftdm_isdn.h b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h similarity index 83% rename from libs/freetdm/src/ftmod/ftmod_isdn/ftdm_isdn.h rename to libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h index 7168abeb3b..95eee90887 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftdm_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.h @@ -1,23 +1,23 @@ /* * Copyright (c) 2007, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -33,7 +33,6 @@ #ifndef FTDM_ISDN_H #define FTDM_ISDN_H -#include "freetdm.h" #define DEFAULT_DIGIT_TIMEOUT 10000 /* default overlap timeout: 10 seconds */ @@ -42,17 +41,23 @@ typedef enum { FTDM_ISDN_OPT_NONE = 0, FTDM_ISDN_OPT_SUGGEST_CHANNEL = (1 << 0), FTDM_ISDN_OPT_OMIT_DISPLAY_IE = (1 << 1), /*!< Do not send Caller name in outgoing SETUP message (= Display IE) */ - FTDM_ISDN_OPT_DISABLE_TONES = (1 << 2), /*!< Disable tone generating thread (NT mode) */ + FTDM_ISDN_OPT_DISABLE_TONES = (1 << 2), /*!< Disable tone generating thread (NT mode) */ FTDM_ISDN_OPT_MAX = (2 << 0) } ftdm_isdn_opts_t; typedef enum { - FTDM_ISDN_RUNNING = (1 << 0), - FTDM_ISDN_TONES_RUNNING = (1 << 1), - FTDM_ISDN_STOP = (1 << 2) + FTDM_ISDN_RUNNING = (1 << 0), + FTDM_ISDN_TONES_RUNNING = (1 << 1), + FTDM_ISDN_STOP = (1 << 2), + + FTDM_ISDN_CAPTURE = (1 << 3), + FTDM_ISDN_CAPTURE_L3ONLY = (1 << 4) } ftdm_isdn_flag_t; +#ifdef HAVE_PCAP +struct pcap_context; +#endif struct ftdm_isdn_data { Q921Data_t q921; @@ -60,6 +65,7 @@ struct ftdm_isdn_data { ftdm_channel_t *dchan; ftdm_channel_t *dchans[2]; struct ftdm_sigmsg sigmsg; + fio_signal_cb_t sig_cb; uint32_t flags; int32_t mode; int32_t digit_timeout; @@ -67,6 +73,9 @@ struct ftdm_isdn_data { ftdm_caller_data_t *outbound_crv[32768]; ftdm_channel_t *channels_local_crv[32768]; ftdm_channel_t *channels_remote_crv[32768]; +#ifdef HAVE_PCAP + struct pcap_context *pcap; +#endif }; typedef struct ftdm_isdn_data ftdm_isdn_data_t; @@ -75,7 +84,7 @@ typedef struct ftdm_isdn_data ftdm_isdn_data_t; /* b-channel private data */ struct ftdm_isdn_bchan_data { - L2ULONG digit_timeout; + int32_t digit_timeout; }; typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t; @@ -91,6 +100,6 @@ typedef struct ftdm_isdn_bchan_data ftdm_isdn_bchan_data_t; * c-basic-offset:4 * End: * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab: */ diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ozmod_isdn.2005.vcproj b/libs/freetdm/src/ftmod/ftmod_isdn/ozmod_isdn.2005.vcproj deleted file mode 100644 index 5c8d2efc0f..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ozmod_isdn.2005.vcproj +++ /dev/null @@ -1,316 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index a7135aab0d..036e80891c 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -1,23 +1,23 @@ /* * Copyright (c) 2007, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -30,10 +30,13 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - #include "private/ftdm_core.h" #include "ftmod_libpri.h" +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) +#endif + /** * \brief Unloads libpri IO module * \return Success @@ -140,100 +143,84 @@ static void s_pri_message(char *s) static void s_pri_message(struct pri *pri, char *s) #endif { - ftdm_log(FTDM_LOG_DEBUG, "%s", s); + ftdm_log(FTDM_LOG_DEBUG, "%s", s); } -/** - * \brief Parses an option string to flags - * \param in String to parse for configuration options - * \return Flags - */ -static uint32_t parse_opts(const char *in) -{ - uint32_t flags = 0; - - if (!in) { - return 0; - } - - if (strstr(in, "suggest_channel")) { - flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL; - } - - if (strstr(in, "omit_display")) { - flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE; - } - - if (strstr(in, "omit_redirecting_number")) { - flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE; - } +static const struct ftdm_libpri_debug { + const char *name; + const int flags; +} ftdm_libpri_debug[] = { + { "q921_raw", PRI_DEBUG_Q921_RAW }, + { "q921_dump", PRI_DEBUG_Q921_DUMP }, + { "q921_state", PRI_DEBUG_Q921_STATE }, + { "q921_all", (PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE) }, - return flags; -} + { "q931_dump", PRI_DEBUG_Q931_DUMP }, + { "q931_state", PRI_DEBUG_Q931_STATE }, + { "q931_anomaly", PRI_DEBUG_Q931_ANOMALY }, + { "q931_all", (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q931_ANOMALY) }, + + { "config", PRI_DEBUG_CONFIG }, + { "apdu", PRI_DEBUG_APDU }, + { "aoc", PRI_DEBUG_AOC } +}; /** * \brief Parses a debug string to flags * \param in Debug string to parse for - * \return Flags + * \return Flags or -1 if nothing matched */ -static int parse_debug(const char *in) +static int parse_debug(const char *in, int *flags) { - int flags = 0; + int res = -1; + int i; - if (!in) { + if (!in || !flags) + return -1; + + if (!strcmp(in, "all")) { + *flags = PRI_DEBUG_ALL; + return 0; + } + if (strstr(in, "none")) { + *flags = 0; return 0; } - if (strstr(in, "q921_raw")) { - flags |= PRI_DEBUG_Q921_RAW; + for (i = 0; i < ARRAY_SIZE(ftdm_libpri_debug); i++) { + if (strstr(in, ftdm_libpri_debug[i].name)) { + *flags |= ftdm_libpri_debug[i].flags; + res = 0; + } } - - if (strstr(in, "q921_dump")) { - flags |= PRI_DEBUG_Q921_DUMP; - } - - if (strstr(in, "q921_state")) { - flags |= PRI_DEBUG_Q921_STATE; - } - - if (strstr(in, "config")) { - flags |= PRI_DEBUG_CONFIG; - } - - if (strstr(in, "q931_dump")) { - flags |= PRI_DEBUG_Q931_DUMP; - } - - if (strstr(in, "q931_state")) { - flags |= PRI_DEBUG_Q931_STATE; - } - - if (strstr(in, "q931_anomaly")) { - flags |= PRI_DEBUG_Q931_ANOMALY; - } - - if (strstr(in, "apdu")) { - flags |= PRI_DEBUG_APDU; - } - - if (strstr(in, "aoc")) { - flags |= PRI_DEBUG_AOC; - } - - if (strstr(in, "all")) { - flags |= PRI_DEBUG_ALL; - } - - if (strstr(in, "none")) { - flags = 0; - } - - return flags; + return res; } +static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span); static ftdm_io_interface_t ftdm_libpri_interface; -static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span); +static const char *ftdm_libpri_usage = + "Usage:\n" + "libpri kill \n" + "libpri debug \n" + "\n" + "Possible debug flags:\n" + "\tq921_raw - Q.921 Raw messages\n" + "\tq921_dump - Q.921 Decoded messages\n" + "\tq921_state - Q.921 State machine changes\n" + "\tq921_all - Enable all Q.921 debug options\n" + "\n" + "\tq931_dump - Q.931 Messages\n" + "\tq931_state - Q.931 State machine changes\n" + "\tq931_anomaly - Q.931 Anomalies\n" + "\tq931_all - Enable all Q.931 debug options\n" + "\n" + "\tapdu - Application protocol data unit\n" + "\taoc - Advice of Charge messages\n" + "\tconfig - Configuration\n" + "\n" + "\tnone - Disable debugging\n" + "\tall - Enable all debug options\n"; /** * \brief API function to kill or debug a libpri span @@ -244,13 +231,20 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span); static FIO_API_FUNCTION(ftdm_libpri_api) { char *mycmd = NULL, *argv[10] = { 0 }; - int argc = 0; - + int argc = 0; + if (data) { mycmd = ftdm_strdup(data); argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } + if (argc == 1) { + if (!strcasecmp(argv[0], "help") || !strcasecmp(argv[0], "usage")) { + stream->write_function(stream, ftdm_libpri_usage); + goto done; + } + } + if (argc == 2) { if (!strcasecmp(argv[0], "kill")) { int span_id = atoi(argv[1]); @@ -280,13 +274,20 @@ static FIO_API_FUNCTION(ftdm_libpri_api) if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) { ftdm_libpri_data_t *isdn_data = span->signal_data; + int flags = 0; + if (span->start != ftdm_libpri_start) { stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); goto done; } - pri_set_debug(isdn_data->spri.pri, parse_debug(argv[2])); - stream->write_function(stream, "%s: +OK debug set.\n", __FILE__); + if (parse_debug(argv[2], &flags) == -1) { + stream->write_function(stream, "%s: -ERR invalid debug flags given\n", __FILE__); + goto done; + } + + pri_set_debug(isdn_data->spri.pri, flags); + stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled"); goto done; } else { stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__); @@ -295,16 +296,15 @@ static FIO_API_FUNCTION(ftdm_libpri_api) } } - stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__); - - done: +done: ftdm_safe_free(mycmd); return FTDM_SUCCESS; } + /** * \brief Loads libpri IO module * \param fio FreeTDM IO interface @@ -313,10 +313,10 @@ static FIO_API_FUNCTION(ftdm_libpri_api) static FIO_IO_LOAD_FUNCTION(ftdm_libpri_io_init) { assert(fio != NULL); - memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface)); + memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface)); ftdm_libpri_interface.name = "libpri"; - ftdm_libpri_interface.api = ftdm_libpri_api; + ftdm_libpri_interface.api = &ftdm_libpri_api; *fio = &ftdm_libpri_interface; @@ -445,8 +445,6 @@ static ftdm_state_map_t isdn_state_map = { {FTDM_CHANNEL_STATE_UP, FTDM_END}, {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, }, - - } }; @@ -461,11 +459,9 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) ftdm_status_t status; ftdm_sigmsg_t sig; q931_call *call = (q931_call *) ftdmchan->call_data; - - - ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", - ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state)); + ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", + ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state)); #if 0 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !call) { @@ -473,7 +469,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) } #endif - + memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; @@ -484,7 +480,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_DOWN: { ftdmchan->call_data = NULL; - ftdm_channel_done(ftdmchan); + ftdm_channel_done(ftdmchan); } break; case FTDM_CHANNEL_STATE_PROGRESS: @@ -562,7 +558,6 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) return; } - dp = ftdmchan->caller_data.dnis.type; switch(dp) { case FTDM_TON_NATIONAL: @@ -582,17 +577,26 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) sr = pri_sr_new(); assert(sr); pri_sr_set_channel(sr, ftdmchan->chan_id, 0, 0); - pri_sr_set_bearer(sr, 0, isdn_data->l1); + pri_sr_set_bearer(sr, PRI_TRANS_CAP_SPEECH, isdn_data->l1); pri_sr_set_called(sr, ftdmchan->caller_data.dnis.digits, dp, 1); - pri_sr_set_caller(sr, ftdmchan->caller_data.cid_num.digits, (isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ? NULL : ftdmchan->caller_data.cid_name), - dp, (ftdmchan->caller_data.pres != 1 ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED)); + pri_sr_set_caller(sr, ftdmchan->caller_data.cid_num.digits, + (isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ? NULL : ftdmchan->caller_data.cid_name), + dp, + (ftdmchan->caller_data.pres != 1 ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED)); if (!(isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE)) { - pri_sr_set_redirecting(sr, ftdmchan->caller_data.cid_num.digits, dp, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL); + pri_sr_set_redirecting(sr, ftdmchan->caller_data.cid_num.digits, dp, + PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL); } - +#ifdef HAVE_LIBPRI_AOC + if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) { + /* request AOC on call */ + pri_sr_set_aoc_charging_request(sr, (PRI_AOC_REQUEST_S | PRI_AOC_REQUEST_E | PRI_AOC_REQUEST_D)); + ftdm_log(FTDM_LOG_DEBUG, "Requesting AOC-S/D/E on call\n"); + } +#endif if (pri_setup(isdn_data->spri.pri, call, sr)) { - ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER; ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); } @@ -606,7 +610,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) pri_hangup(isdn_data->spri.pri, call, ftdmchan->caller_data.hangup_cause); pri_destroycall(isdn_data->spri.pri, call); ftdmchan->call_data = NULL; - } + } ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } break; @@ -633,21 +637,23 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan) */ static __inline__ void check_state(ftdm_span_t *span) { - if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { - uint32_t j; - ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); - for(j = 1; j <= span->chan_count; j++) { - if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_mutex_lock(span->channels[j]->mutex); - ftdm_channel_lock(span->channels[j]); - ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE); - state_advance(span->channels[j]); - ftdm_channel_complete_state(span->channels[j]); - ftdm_mutex_unlock(span->channels[j]->mutex); - ftdm_channel_unlock(span->channels[j]); - } - } - } + if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) { + uint32_t j; + + ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE); + + for (j = 1; j <= span->chan_count; j++) { + if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_channel_lock(span->channels[j]); + + ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE); + state_advance(span->channels[j]); + ftdm_channel_complete_state(span->channels[j]); + + ftdm_channel_unlock(span->channels[j]); + } + } + } } /** @@ -659,7 +665,6 @@ static __inline__ void check_state(ftdm_span_t *span) */ static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { - ftdm_log(FTDM_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum); if (strlen(pevent->ring.callednum) > 3) { ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum); @@ -681,7 +686,7 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_channel_t *ftdmchan = NULL; q931_call *call = NULL; ftdmchan = span->channels[pevent->hangup.channel]; - + if (!ftdmchan) { ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->hangup.channel); return 0; @@ -698,7 +703,7 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_state2str(ftdmchan->state)); goto done; } - + call = (q931_call *) ftdmchan->call_data; ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel); ftdmchan->caller_data.hangup_cause = pevent->hangup.cause; @@ -727,13 +732,12 @@ static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even ftdm_channel_t *ftdmchan = NULL; ftdmchan = span->channels[pevent->answer.channel]; - + if (ftdmchan) { ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span->span_id, pevent->answer.channel); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); } else { ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->answer.channel, ftdmchan->chan_id); - } return 0; @@ -750,9 +754,9 @@ static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve { ftdm_span_t *span = spri->private_info; ftdm_channel_t *ftdmchan = NULL; - + ftdmchan = span->channels[pevent->proceeding.channel]; - + if (ftdmchan) { ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span->span_id, pevent->proceeding.channel); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); @@ -777,7 +781,7 @@ static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve ftdm_channel_t *ftdmchan = NULL; ftdmchan = span->channels[pevent->ringing.channel]; - + if (ftdmchan) { ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span->span_id, pevent->ringing.channel); /* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */ @@ -808,7 +812,7 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event int ret = 0; //switch_mutex_lock(globals.channel_mutex); - + ftdmchan = span->channels[pevent->ring.channel]; if (!ftdmchan || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel); @@ -821,13 +825,12 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event ret = 0; goto done; } - ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span->span_id, pevent->ring.channel, pevent->ring.callingnum, pevent->ring.callednum); - + memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data)); - + ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)pevent->ring.callingnum); if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) { ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingname); @@ -836,19 +839,18 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event } ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)pevent->ring.callingani); ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)pevent->ring.callednum); - + if (pevent->ring.ani2 >= 0) { snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", pevent->ring.ani2); } - + // scary to trust this pointer, you'd think they would give you a copy of the call data so you own it...... ftdmchan->call_data = pevent->ring.call; - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - - done: - //switch_mutex_unlock(globals.channel_mutex); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); + +done: + //switch_mutex_unlock(globals.channel_mutex); return ret; } @@ -861,8 +863,13 @@ static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event) { ftdm_alarm_flag_t alarmbits; - ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n", - ftdm_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state)); + + ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n", + ftdm_oob_event2str(event->enum_id), + event->enum_id, + event->channel->span_id, + event->channel->chan_id, + ftdm_channel_state2str(event->channel->state)); switch(event->enum_id) { case FTDM_OOB_ALARM_TRAP: @@ -872,11 +879,9 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART); } } - ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED); - ftdm_channel_get_alarms(event->channel, &alarmbits); ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n", event->channel->span_id, event->channel->chan_id, @@ -886,7 +891,6 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e break; case FTDM_OOB_ALARM_CLEAR: { - ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id, event->channel->physical_span_id, event->channel->physical_chan_id); @@ -913,6 +917,7 @@ static __inline__ void check_events(ftdm_span_t *span) case FTDM_SUCCESS: { ftdm_event_t *event; + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { if (event->enum_id == FTDM_OOB_NOOP) { continue; @@ -923,12 +928,12 @@ static __inline__ void check_events(ftdm_span_t *span) } } break; + case FTDM_FAIL: - { - ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running()); - ftdm_sleep(2000); - } + ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running()); + ftdm_sleep(2000); break; + default: break; } @@ -949,8 +954,6 @@ static int check_flags(lpwrap_pri_t *spri) check_state(span); check_events(span); - - return 0; } @@ -967,7 +970,7 @@ static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve ftdm_channel_t *ftdmchan; ftdm_log(FTDM_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span->span_id, pevent->restart.channel); - + spri->dchan->state = FTDM_CHANNEL_STATE_UP; ftdmchan = span->channels[pevent->restart.channel]; @@ -984,6 +987,182 @@ static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve return 0; } +/* + * FACILITY Advice-On-Charge handler + */ +#ifdef HAVE_LIBPRI_AOC +static const char *aoc_billing_id(const int id) +{ + switch (id) { + case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE: + return "not available"; + case PRI_AOC_E_BILLING_ID_NORMAL: + return "normal"; + case PRI_AOC_E_BILLING_ID_REVERSE: + return "reverse"; + case PRI_AOC_E_BILLING_ID_CREDIT_CARD: + return "credit card"; + case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL: + return "call forwarding unconditional"; + case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY: + return "call forwarding busy"; + case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY: + return "call forwarding no reply"; + case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION: + return "call deflection"; + case PRI_AOC_E_BILLING_ID_CALL_TRANSFER: + return "call transfer"; + default: + return "unknown\n"; + } +} + +static float aoc_money_amount(const struct pri_aoc_amount *amount) +{ + switch (amount->multiplier) { + case PRI_AOC_MULTIPLIER_THOUSANDTH: + return amount->cost * 0.001f; + case PRI_AOC_MULTIPLIER_HUNDREDTH: + return amount->cost * 0.01f; + case PRI_AOC_MULTIPLIER_TENTH: + return amount->cost * 0.1f; + case PRI_AOC_MULTIPLIER_TEN: + return amount->cost * 10.0f; + case PRI_AOC_MULTIPLIER_HUNDRED: + return amount->cost * 100.0f; + case PRI_AOC_MULTIPLIER_THOUSAND: + return amount->cost * 1000.0f; + default: + return amount->cost; + } +} + +static int handle_facility_aoc_s(const struct pri_subcmd_aoc_s *aoc_s) +{ + /* Left as an excercise to the reader */ + return 0; +} + +static int handle_facility_aoc_d(const struct pri_subcmd_aoc_d *aoc_d) +{ + /* Left as an excercise to the reader */ + return 0; +} + +static int handle_facility_aoc_e(const struct pri_subcmd_aoc_e *aoc_e) +{ + char tmp[1024] = { 0 }; + int x = 0, offset = 0; + + switch (aoc_e->charge) { + case PRI_AOC_DE_CHARGE_FREE: + strcat(tmp, "\tcharge-type: none\n"); + offset = strlen(tmp); + break; + + case PRI_AOC_DE_CHARGE_CURRENCY: + sprintf(tmp, "\tcharge-type: money\n\tcharge-amount: %.2f\n\tcharge-currency: %s\n", + aoc_money_amount(&aoc_e->recorded.money.amount), + aoc_e->recorded.money.currency); + offset = strlen(tmp); + break; + + case PRI_AOC_DE_CHARGE_UNITS: + strcat(tmp, "\tcharge-type: units\n"); + offset = strlen(tmp); + + for (x = 0; x < aoc_e->recorded.unit.num_items; x++) { + sprintf(&tmp[offset], "\tcharge-amount: %ld (type: %d)\n", + aoc_e->recorded.unit.item[x].number, + aoc_e->recorded.unit.item[x].type); + offset += strlen(&tmp[offset]); + } + break; + + default: + strcat(tmp, "\tcharge-type: not available\n"); + offset = strlen(tmp); + } + + sprintf(&tmp[offset], "\tbilling-id: %s\n", aoc_billing_id(aoc_e->billing_id)); + offset += strlen(&tmp[offset]); + + strcat(&tmp[offset], "\tassociation-type: "); + offset += strlen(&tmp[offset]); + + switch (aoc_e->associated.charging_type) { + case PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE: + strcat(&tmp[offset], "not available\n"); + break; + case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER: + sprintf(&tmp[offset], "number\n\tassociation-number: %s\n", aoc_e->associated.charge.number.str); + break; + case PRI_AOC_E_CHARGING_ASSOCIATION_ID: + sprintf(&tmp[offset], "id\n\tassociation-id: %d\n", aoc_e->associated.charge.id); + break; + default: + strcat(&tmp[offset], "unknown\n"); + } + + ftdm_log(FTDM_LOG_INFO, "AOC-E:\n%s", tmp); + return 0; +} +#endif + +/** + * \brief Handler for libpri facility events + * \param spri Pri wrapper structure (libpri, span, dchan) + * \param event_type Event type (unused) + * \param pevent Event + * \return 0 + */ +static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) +{ + struct pri_event_facility *pfac = (struct pri_event_facility *)pevent; + int i = 0; + + if (!pevent) + return 0; + + if (!pfac->subcmds || pfac->subcmds->counter_subcmd <= 0) + return 0; + + for (i = 0; i < pfac->subcmds->counter_subcmd; i++) { + struct pri_subcommand *sub = &pfac->subcmds->subcmd[i]; + int res = -1; + + switch (sub->cmd) { +#ifdef HAVE_LIBPRI_AOC + case PRI_SUBCMD_AOC_S: /* AOC-S: Start of call */ + res = handle_facility_aoc_s(&sub->u.aoc_s); + break; + case PRI_SUBCMD_AOC_D: /* AOC-D: During call */ + res = handle_facility_aoc_d(&sub->u.aoc_d); + break; + case PRI_SUBCMD_AOC_E: /* AOC-E: End of call */ + res = handle_facility_aoc_e(&sub->u.aoc_e); + break; + case PRI_SUBCMD_AOC_CHARGING_REQ: + ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request received\n"); + break; + case PRI_SUBCMD_AOC_CHARGING_REQ_RSP: + ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request Response received [aoc_s data: %s, req: %x, resp: %x]\n", + sub->u.aoc_request_response.valid_aoc_s ? "yes" : "no", + sub->u.aoc_request_response.charging_request, + sub->u.aoc_request_response.charging_response); + break; +#endif + default: + ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d is not implemented, ignoring\n", sub->cmd); + } + + ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d handler returned %d\n", sub->cmd, res); + } + + ftdm_log(FTDM_LOG_DEBUG, "Caught Event on span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type)); + return 0; +} + /** * \brief Handler for libpri dchan up event * \param spri Pri wrapper structure (libpri, span, dchan) @@ -998,19 +1177,23 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev ftdm_channel_t *ftdmchan = NULL; ftdm_sigmsg_t sig; int i; + ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan UP!\n", spri->span->span_id); ftdm_set_flag(spri, LPWRAP_PRI_READY); ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART); ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status)); - for(i=1; i <= spri->span->chan_count; i++) { + + for (i = 1; i <= spri->span->chan_count; i++) { ftdmchan = spri->span->channels[i]; + memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.raw_data = &status; + ftdm_span_send_signal(spri->span, &sig); } } @@ -1025,26 +1208,29 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev * \return 0 */ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) -{ +{ if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) { ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN; ftdm_channel_t *ftdmchan = NULL; ftdm_sigmsg_t sig; int i; + ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span->span_id); ftdm_clear_flag(spri, LPWRAP_PRI_READY); ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART); - ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status)); - for(i=1; i <= spri->span->chan_count; i++) { + + for (i = 1; i <= spri->span->chan_count; i++) { ftdmchan = spri->span->channels[i]; + memset(&sig, 0, sizeof(sig)); sig.chan_id = ftdmchan->chan_id; sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sig.raw_data = &status; + ftdm_span_send_signal(spri->span, &sig); } } @@ -1061,7 +1247,6 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ */ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { - ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type)); return 0; } @@ -1075,7 +1260,6 @@ static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev */ static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent) { - ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type)); return 0; } @@ -1084,20 +1268,24 @@ static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_eve * \brief Main thread function for libpri span (monitor) * \param me Current thread * \param obj Span to run in this thread + * + * \todo Move all init stuff outside of loop or into ftdm_libpri_configure_span() */ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) { ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_libpri_data_t *isdn_data = span->signal_data; - int i, x = 0; int down = 0; int got_d = 0; - + int res = 0; + ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); - - while(ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { + + while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { if (!got_d) { - for(i = 1; i <= span->chan_count; i++) { + int i, x; + + for (i = 1, x = 0; i <= span->chan_count; i++) { if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { if (ftdm_channel_open(span->span_id, i, &isdn_data->dchan) == FTDM_SUCCESS) { ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id); @@ -1110,22 +1298,49 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) } } } - if (!got_d) { ftdm_log(FTDM_LOG_ERROR, "Failed to get a D-channel in span %d\n", span->span_id); break; } - - - if (lpwrap_init_pri(&isdn_data->spri, - span, // span - isdn_data->dchan, // dchan - isdn_data->pswitch, - isdn_data->node, - isdn_data->debug) < 0) { - snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!"); - } else { + /* Initialize libpri trunk */ + switch (ftdm_span_get_trunk_type(span)) { + case FTDM_TRUNK_E1: + case FTDM_TRUNK_T1: + case FTDM_TRUNK_J1: + res = lpwrap_init_pri(&isdn_data->spri, span, isdn_data->dchan, + isdn_data->pswitch, isdn_data->node, isdn_data->debug); + break; + case FTDM_TRUNK_BRI: + res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan, + isdn_data->pswitch, isdn_data->node, 1, isdn_data->debug); +#ifndef HAVE_LIBPRI_BRI + goto out; +#endif + break; + case FTDM_TRUNK_BRI_PTMP: + res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan, + isdn_data->pswitch, isdn_data->node, 0, isdn_data->debug); +#ifndef HAVE_LIBPRI_BRI + goto out; +#endif + break; + default: + snprintf(span->last_error, sizeof(span->last_error), "Invalid trunk type"); + goto out; + } + +#ifdef HAVE_LIBPRI_AOC + /* + * Only enable facility on trunk if really required, + * this may help avoid problems on troublesome lines. + */ + if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) { + pri_facility_enable(isdn_data->spri.pri); + } +#endif + + if (res == 0) { LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing); @@ -1139,6 +1354,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart); LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail); + LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_FACILITY, on_facility); if (down) { ftdm_log(FTDM_LOG_INFO, "PRI back up on span %d\n", isdn_data->spri.span->span_id); @@ -1148,8 +1364,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) isdn_data->spri.on_loop = check_flags; isdn_data->spri.private_info = span; - lpwrap_run_pri(&isdn_data->spri); + lpwrap_run_pri(&isdn_data->spri); + } else { + snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!"); } if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) { @@ -1172,7 +1390,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) down++; ftdm_sleep(5000); } - +out: ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", span->span_id); ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); @@ -1197,11 +1415,15 @@ static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span) } ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART); + check_state(span); + ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD); - while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { + + while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { ftdm_sleep(100); } + check_state(span); return FTDM_SUCCESS; @@ -1241,7 +1463,7 @@ static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span) * \param node Node string to convert * \return -1 on failure, node value on success */ -static int str2node(char *node) +static int parse_node(const char *node) { if (!strcasecmp(node, "cpe") || !strcasecmp(node, "user")) return PRI_CPE; @@ -1255,7 +1477,7 @@ static int str2node(char *node) * \param swtype Swtype string to convert * \return Switch value */ -static int str2switch(char *swtype) +static int parse_switch(const char *swtype) { if (!strcasecmp(swtype, "ni1")) return PRI_SWITCH_NI1; @@ -1273,6 +1495,7 @@ static int str2switch(char *swtype) return PRI_SWITCH_GR303_EOC; if (!strcasecmp(swtype, "gr303tmc")) return PRI_SWITCH_GR303_TMC; + return PRI_SWITCH_DMS100; } @@ -1281,11 +1504,11 @@ static int str2switch(char *swtype) * \param l1 L1 string to convert * \return L1 value */ -static int str2l1(char *l1) +static int parse_l1(const char *l1) { if (!strcasecmp(l1, "alaw")) return PRI_LAYER_1_ALAW; - + return PRI_LAYER_1_ULAW; } @@ -1294,7 +1517,7 @@ static int str2l1(char *l1) * \param dp DP string to convert * \return DP value */ -static int str2dp(char *dp) +static int parse_numplan(const char *dp) { if (!strcasecmp(dp, "international")) return PRI_INTERNATIONAL_ISDN; @@ -1310,26 +1533,54 @@ static int str2dp(char *dp) return PRI_UNKNOWN; } +/** + * \brief Parses an option string to flags + * \param in String to parse for configuration options + * \return Flags + */ +static uint32_t parse_opts(const char *in) +{ + uint32_t flags = 0; + + if (!in) { + return 0; + } + + if (strstr(in, "suggest_channel")) { + flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL; + } + if (strstr(in, "omit_display")) { + flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE; + } + if (strstr(in, "omit_redirecting_number")) { + flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE; + } + if (strstr(in, "aoc")) { + flags |= FTMOD_LIBPRI_OPT_FACILITY_AOC; + } + return flags; +} + /** * \brief Initialises a libpri span from configuration variables * \param span Span to configure * \param sig_cb Callback function for event signals - * \param ap List of configuration variables + * \param ftdm_parameters List of configuration variables * \return Success or failure */ -static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span) +static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span) { uint32_t i, x = 0; + uint32_t paramindex = 0; //ftdm_channel_t *dchans[2] = {0}; ftdm_libpri_data_t *isdn_data; - char *var, *val; - char *debug = NULL; + const char *var, *val; - if (span->trunk_type >= FTDM_TRUNK_NONE) { - ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type)); - span->trunk_type = FTDM_TRUNK_T1; + if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) { + ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(ftdm_span_get_trunk_type(span))); + ftdm_span_set_trunk_type(span, FTDM_TRUNK_T1); } - + for(i = 1; i <= span->chan_count; i++) { if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { if (x > 1) { @@ -1346,7 +1597,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span) } } } - + #if 0 if (!x) { snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!"); @@ -1358,97 +1609,107 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span) assert(isdn_data != NULL); memset(isdn_data, 0, sizeof(*isdn_data)); - if (span->trunk_type == FTDM_TRUNK_E1) { - ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1 trunk\n"); - isdn_data->l1 = PRI_LAYER_1_ALAW; - } else if (span->trunk_type == FTDM_TRUNK_T1) { - ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1 trunk\n"); - isdn_data->l1 = PRI_LAYER_1_ULAW; - } - - while((var = va_arg(ap, char *))) { + switch (ftdm_span_get_trunk_type(span)) { + case FTDM_TRUNK_BRI: + case FTDM_TRUNK_BRI_PTMP: +#ifndef HAVE_LIBPRI_BRI + ftdm_log(FTDM_LOG_ERROR, "Unsupported trunk type: '%s', libpri too old\n", ftdm_trunk_type2str(ftdm_span_get_trunk_type(span))); + snprintf(span->last_error, sizeof(span->last_error), "Unsupported trunk type [%s], libpri too old", ftdm_trunk_type2str(ftdm_span_get_trunk_type(span))); + return FTDM_FAIL; +#endif + case FTDM_TRUNK_E1: + ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n"); + isdn_data->l1 = PRI_LAYER_1_ALAW; + break; + case FTDM_TRUNK_T1: + case FTDM_TRUNK_J1: + ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n"); + isdn_data->l1 = PRI_LAYER_1_ULAW; + break; + default: + ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_trunk_type2str(ftdm_span_get_trunk_type(span))); + snprintf(span->last_error, sizeof(span->last_error), "Invalid trunk type [%s]", ftdm_trunk_type2str(ftdm_span_get_trunk_type(span))); + return FTDM_FAIL; + } + + for (paramindex = 0; paramindex < 10 && ftdm_parameters[paramindex].var; paramindex++) { + var = ftdm_parameters[paramindex].var; + val = ftdm_parameters[paramindex].val; + + if (!val) { + ftdm_log(FTDM_LOG_ERROR, "Parameter '%s' has no value\n", var); + snprintf(span->last_error, sizeof(span->last_error), "Parameter [%s] has no value", var); + return FTDM_FAIL; + } + if (!strcasecmp(var, "node")) { - int node; - if (!(val = va_arg(ap, char *))) { - break; - } - node = str2node(val); - if (-1 == node) { - ftdm_log(FTDM_LOG_ERROR, "Unknown node type %s, defaulting to CPE mode\n", val); - node = PRI_CPE; - } - isdn_data->node = node; - } else if (!strcasecmp(var, "switch")) { - if (!(val = va_arg(ap, char *))) { - break; - } - isdn_data->pswitch = str2switch(val); - } else if (!strcasecmp(var, "opts")) { - if (!(val = va_arg(ap, char *))) { - break; + if ((isdn_data->node = parse_node(val)) == -1) { + ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s', defaulting to CPE mode\n", val); + isdn_data->node = PRI_CPE; } + } + else if (!strcasecmp(var, "switch")) { + isdn_data->pswitch = parse_switch(val); + } + else if (!strcasecmp(var, "opts")) { isdn_data->opts = parse_opts(val); - } else if (!strcasecmp(var, "dp")) { - if (!(val = va_arg(ap, char *))) { - break; + } + else if (!strcasecmp(var, "dp")) { + isdn_data->dp = parse_numplan(val); + } + else if (!strcasecmp(var, "l1")) { + isdn_data->l1 = parse_l1(val); + } + else if (!strcasecmp(var, "debug")) { + if (parse_debug(val, &isdn_data->debug) == -1) { + ftdm_log(FTDM_LOG_ERROR, "Invalid debug flag, ignoring parameter\n"); + isdn_data->debug = 0; } - isdn_data->dp = str2dp(val); - } else if (!strcasecmp(var, "l1")) { - if (!(val = va_arg(ap, char *))) { - break; - } - isdn_data->l1 = str2l1(val); - } else if (!strcasecmp(var, "debug")) { - if (!(val = va_arg(ap, char *))) { - break; - } - debug = val; - } else { + } + else { + ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var); snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); return FTDM_FAIL; } } - + span->start = ftdm_libpri_start; - span->stop = ftdm_libpri_stop; + span->stop = ftdm_libpri_stop; span->signal_cb = sig_cb; //isdn_data->dchans[0] = dchans[0]; //isdn_data->dchans[1] = dchans[1]; //isdn_data->dchan = isdn_data->dchans[0]; - - isdn_data->debug = parse_debug(debug); - span->signal_data = isdn_data; span->signal_type = FTDM_SIGTYPE_ISDN; span->outgoing_call = isdn_outgoing_call; + span->state_map = &isdn_state_map; + span->get_channel_sig_status = isdn_get_channel_sig_status; span->get_span_sig_status = isdn_get_span_sig_status; - + if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) { span->channel_request = isdn_channel_request; ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID); } - span->state_map = &isdn_state_map; - return FTDM_SUCCESS; } /** * \brief FreeTDM libpri signaling and IO module definition */ -ftdm_module_t ftdm_module = { +ftdm_module_t ftdm_module = { "libpri", ftdm_libpri_io_init, ftdm_libpri_unload, ftdm_libpri_init, - ftdm_libpri_configure_span, - NULL + NULL, + NULL, + ftdm_libpri_configure_span }; - /* For Emacs: * Local Variables: * mode:c diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h index 0bf8c46817..b11baec6c5 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.h @@ -42,8 +42,9 @@ typedef enum { FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL = (1 << 0), FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE = (1 << 1), FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE = (1 << 2), - - FTMOD_LIBPRI_OPT_MAX = (1 << 3) + FTMOD_LIBPRI_OPT_FACILITY_AOC = (1 << 3), + + FTMOD_LIBPRI_OPT_MAX = (1 << 4) } ftdm_isdn_opts_t; typedef enum { diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index 8dfba34ec3..de4fa2b232 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -1,23 +1,23 @@ /* * Copyright (c) 2009, Anthony Minessale II * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * - * + * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -35,8 +35,8 @@ #include "private/ftdm_core.h" #include "lpwrap_pri.h" -#ifndef HAVE_GETTIMEOFDAY +#ifndef HAVE_GETTIMEOFDAY #ifdef WIN32 #include @@ -92,7 +92,7 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = { {8, LPWRAP_PRI_EVENT_ANSWER, "ANSWER"}, {9, LPWRAP_PRI_EVENT_HANGUP_ACK, "HANGUP_ACK"}, {10, LPWRAP_PRI_EVENT_RESTART_ACK, "RESTART_ACK"}, - {11, LPWRAP_PRI_EVENT_FACNAME, "FACNAME"}, + {11, LPWRAP_PRI_EVENT_FACILITY, "FACILITY"}, {12, LPWRAP_PRI_EVENT_INFO_RECEIVED, "INFO_RECEIVED"}, {13, LPWRAP_PRI_EVENT_PROCEEDING, "PROCEEDING"}, {14, LPWRAP_PRI_EVENT_SETUP_ACK, "SETUP_ACK"}, @@ -106,7 +106,10 @@ static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = { #define LINE "--------------------------------------------------------------------------------" const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id) -{ +{ + if (event_id < 0 || event_id >= LPWRAP_PRI_EVENT_MAX) + return ""; + return LPWRAP_PRI_EVENT_LIST[event_id].name; } @@ -114,8 +117,8 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen) { struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri); ftdm_size_t len = buflen; - int res; ftdm_status_t zst; + int res; if ((zst = ftdm_channel_read(spri->dchan, buf, &len)) != FTDM_SUCCESS) { if (zst == FTDM_FAIL) { @@ -124,31 +127,31 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen) } else { ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id); } - + ftdm_clear_flag(spri, LPWRAP_PRI_READY); return -1; } spri->errs = 0; res = (int)len; - memset(&((unsigned char*)buf)[res],0,2); - res+=2; + + memset(&((unsigned char*)buf)[res], 0, 2); + res += 2; #ifdef IODEBUG { char bb[2048] = { 0 }; print_hex_bytes(buf, res - 2, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res-2); + ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2); } #endif - return res; } static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen) { struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri); - ftdm_size_t len = buflen -2; + ftdm_size_t len = buflen - 2; if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error); @@ -161,11 +164,10 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen) char bb[2048] = { 0 }; print_hex_bytes(buf, buflen - 2, bb, sizeof(bb)); - ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", (int)buflen-2); + ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", (int)buflen - 2); } #endif - - return (int) buflen; + return (int)buflen; } int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug) @@ -173,21 +175,63 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t * int ret = -1; memset(spri, 0, sizeof(struct lpwrap_pri)); - spri->dchan = dchan; - spri->span = span; + spri->span = span; - if (spri->dchan && (spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))){ - unsigned char buf[4] = { 0 }; - size_t buflen = sizeof(buf), len = 0; - pri_set_debug(spri->pri, debug); - ret = 0; - - ftdm_channel_write(spri->dchan, buf, buflen, &len); - } else { - fprintf(stderr, "Unable to create PRI\n"); + if (!spri->dchan) { + ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create PRI\n"); + return ret; } + if ((spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) { + unsigned char buf[4] = { 0 }; + size_t buflen = sizeof(buf), len = 0; + + pri_set_debug(spri->pri, debug); +#ifdef HAVE_LIBPRI_AOC + pri_aoc_events_enable(spri->pri, 1); +#endif + ftdm_channel_write(spri->dchan, buf, buflen, &len); + + ret = 0; + } else { + ftdm_log(FTDM_LOG_ERROR, "Unable to create PRI\n"); + } + return ret; +} + +int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug) +{ + int ret = -1; + +#ifdef HAVE_LIBPRI_BRI + memset(spri, 0, sizeof(struct lpwrap_pri)); + spri->dchan = dchan; + spri->span = span; + + if (!spri->dchan) { + ftdm_log(FTDM_LOG_ERROR, "No D-Channel available, unable to create BRI\n"); + return ret; + } + + if ((spri->pri = pri_new_bri_cb(spri->dchan->sockfd, ptp, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))) { + unsigned char buf[4] = { 0 }; + size_t buflen = sizeof(buf), len = 0; + + pri_set_debug(spri->pri, debug); +#ifdef HAVE_LIBPRI_AOC + pri_aoc_events_enable(spri->pri, 1); +#endif + ftdm_channel_write(spri->dchan, buf, buflen, &len); + + ret = 0; + } else { + ftdm_log(FTDM_LOG_ERROR, "Unable to create BRI\n"); + } +#else + ftdm_log(FTDM_LOG_ERROR, "Installed libpri version (%s) has no BRI support\n", + pri_get_version()); +#endif return ret; } @@ -195,11 +239,11 @@ int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t * int lpwrap_one_loop(struct lpwrap_pri *spri) { fd_set rfds, efds; - struct timeval now = {0,0}, *next; - pri_event *event; + struct timeval now = {0,0}, *next = NULL; + pri_event *event = NULL; event_handler handler; - int sel; - + int sel; + if (spri->on_loop) { if ((sel = spri->on_loop(spri)) < 0) { return sel; @@ -231,9 +275,6 @@ int lpwrap_one_loop(struct lpwrap_pri *spri) now.tv_usec = 100000; sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, &now); - - event = NULL; - if (!sel) { if ((next = pri_schedule_next(spri->pri))) { gettimeofday(&now, NULL); @@ -248,46 +289,40 @@ int lpwrap_one_loop(struct lpwrap_pri *spri) if (event) { /* 0 is catchall event handler */ - if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) { + if (event->e < 0 || event->e >= LPWRAP_PRI_EVENT_MAX) { + handler = spri->eventmap[0]; + } else if (spri->eventmap[event->e]) { + handler = spri->eventmap[event->e]; + } else { + handler = spri->eventmap[0]; + } + + if (handler) { handler(spri, event->e, event); } else { ftdm_log(FTDM_LOG_CRIT, "No event handler found for event %d.\n", event->e); } } - - return sel; - - - if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] ? spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) { - handler(spri, LPWRAP_PRI_EVENT_IO_FAIL, NULL); - } - - return -1; } int lpwrap_run_pri(struct lpwrap_pri *spri) { int ret = 0; - - for (;;){ - ret = lpwrap_one_loop(spri); - - if (ret < 0) { + for (;;) { + if ((ret = lpwrap_one_loop(spri)) < 0) { #ifndef WIN32 //This needs to be adressed fror WIN32 still if (errno == EINTR){ /* Igonore an interrupted system call */ continue; } -#endif +#endif ftdm_log(FTDM_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno)); break; } } - return ret; - } /* For Emacs: @@ -300,4 +335,3 @@ int lpwrap_run_pri(struct lpwrap_pri *spri) * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ - diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h index f92c5bbafa..b62e5fb176 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.h @@ -51,7 +51,11 @@ typedef enum { LPWRAP_PRI_EVENT_ANSWER = PRI_EVENT_ANSWER, LPWRAP_PRI_EVENT_HANGUP_ACK = PRI_EVENT_HANGUP_ACK, LPWRAP_PRI_EVENT_RESTART_ACK = PRI_EVENT_RESTART_ACK, - LPWRAP_PRI_EVENT_FACNAME = PRI_EVENT_FACNAME, +#ifdef PRI_EVENT_FACILITY + LPWRAP_PRI_EVENT_FACILITY = PRI_EVENT_FACILITY, +#else + LPWRAP_PRI_EVENT_FACILITY = PRI_EVENT_FACNAME, +#endif LPWRAP_PRI_EVENT_INFO_RECEIVED = PRI_EVENT_INFO_RECEIVED, LPWRAP_PRI_EVENT_PROCEEDING = PRI_EVENT_PROCEEDING, LPWRAP_PRI_EVENT_SETUP_ACK = PRI_EVENT_SETUP_ACK, @@ -121,6 +125,8 @@ struct lpwrap_pri_event_list { const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id); int lpwrap_one_loop(struct lpwrap_pri *spri); int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug); +int lpwrap_init_bri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int ptp, int debug); int lpwrap_run_pri(struct lpwrap_pri *spri); +#define lpwrap_run_bri(x) lpwrap_run_pri(x) #endif diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 56c0bc6e73..086656128e 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -403,6 +403,7 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Cannot start call when channel is in use (state = %s)\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_mutex_unlock(ftdmchan->mutex); + return; } if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) { @@ -436,9 +437,6 @@ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); ftdm_mutex_unlock(ftdmchan->mutex); - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Span is not threaded, not launching thread for this call\n"); - return; } /* only called for incoming calls when the ANI, DNIS etc is complete and the user has to decide either to accept or reject the call */ @@ -447,9 +445,7 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Priority = (%d)\n", ani, dnis, category); - //ftdmchan->caller_data.priority = category; ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode) @@ -602,8 +598,8 @@ static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan) ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED); - /* XXX when should we set/unset this flag? XXX */ - ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_UP); + /* XXX when should we set/unset this flag? XXX */ + ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_UP); } static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message) @@ -1116,7 +1112,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span) memset(r2call, 0, sizeof(*r2call)); openr2_chan_set_logging_func(r2chan, ftdm_r2_on_chan_log); openr2_chan_set_client_data(r2chan, span->channels[i]); - r2call->r2chan = r2chan; + r2call->r2chan = r2chan; span->channels[i]->call_data = r2call; /* value and key are the same so just free one of them */ snprintf(r2call->name, sizeof(r2call->name), "chancall%d", i); @@ -1331,8 +1327,8 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan) static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) { openr2_chan_t *r2chan; - ftdm_r2_call_t *r2call = NULL; - ftdm_channel_t *ftdmchan = NULL; + ftdm_r2_call_t *r2call = NULL; + ftdm_channel_t *ftdmchan = NULL; ftdm_status_t status; ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_r2_data_t *r2data = span->signal_data; @@ -1368,16 +1364,14 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) } #ifndef WIN32 - /* figure out what event to poll each channel for. POLLPRI when the channel is down, - * POLLPRI|POLLIN|POLLOUT otherwise. - */ - memset(poll_events, 0, sizeof(short)*span->chan_count); - for (i = 0; i < span->chan_count; i++) { - r2chan = R2CALL(span->channels[(i+1)])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); - - poll_events[i] = ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ? POLLPRI : (POLLPRI | POLLIN | POLLOUT); - } + /* figure out what event to poll each channel for. POLLPRI when the channel is down, + * POLLPRI|POLLIN|POLLOUT otherwise */ + memset(poll_events, 0, sizeof(short)*span->chan_count); + for (i = 0; i < span->chan_count; i++) { + r2chan = R2CALL(span->channels[(i+1)])->r2chan; + ftdmchan = openr2_chan_get_client_data(r2chan); + poll_events[i] = ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ? POLLPRI : (POLLPRI | POLLIN | POLLOUT); + } status = ftdm_span_poll_event(span, waitms, poll_events); #else @@ -1394,62 +1388,61 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) continue; } - if (FTDM_SUCCESS == status) { + if (FTDM_SUCCESS == status) { ftdm_event_t *event; while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { if (event->enum_id == FTDM_OOB_CAS_BITS_CHANGE) { - r2call = R2CALL(event->channel); - r2chan = r2call->r2chan; + r2call = R2CALL(event->channel); + r2chan = r2call->r2chan; ftdm_log(FTDM_LOG_DEBUG, "Handling CAS on channel %d.\n", openr2_chan_get_number(r2chan)); // we only expect CAS and other OOB events on this thread/loop, once a call is started // the MF events (in-band signaling) are handled in the call thread openr2_chan_process_cas_signaling(r2chan); - } else { ftdm_log(FTDM_LOG_DEBUG, "Ignoring event %d on channel %d.\n", event->enum_id, openr2_chan_get_number(r2chan)); // XXX TODO: handle alarms here XXX } } - /* XXX - * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. - * is it possible to know on which channels those events are pending, without trasvering the span? - * XXX - */ - for (i = 1; i <= span->chan_count; i++) { - r2chan = R2CALL(span->channels[i])->r2chan; - ftdmchan = openr2_chan_get_client_data(r2chan); - r2call = R2CALL(ftdmchan); + /* XXX + * when ftdm_span_poll_event() returns FTDM_SUCCESS, means there are events pending on the span. + * is it possible to know on which channels those events are pending, without traversing the span? + * XXX */ + for (i = 1; i <= span->chan_count; i++) { + r2chan = R2CALL(span->channels[i])->r2chan; + ftdmchan = openr2_chan_get_client_data(r2chan); + r2call = R2CALL(ftdmchan); - ftdm_mutex_lock(ftdmchan->mutex); - ftdm_set_flag(r2call, FTDM_R2_PROCESSING); + ftdm_mutex_lock(ftdmchan->mutex); + ftdm_set_flag(r2call, FTDM_R2_PROCESSING); - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } + if (ftdm_r2_state_advance(ftdmchan)) { + ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); + ftdm_mutex_unlock(ftdmchan->mutex); + continue; + } - /* handle timeout events first if any */ - openr2_chan_run_schedule(r2chan); + /* handle timeout events first if any */ + openr2_chan_run_schedule(r2chan); - /* process mf tones, if any */ - if (openr2_chan_get_read_enabled(r2chan)) - openr2_chan_process_mf_signaling(r2chan); + /* process mf tones, if any */ + if (openr2_chan_get_read_enabled(r2chan)) { + openr2_chan_process_mf_signaling(r2chan); + } - if (ftdm_r2_state_advance(ftdmchan)) { - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - continue; - } + if (ftdm_r2_state_advance(ftdmchan)) { + ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); + ftdm_mutex_unlock(ftdmchan->mutex); + continue; + } - ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); - ftdm_mutex_unlock(ftdmchan->mutex); - } + ftdm_clear_flag(r2call, FTDM_R2_PROCESSING); + ftdm_mutex_unlock(ftdmchan->mutex); + } } else if (status != FTDM_TIMEOUT) { ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status); - } + } ftdm_sleep(20); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 04c3b86c5e..69743115fe 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -49,7 +49,6 @@ ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisd static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span); static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event); - static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); @@ -279,6 +278,10 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) { ftdm_status_t ret_status; + ftdm_channel_t *ftdmchan; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; + ret_status = ftdm_span_poll_event(span, 0, NULL); switch(ret_status) { case FTDM_SUCCESS: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index 43e35b6dfd..3b264ae02f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -100,6 +100,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span) ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported switchtype %s for trunktype:%s\n", span->name, switch_name, ftdm_trunk_type2str(span->trunk_type)); return FTDM_FAIL; } + ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); + ftdm_set_flag(span, FTDM_SPAN_PWR_SAVING); /* can be > 1 for some BRI variants */ break; default: @@ -188,6 +190,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ signal_data->min_digits = 8; signal_data->overlap_dial = SNGISDN_OPT_DEFAULT; signal_data->setup_arb = SNGISDN_OPT_DEFAULT; + signal_data->timer_t3 = 8; signal_data->link_id = span->span_id; span->default_caller_data.bearer_capability = IN_ITC_SPEECH; @@ -198,6 +201,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ if (span->trunk_type == FTDM_TRUNK_BRI || span->trunk_type == FTDM_TRUNK_BRI_PTMP) { + ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan); ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type); ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index d8e6c8e00d..1714ac185c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -113,6 +113,40 @@ ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span) } +ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span) +{ + L1Mngmt cntrl; + Pst pst; + + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; + + /* initalize the post structure */ + stack_pst_init(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTL1; + + /* initalize the control structure */ + memset(&cntrl, 0, sizeof(cntrl)); + + /* initalize the control header */ + stack_hdr_init(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* configuration */ + cntrl.hdr.entId.ent = ENTL1; /* entity */ + cntrl.hdr.entId.inst = S_INST; /* instance */ + cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */ + + cntrl.t.cntrl.action = AENA; + cntrl.t.cntrl.subAction = SAELMNT; + cntrl.t.cntrl.sapId = signal_data->link_id; + + if (sng_isdn_phy_cntrl(&pst, &cntrl)) { + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index 37613cc33d..dd0b9d46d9 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -135,6 +135,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display); + cpy_redir_num_from_stack(&ftdmchan->caller_data, &conEvnt->redirNmb); ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits); if (conEvnt->bearCap[0].eh.pres) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index bf44cb2e0a..163265177f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -38,13 +38,6 @@ extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_d extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); -void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); -void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan); -void sngisdn_snd_progress(ftdm_channel_t *ftdmchan); -void sngisdn_snd_connect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan); -void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare); - void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) { @@ -147,6 +140,7 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); + cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data); cpy_calling_name_from_user(&conEvnt, ftdmchan); ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index e2d85f7ea1..896b8eebd8 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1011,13 +1011,15 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) } alarms = tdm_api.wp_tdm_cmd.fe_alarms; #endif -#if 1 - /* DAVIDY - Temporary fix: in the current trunk of libsangoma, for BRI, +#ifdef WIN32 + /* Temporary fix: in the current trunk of libsangoma, for BRI, WAN_TE_BIT_ALARM_RED bit is set if the card is in disconnected state, but this has not been ported to Windows-libsangoma yet */ - if (alarms) { - ftdmchan->alarm_flags |= FTDM_ALARM_RED; - alarms = 0; + if (FTDM_SPAN_IS_BRI(ftdmchan->span)) { + if (alarms) { + ftdmchan->alarm_flags |= FTDM_ALARM_RED; + alarms = 0; + } } #endif @@ -1027,6 +1029,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms) ftdmchan->alarm_flags |= FTDM_ALARM_RED; alarms &= ~WAN_TE_BIT_ALARM_RED; } + if (alarms & WAN_TE_BIT_ALARM_AIS) { ftdmchan->alarm_flags |= FTDM_ALARM_BLUE; @@ -1176,6 +1179,11 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; event_id = FTDM_OOB_NOOP; + if (tmp_dtmf[0] == 'f') { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring wanpipe DTMF: %c, fax tones will be passed through!\n", tmp_dtmf[0]); + break; + } + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_MUTE); } diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c index ae9398418a..692b505716 100644 --- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c +++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c @@ -867,7 +867,7 @@ static FIO_WAIT_FUNCTION(zt_wait) { int32_t inflags = 0; int result; - struct pollfd pfds[1]; + struct pollfd pfds[1]; if (*flags & FTDM_READ) { inflags |= POLLIN; @@ -882,13 +882,14 @@ static FIO_WAIT_FUNCTION(zt_wait) } - memset(&pfds[0], 0, sizeof(pfds[0])); - pfds[0].fd = ftdmchan->sockfd; - pfds[0].events = inflags; - result = poll(pfds, 1, to); + memset(&pfds[0], 0, sizeof(pfds[0])); + pfds[0].fd = ftdmchan->sockfd; + pfds[0].events = inflags; + result = poll(pfds, 1, to); *flags = 0; if (pfds[0].revents & POLLERR) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "DAHDI device got POLLERR\n"); result = -1; } @@ -900,6 +901,7 @@ static FIO_WAIT_FUNCTION(zt_wait) if (result < 0){ snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Poll failed"); + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to poll DAHDI device: %s\n", strerror(errno)); return FTDM_FAIL; } diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 239eb4a3d9..c5f3c4b821 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -223,7 +223,6 @@ extern "C" { #define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119) #define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP) - /*! \brief Copy flags from one arbitrary object to another \command dest the object to copy the flags to diff --git a/libs/libsndfile/M4/lt~obsolete.m4 b/libs/libsndfile/M4/lt~obsolete.m4 index 637bb2066c..c573da90c5 100644 --- a/libs/libsndfile/M4/lt~obsolete.m4 +++ b/libs/libsndfile/M4/lt~obsolete.m4 @@ -1,13 +1,13 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 4 lt~obsolete.m4 +# serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # @@ -77,7 +77,6 @@ m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) @@ -90,3 +89,10 @@ m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c b/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c index 937c67b328..dc2218012e 100644 --- a/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c +++ b/libs/openzap/src/ozmod/ozmod_sangoma_boost/ozmod_sangoma_boost.c @@ -898,7 +898,7 @@ tryagain: static void handle_call_loop_start(zap_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event) { - zap_status_t res = ZAP_FAIL; + zap_state_change_result_t res = ZAP_FAIL; zap_channel_t *zchan; if (!(zchan = find_zchan(span, (sangomabc_short_event_t*)event, 0))) { @@ -923,7 +923,7 @@ static void handle_call_loop_start(zap_span_t *span, sangomabc_connection_t *mco static __inline__ void stop_loop(zap_channel_t *zchan) { - zap_status_t res = ZAP_FAIL; + zap_state_change_result_t res = ZAP_STATE_CHANGE_FAIL; zap_channel_command(zchan, ZAP_COMMAND_DISABLE_LOOP, NULL); /* even when we did not sent a msg we set this flag to avoid sending call stop in the DOWN state handler */ zap_set_flag(zchan, SFLAG_SENT_FINAL_MSG); diff --git a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c index 40cf2a5a7c..8423aac34b 100644 --- a/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c +++ b/libs/openzap/src/ozmod/ozmod_wanpipe/ozmod_wanpipe.c @@ -1119,7 +1119,14 @@ ZIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event) event_id = ZAP_OOB_NOOP; //zap_log(ZAP_LOG_WARNING, "%d:%d queue hardware dtmf %s %s\n", zchan->span_id, zchan->chan_id, tmp_dtmf, - //tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT ? "on" : "off"); + //tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT ? "on" : "off"); + if (tmp_dtmf[0] == 'f') { + if (zap_test_flag(zchan, ZAP_CHANNEL_INUSE)) { + zap_channel_queue_dtmf(zchan, tmp_dtmf); + } + break; + } + if (tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_type == WAN_EC_TONE_PRESENT) { zap_set_flag_locked(zchan, ZAP_CHANNEL_MUTE); } diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index ec0a895cdb..aacfc996d3 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Mon May 31 09:47:08 EDT 2010 +Wed Nov 3 13:53:34 EDT 2010 diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 40ee1f8f85..f77cdd3afa 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -1674,7 +1674,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags) progress = 60 * 1000; agent->sa_progress = progress; - if (server_rport > 2) + if (server_rport > 3) server_rport = 1; else if (server_rport < 0) server_rport = 1; @@ -3084,7 +3084,9 @@ int agent_check_request_via(nta_agent_t *agent, rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port)); msg_header_replace_param(msg_home(msg), v->v_common, rport); } - else if (agent->sa_server_rport == 2) { + else if (agent->sa_server_rport == 2 || + (agent->sa_server_rport == 3 && sip && sip->sip_user_agent && + sip->sip_user_agent->g_string && !strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7))) { rport = su_sprintf(msg_home(msg), "rport=%u", ntohs(from->su_port)); msg_header_replace_param(msg_home(msg), v->v_common, rport); } @@ -8174,9 +8176,12 @@ outgoing_send(nta_outgoing_t *orq, int retransmit) if (orq->orq_method == sip_method_ack) ; - else if (!orq->orq_reliable) - outgoing_set_timer(orq, agent->sa_t1); /* Timer A/E */ - else if (orq->orq_try_tcp_instead && !tport_is_connected(tp)) + else if (!orq->orq_reliable) { + /* race condition on initial t1 timer timeout, set minimum initial timeout to 1000ms */ + unsigned t1_timer = agent->sa_t1; + if (t1_timer < 1000) t1_timer = 1000; + outgoing_set_timer(orq, t1_timer); /* Timer A/E */ + } else if (orq->orq_try_tcp_instead && !tport_is_connected(tp)) outgoing_set_timer(orq, agent->sa_t4); /* Timer N3 */ } @@ -8660,6 +8665,10 @@ void outgoing_destroy(nta_outgoing_t *orq) orq->orq_destroyed = 1; orq->orq_callback = outgoing_default_cb; orq->orq_magic = NULL; + + if (orq->orq_method != sip_method_invite && + orq->orq_method != sip_method_ack) + outgoing_terminate(orq); } /** @internal Outgoing transaction timer routine. diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c index 866ae57616..f305a0f3df 100644 --- a/libs/stfu/stfu.c +++ b/libs/stfu/stfu.c @@ -280,7 +280,8 @@ stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i) i->miss_count++; - if (i->miss_count > 10 || (i->in_queue->array_len == i->in_queue->array_size) || tried >= i->in_queue->array_size) { + if (i->miss_count > 10 || (i->in_queue->array_len == i->in_queue->array_size) || + tried >= (i->in_queue->array_size + i->out_queue->array_size)) { i->running = 0; i->interval = 0; i->out_queue->wr_len = i->out_queue->array_size; diff --git a/libs/win32/Sound_Files/16khz.2008.vcproj b/libs/win32/Sound_Files/16khz.2008.vcproj index d8f80bbde6..026987197d 100644 --- a/libs/win32/Sound_Files/16khz.2008.vcproj +++ b/libs/win32/Sound_Files/16khz.2008.vcproj @@ -11,6 +11,9 @@ + @@ -33,7 +36,7 @@ /> + + + + + + + + + + + + diff --git a/libs/win32/Sound_Files/16khzmusic.2008.vcproj b/libs/win32/Sound_Files/16khzmusic.2008.vcproj index 932d1c5b4f..c09a5aec90 100644 --- a/libs/win32/Sound_Files/16khzmusic.2008.vcproj +++ b/libs/win32/Sound_Files/16khzmusic.2008.vcproj @@ -11,6 +11,9 @@ + @@ -58,6 +61,51 @@ CommandLine="xcopy "$(SolutionDir)libs\sounds\music\16000\*.*" "$(OutDir)\sounds\music\16000" /C /D /Y /S /I " /> + + + + + + + + + + + + diff --git a/libs/win32/Sound_Files/32khz.2008.vcproj b/libs/win32/Sound_Files/32khz.2008.vcproj index d2ac0af2e3..cdf3fa93fc 100644 --- a/libs/win32/Sound_Files/32khz.2008.vcproj +++ b/libs/win32/Sound_Files/32khz.2008.vcproj @@ -11,6 +11,9 @@ + @@ -33,7 +36,7 @@ /> + + + + + + + + + + + + diff --git a/libs/win32/Sound_Files/32khzmusic.2008.vcproj b/libs/win32/Sound_Files/32khzmusic.2008.vcproj index aafc1ef50d..7ff356e038 100644 --- a/libs/win32/Sound_Files/32khzmusic.2008.vcproj +++ b/libs/win32/Sound_Files/32khzmusic.2008.vcproj @@ -11,6 +11,9 @@ + @@ -58,6 +61,51 @@ CommandLine="xcopy "$(SolutionDir)libs\sounds\music\32000\*.*" "$(OutDir)\sounds\music\32000" /C /D /Y /S /I" /> + + + + + + + + + + + + diff --git a/libs/win32/Sound_Files/8khz.2008.vcproj b/libs/win32/Sound_Files/8khz.2008.vcproj index 413c47dc63..5f6d36803e 100644 --- a/libs/win32/Sound_Files/8khz.2008.vcproj +++ b/libs/win32/Sound_Files/8khz.2008.vcproj @@ -11,6 +11,9 @@ + @@ -33,7 +36,7 @@ /> + + + + + + + + + + + + diff --git a/libs/win32/Sound_Files/8khzmusic.2008.vcproj b/libs/win32/Sound_Files/8khzmusic.2008.vcproj index 2e46ecff8e..a89d14f9f0 100644 --- a/libs/win32/Sound_Files/8khzmusic.2008.vcproj +++ b/libs/win32/Sound_Files/8khzmusic.2008.vcproj @@ -11,6 +11,9 @@ + @@ -58,6 +61,51 @@ CommandLine="xcopy "$(SolutionDir)libs\sounds\music\8000\*.*" "$(OutDir)\sounds\music\8000" /C /D /Y /S /I " /> + + + + + + + + + + + + diff --git a/libs/win32/json/libjson.2008.vcproj b/libs/win32/json/libjson.2008.vcproj index 91a371b48c..5c09e5413c 100644 --- a/libs/win32/json/libjson.2008.vcproj +++ b/libs/win32/json/libjson.2008.vcproj @@ -172,7 +172,7 @@ Optimization="2" EnableIntrinsicFunctions="true" AdditionalIncludeDirectories="." - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS" RuntimeLibrary="2" EnableFunctionLevelLinking="true" UsePrecompiledHeader="0" @@ -236,7 +236,7 @@ Optimization="2" EnableIntrinsicFunctions="true" AdditionalIncludeDirectories="." - PreprocessorDefinitions="WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS" + PreprocessorDefinitions="WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS" RuntimeLibrary="2" EnableFunctionLevelLinking="true" UsePrecompiledHeader="0" diff --git a/libs/win32/json/libjson.2010.vcxproj b/libs/win32/json/libjson.2010.vcxproj index 5846ff3e92..a371ac2f46 100644 --- a/libs/win32/json/libjson.2010.vcxproj +++ b/libs/win32/json/libjson.2010.vcxproj @@ -96,7 +96,7 @@ MaxSpeed true .;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 @@ -110,7 +110,7 @@ MaxSpeed true .;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;HAVE_CONFIG_H;HAVE_STDARG_H;STDC_HEADERS;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 diff --git a/libs/win32/openssl/libeay32.2008.vcproj b/libs/win32/openssl/libeay32.2008.vcproj index 84cc80b4ee..5681c7cfb9 100644 --- a/libs/win32/openssl/libeay32.2008.vcproj +++ b/libs/win32/openssl/libeay32.2008.vcproj @@ -32,7 +32,7 @@ > - copy /Y $(ProjectDir)opensslconf.h $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h -copy /Y $(ProjectDir)applink.c $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c -copy /Y $(ProjectDir)buildinf.h $(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h -copy /Y $(ProjectDir)libeay32.def $(ProjectDir)..\..\openssl-1.0.0a\libeay32.def + copy /Y "$(ProjectDir)opensslconf.h" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h" +copy /Y "$(ProjectDir)applink.c" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c" +copy /Y "$(ProjectDir)buildinf.h" "$(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h" +copy /Y "$(ProjectDir)libeay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\libeay32.def" if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$(ProjectDir)\include\*.*" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\" /C /Y /S @@ -115,10 +115,10 @@ if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$ - copy /Y $(ProjectDir)opensslconf.h $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h -copy /Y $(ProjectDir)applink.c $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c -copy /Y $(ProjectDir)buildinf.h $(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h -copy /Y $(ProjectDir)libeay32.def $(ProjectDir)..\..\openssl-1.0.0a\libeay32.def + copy /Y "$(ProjectDir)opensslconf.h" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h" +copy /Y "$(ProjectDir)applink.c" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c" +copy /Y "$(ProjectDir)buildinf.h" "$(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h" +copy /Y "$(ProjectDir)libeay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\libeay32.def" if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$(ProjectDir)\include\*.*" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\" /C /Y /S @@ -151,10 +151,10 @@ if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$ - copy /Y $(ProjectDir)opensslconf.h $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h -copy /Y $(ProjectDir)applink.c $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c -copy /Y $(ProjectDir)buildinf.h $(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h -copy /Y $(ProjectDir)libeay32.def $(ProjectDir)..\..\openssl-1.0.0a\libeay32.def + copy /Y "$(ProjectDir)opensslconf.h" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h" +copy /Y "$(ProjectDir)applink.c" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c" +copy /Y "$(ProjectDir)buildinf.h" "$(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h" +copy /Y "$(ProjectDir)libeay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\libeay32.def" if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$(ProjectDir)\include\*.*" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\" /C /Y /S @@ -185,10 +185,10 @@ if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$ - copy /Y $(ProjectDir)opensslconf.h $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h -copy /Y $(ProjectDir)applink.c $(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c -copy /Y $(ProjectDir)buildinf.h $(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h -copy /Y $(ProjectDir)libeay32.def $(ProjectDir)..\..\openssl-1.0.0a\libeay32.def + copy /Y "$(ProjectDir)opensslconf.h" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\opensslconf.h" +copy /Y "$(ProjectDir)applink.c" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\applink.c" +copy /Y "$(ProjectDir)buildinf.h" "$(ProjectDir)..\..\openssl-1.0.0a\crypto\buildinf.h" +copy /Y "$(ProjectDir)libeay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\libeay32.def" if not exist "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\e_os.h" xcopy "$(ProjectDir)\include\*.*" "$(ProjectDir)..\..\openssl-1.0.0a\include\openssl\" /C /Y /S diff --git a/libs/win32/openssl/ssleay32.2008.vcproj b/libs/win32/openssl/ssleay32.2008.vcproj index 1d8654a882..fef7e5c947 100644 --- a/libs/win32/openssl/ssleay32.2008.vcproj +++ b/libs/win32/openssl/ssleay32.2008.vcproj @@ -29,7 +29,7 @@ > - copy /Y $(ProjectDir)ssleay32.def $(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def + copy /Y "$(ProjectDir)ssleay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def" /Gs0 %(AdditionalOptions) @@ -107,7 +107,7 @@ - copy /Y $(ProjectDir)ssleay32.def $(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def + copy /Y "$(ProjectDir)ssleay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def" /Gs0 %(AdditionalOptions) @@ -134,7 +134,7 @@ - copy /Y $(ProjectDir)ssleay32.def $(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def + copy /Y "$(ProjectDir)ssleay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def" X64 @@ -164,7 +164,7 @@ - copy /Y $(ProjectDir)ssleay32.def $(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def + copy /Y "$(ProjectDir)ssleay32.def" "$(ProjectDir)..\..\openssl-1.0.0a\ssleay32.def" X64 diff --git a/src/fs_encode.c b/src/fs_encode.c new file mode 100644 index 0000000000..9517802600 --- /dev/null +++ b/src/fs_encode.c @@ -0,0 +1,246 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2010, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Mathieu Rene + * + * fs_encode.c -- Encode a native file + * + */ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 +#endif + +#ifndef WIN32 +#ifdef HAVE_SETRLIMIT +#include +#endif +#endif + +#include +#include + + +/* Picky compiler */ +#ifdef __ICC +#pragma warning (disable:167) +#endif + +int main(int argc, char *argv[]) +{ + int r = 1; + switch_bool_t verbose = SWITCH_FALSE; + const char *err = NULL; + int i; + char *extra_modules[100] = { 0 }; + int extra_modules_count = 0; + int cmd_fail = 0; + const char *fmtp = ""; + int ptime = 20; + const char *input, *output, *format = NULL; + int channels = 1; + int rate = 8000; + switch_file_handle_t fh_input = { 0 }, fh_output = { 0 }; + switch_codec_t codec = { 0 }; + char buf[2048]; + switch_size_t len = sizeof(buf)/2; + switch_memory_pool_t *pool; + int bitrate = 0; + int blocksize; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch(argv[i][1]) { + case 'l': + i++; + /* Load extra modules */ + if (strchr(argv[i], ',')) { + extra_modules_count = switch_split(argv[i], ',', extra_modules); + } else { + extra_modules_count = 1; + extra_modules[0] = argv[i]; + } + break; + case 'f': + fmtp = argv[++i]; + break; + case 'p': + ptime = atoi(argv[++i]); + break; + case 'r': + rate = atoi(argv[++i]); + break; + case 'b': + bitrate = atoi(argv[++i]); + break; + case 'v': + verbose = SWITCH_TRUE; + break; + default: + printf("Command line option not recognized: %s\n", argv[i]); + cmd_fail = 1; + } + } else { + break; + } + } + + if (argc - i < 2 || cmd_fail) { + goto usage; + } + + input = argv[i++]; + output = argv[i++]; + if (zstr(input) || zstr(output) || !(format = strchr(output, '.'))) { + goto usage; + } + + format++; + + if (switch_core_init(SCF_MINIMAL, verbose, &err) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot init core [%s]\n", err); + goto end; + } + + switch_loadable_module_init(SWITCH_FALSE); + + for (i = 0; i < extra_modules_count; i++) { + if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) extra_modules[i], SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot init %s [%s]\n", extra_modules[i], err); + goto end; + } + } + + if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) "mod_sndfile", SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot init mod_sndfile [%s]\n", err); + goto end; + } + + if (switch_loadable_module_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) "mod_native_file", SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot init mod_native_file [%s]\n", err); + goto end; + } + + switch_core_new_memory_pool(&pool); + if (verbose) { + fprintf(stderr, "Opening file %s\n", input); + } + if (switch_core_file_open(&fh_input, input, channels, rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Couldn't open %s\n", input); + goto end; + } + + + if (verbose) { + fprintf(stderr, "Opening file %s\n", output); + } + if (switch_core_file_open(&fh_output, output, channels, rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_NATIVE, NULL) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Couldn't open %s\n", output); + goto end; + } + + if (switch_test_flag(&fh_input, SWITCH_FILE_NATIVE)) { + fprintf(stderr, "Input as native file is not implemented\n"); + goto end; + } + + if (switch_core_codec_init_with_bitrate(&codec, format, fmtp, rate, ptime, channels, bitrate, SWITCH_CODEC_FLAG_ENCODE, NULL, pool) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Couldn't initialize codec for %s@%dh@%di\n", format, rate, ptime); + goto end; + } + + blocksize = len = (rate*ptime)/1000; + switch_assert(sizeof(buf) >= len * 2); + + if (verbose) { + fprintf(stderr, "Frame size is %d\n", blocksize); + } + + while (switch_core_file_read(&fh_input, buf, &len) == SWITCH_STATUS_SUCCESS) { + char encode_buf[2048]; + uint32_t encoded_len = sizeof(buf); + uint32_t encoded_rate = rate; + unsigned int flags = 0; + + if (switch_core_codec_encode(&codec, NULL, buf, len*2, rate, encode_buf, &encoded_len, &encoded_rate, &flags) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Codec encoder error\n"); + goto end; + } + + len = encoded_len; + + if (switch_core_file_write(&fh_output, encode_buf, &len) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Write error\n"); + goto end; + } + + if (len != encoded_len) { + printf("Short write: wrote %"SWITCH_SIZE_T_FMT"/%d bytes\n", len, encoded_len); + } + + len = blocksize; + } + + r = 0; + +end: + + switch_core_codec_destroy(&codec); + + if (fh_input.file_interface) { + switch_core_file_close(&fh_input); + } + + if (fh_output.file_interface) { + switch_core_file_close(&fh_output); + } + + if (pool) { + switch_core_destroy_memory_pool(&pool); + } + switch_core_destroy(); + return r; +usage: + printf("Usage: %s [options] input output\n\n", argv[0]); + printf("The output must end in the format, e.g., myfile.SPEEX\n"); + printf("\t\t -l module[,module]\t Load additional modules (comma-separated)\n"); + printf("\t\t -f format\t\t fmtp to pass to the codec\n"); + printf("\t\t -p ptime\t\t ptime to use while encoding\n"); + printf("\t\t -r rate\t\t sampling rate\n"); + printf("\t\t -b bitrate\t\t codec bitrate (if supported)\n"); + printf("\t\t -v\t\t\t verbose\n"); + return 1; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index ea02f22fa0..3df9001b0c 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -193,6 +193,11 @@ struct switch_media_bug { struct switch_media_bug *next; }; +typedef enum { + DBTYPE_DEFAULT = 0, + DBTYPE_MSSQL = 1, +} switch_dbtype_t; + struct switch_runtime { switch_time_t initiated; switch_time_t reference; @@ -237,6 +242,7 @@ struct switch_runtime { double min_idle_time; int sql_buffer_len; int max_sql_buffer_len; + switch_dbtype_t odbc_dbtype; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_core_event_hook.h b/src/include/switch_core_event_hook.h index b60246cf24..575786f5ce 100644 --- a/src/include/switch_core_event_hook.h +++ b/src/include/switch_core_event_hook.h @@ -45,6 +45,7 @@ typedef struct switch_io_event_hook_kill_channel switch_io_event_hook_kill_chann typedef struct switch_io_event_hook_send_dtmf switch_io_event_hook_send_dtmf_t; typedef struct switch_io_event_hook_recv_dtmf switch_io_event_hook_recv_dtmf_t; typedef struct switch_io_event_hook_state_change switch_io_event_hook_state_change_t; +typedef struct switch_io_event_hook_state_run switch_io_event_hook_state_run_t; typedef struct switch_io_event_hook_resurrect_session switch_io_event_hook_resurrect_session_t; typedef switch_status_t (*switch_outgoing_channel_hook_t) (switch_core_session_t *, switch_event_t *, switch_caller_profile_t *, switch_core_session_t *, switch_originate_flag_t); @@ -58,6 +59,7 @@ typedef switch_status_t (*switch_kill_channel_hook_t) (switch_core_session_t *, typedef switch_status_t (*switch_send_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction); typedef switch_status_t (*switch_recv_dtmf_hook_t) (switch_core_session_t *, const switch_dtmf_t *, switch_dtmf_direction_t direction); typedef switch_status_t (*switch_state_change_hook_t) (switch_core_session_t *); +typedef switch_status_t (*switch_state_run_hook_t) (switch_core_session_t *); typedef switch_call_cause_t (*switch_resurrect_session_hook_t) (switch_core_session_t **, switch_memory_pool_t **, void *); /*! \brief Node in which to store custom receive message callback hooks */ @@ -136,6 +138,13 @@ struct switch_io_event_hook_state_change { struct switch_io_event_hook_state_change *next; }; +/*! \brief Node in which to store state run callback hooks */ +struct switch_io_event_hook_state_run { + /*! the state run channel callback hook */ + switch_state_run_hook_t state_run; + struct switch_io_event_hook_state_run *next; +}; + struct switch_io_event_hook_resurrect_session { switch_resurrect_session_hook_t resurrect_session; @@ -166,6 +175,7 @@ struct switch_io_event_hooks { switch_io_event_hook_recv_dtmf_t *recv_dtmf; /*! a list of state change hooks */ switch_io_event_hook_state_change_t *state_change; + switch_io_event_hook_state_run_t *state_run; switch_io_event_hook_resurrect_session_t *resurrect_session; }; @@ -218,6 +228,7 @@ NEW_HOOK_DECL_ADD_P(outgoing_channel); NEW_HOOK_DECL_ADD_P(receive_message); NEW_HOOK_DECL_ADD_P(receive_event); NEW_HOOK_DECL_ADD_P(state_change); +NEW_HOOK_DECL_ADD_P(state_run); NEW_HOOK_DECL_ADD_P(read_frame); NEW_HOOK_DECL_ADD_P(write_frame); NEW_HOOK_DECL_ADD_P(video_read_frame); @@ -231,6 +242,7 @@ NEW_HOOK_DECL_REM_P(outgoing_channel); NEW_HOOK_DECL_REM_P(receive_message); NEW_HOOK_DECL_REM_P(receive_event); NEW_HOOK_DECL_REM_P(state_change); +NEW_HOOK_DECL_REM_P(state_run); NEW_HOOK_DECL_REM_P(read_frame); NEW_HOOK_DECL_REM_P(write_frame); NEW_HOOK_DECL_REM_P(video_read_frame); diff --git a/src/include/switch_event.h b/src/include/switch_event.h index 1864e397e6..41bc75cada 100644 --- a/src/include/switch_event.h +++ b/src/include/switch_event.h @@ -345,11 +345,15 @@ SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(_In_z_ char */ #define switch_event_create(event, id) switch_event_create_subclass(event, id, SWITCH_EVENT_SUBCLASS_ANY) - static inline switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id) +static inline switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id) { switch_status_t status = switch_event_create(event, SWITCH_EVENT_CLONE); if (status == SWITCH_STATUS_SUCCESS) { (*event)->event_id = event_id; + + if (event_id == SWITCH_EVENT_REQUEST_PARAMS || event_id == SWITCH_EVENT_CHANNEL_DATA) { + (*event)->flags |= EF_UNIQ_HEADERS; + } } return status; diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index fb023848ec..249ac63a58 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -840,11 +840,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_say_ip(switch_core_session_t *session SWITCH_DECLARE(switch_status_t) switch_ivr_set_user(switch_core_session_t *session, const char *data); SWITCH_DECLARE(switch_status_t) switch_ivr_sound_test(switch_core_session_t *session); -SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname); +SWITCH_DECLARE(void) switch_process_import(switch_core_session_t *session, switch_channel_t *peer_channel, const char *varname, const char *prefix); SWITCH_DECLARE(switch_bool_t) switch_ivr_uuid_exists(const char *uuid); +SWITCH_DECLARE(void) switch_ivr_dmachine_set_match_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t match_callback); +SWITCH_DECLARE(void) switch_ivr_dmachine_set_nonmatch_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t nonmatch_callback); SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t **dmachine_p, const char *name, switch_memory_pool_t *pool, diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index a6013a9386..ae0ce900a9 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -134,6 +134,7 @@ typedef switch_status_t (*switch_io_send_dtmf_t) (switch_core_session_t *, const typedef switch_status_t (*switch_io_receive_message_t) (switch_core_session_t *, switch_core_session_message_t *); typedef switch_status_t (*switch_io_receive_event_t) (switch_core_session_t *, switch_event_t *); typedef switch_status_t (*switch_io_state_change_t) (switch_core_session_t *); +typedef switch_status_t (*switch_io_state_run_t) (switch_core_session_t *); typedef switch_status_t (*switch_io_read_video_frame_t) (switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int); typedef switch_status_t (*switch_io_write_video_frame_t) (switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int); typedef switch_call_cause_t (*switch_io_resurrect_session_t) (switch_core_session_t **, switch_memory_pool_t **, void *); @@ -174,6 +175,8 @@ struct switch_io_routines { switch_io_read_video_frame_t read_video_frame; /*! write a video frame to a session */ switch_io_write_video_frame_t write_video_frame; + /*! change a sessions channel run state */ + switch_io_state_run_t state_run; /*! resurrect a session */ switch_io_resurrect_session_t resurrect_session; void *padding[10]; diff --git a/src/include/switch_odbc.h b/src/include/switch_odbc.h index 81039f113d..b8d4bc2f17 100644 --- a/src/include/switch_odbc.h +++ b/src/include/switch_odbc.h @@ -58,6 +58,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_ char **err); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err); SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void); +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on); +SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit); SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt); /*! diff --git a/src/include/switch_types.h b/src/include/switch_types.h index b1fc627354..272d435068 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -840,6 +840,7 @@ typedef enum { SWITCH_STATUS_IGNORE, SWITCH_STATUS_TOO_SMALL, SWITCH_STATUS_FOUND, + SWITCH_STATUS_CONTINUE, SWITCH_STATUS_NOT_INITALIZED } switch_status_t; @@ -1063,6 +1064,7 @@ typedef enum { CF_CONSUME_ON_ORIGINATE, CF_PASSTHRU_PTIME_MISMATCH, CF_BRIDGE_NOWRITE, + CF_RECOVERED, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; @@ -1266,7 +1268,8 @@ typedef enum { SMBF_STEREO = (1 << 5), SMBF_ANSWER_REQ = (1 << 6), SMBF_THREAD_LOCK = (1 << 7), - SMBF_PRUNE = (1 << 8) + SMBF_PRUNE = (1 << 8), + SMBF_NO_PAUSE = (1 << 9) } switch_media_bug_flag_enum_t; typedef uint32_t switch_media_bug_flag_t; @@ -1304,7 +1307,8 @@ typedef enum { SWITCH_FILE_CALLBACK = (1 << 12), SWITCH_FILE_DONE = (1 << 13), SWITCH_FILE_BUFFER_DONE = (1 << 14), - SWITCH_FILE_WRITE_APPEND = (1 << 15) + SWITCH_FILE_WRITE_APPEND = (1 << 15), + SWITCH_FILE_WRITE_OVER = (1 << 16) } switch_file_flag_enum_t; typedef uint32_t switch_file_flag_t; diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 945583ee07..3a4f8b253b 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -322,7 +322,7 @@ SWITCH_DECLARE(unsigned char) switch_char_to_rfc2833(char key); \param key the key to test \return TRUE or FALSE */ -#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119 || key == 70) +#define is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119 || key == 70 || key == 102) #define end_of(_s) *(*_s == '\0' ? _s : _s + strlen(_s) - 1) #define end_of_p(_s) (*_s == '\0' ? _s : _s + strlen(_s) - 1) @@ -711,7 +711,7 @@ SWITCH_DECLARE(int) switch_inet_pton(int af, const char *src, void *dst); SWITCH_DECLARE(const char *) switch_dow_int2str(int val); SWITCH_DECLARE(int) switch_dow_str2int(const char *exp); -SWITCH_DECLARE(int) switch_dow_cmp(const char *exp, int val); +SWITCH_DECLARE(switch_bool_t) switch_dow_cmp(const char *exp, int val); SWITCH_DECLARE(int) switch_number_cmp(const char *exp, int val); SWITCH_DECLARE(int) switch_tod_cmp(const char *exp, int val); diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index ddd2cd5175..1b0ba1331a 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -37,7 +37,6 @@ #define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby" #define CC_SQLITE_DB_NAME "callcenter" -#define CC_MAX_TIME_DIFF_CHECK 5 /* TODO drop caller if no agent login dont allow new caller @@ -429,6 +428,7 @@ struct cc_queue { uint32_t max_wait_time; uint32_t max_wait_time_with_no_agent; + uint32_t max_wait_time_with_no_agent_time_reached; switch_mutex_t *mutex; @@ -540,6 +540,7 @@ cc_queue_t *queue_set_config(cc_queue_t *queue) SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL); SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent-time-reached", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent_time_reached, 5, &config_int_0_86400, NULL, NULL); switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT); @@ -850,7 +851,7 @@ cc_status_t cc_agent_del(const char *agent) return result; } -cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, size_t ret_result_size) +cc_status_t cc_agent_get(const char *key, const char *agent, char *ret_result, size_t ret_result_size) { cc_status_t result = CC_STATUS_SUCCESS; char *sql; @@ -890,7 +891,7 @@ cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_res done: if (result == CC_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Get Info Agent %s set %s = %s\n", agent, key, res); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Get Info Agent %s %s = %s\n", agent, key, res); } return result; @@ -2023,7 +2024,7 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj } /* Will drop the caller if no agent was found for more than X secondes */ - if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - CC_MAX_TIME_DIFF_CHECK && + if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - queue->max_wait_time_with_no_agent_time_reached && queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) { m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT; switch_channel_set_flag_value(member_channel, CF_BREAK, 2); @@ -2465,9 +2466,10 @@ SWITCH_STANDARD_API(cc_config_api_function) } else { const char *key = argv[0 + initial_argc]; const char *agent = argv[1 + initial_argc]; - switch (cc_agent_get(key, agent, NULL, 0)) { + char ret[64]; + switch (cc_agent_get(key, agent, ret, sizeof(ret))) { case CC_STATUS_SUCCESS: - stream->write_function(stream, "%s", "+OK\n"); + stream->write_function(stream, "%s", ret); break; case CC_STATUS_INVALID_KEY: stream->write_function(stream, "%s", "-ERR Invalid Agent Update KEY!\n"); @@ -2631,7 +2633,21 @@ SWITCH_STANDARD_API(cc_config_api_function) } } else if (action && !strcasecmp(action, "list")) { if (argc-initial_argc < 1) { - stream->write_function(stream, "%s", "-ERR Invalid!\n"); + switch_hash_index_t *hi; + stream->write_function(stream, "%s", "name|strategy|moh_sound|time_base_score|tier_rules_apply|tier_rule_wait_second|tier_rule_wait_multiply_level|tier_rule_no_agent_no_wait|discard_abandoned_after|abandoned_resume_allowed|max_wait_time|max_wait_time_with_no_agent|max_wait_time_with_no_agent_time_reached|record_template\n"); + switch_mutex_lock(globals.mutex); + for (hi = switch_hash_first(NULL, globals.queue_hash); hi; hi = switch_hash_next(hi)) { + void *val = NULL; + const void *key; + switch_ssize_t keylen; + cc_queue_t *queue; + switch_hash_this(hi, &key, &keylen, &val); + queue = (cc_queue_t *) val; + stream->write_function(stream, "%s|%s|%s|%s|%s|%d|%s|%s|%d|%s|%d|%d|%d|%s\n", queue->name, queue->strategy, queue->moh, queue->time_base_score, (queue->tier_rules_apply?"true":"false"), queue->tier_rule_wait_second, (queue->tier_rule_wait_multiply_level?"true":"false"), (queue->tier_rule_no_agent_no_wait?"true":"false"), queue->discard_abandoned_after, (queue->abandoned_resume_allowed?"true":"false"), queue->max_wait_time, queue->max_wait_time_with_no_agent, queue->max_wait_time_with_no_agent_time_reached, queue->record_template); + queue = NULL; + } + switch_mutex_unlock(globals.mutex); + stream->write_function(stream, "%s", "+OK\n"); goto done; } else { const char *queue_name = argv[0 + initial_argc]; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 1fb1c95c47..6c43f25d44 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2019,6 +2019,66 @@ SWITCH_STANDARD_API(transfer_function) return SWITCH_STATUS_SUCCESS; } + +#define DUAL_TRANSFER_SYNTAX " [/][/] [/][/]" +SWITCH_STANDARD_API(dual_transfer_function) +{ + switch_core_session_t *tsession = NULL, *other_session = NULL; + char *mycmd = NULL, *argv[5] = { 0 }; + int argc = 0; + char *tuuid, *dest1, *dest2, *dp1 = NULL, *dp2 = NULL, *context1 = NULL, *context2 = NULL; + + if (zstr(cmd) || !(mycmd = strdup(cmd))) { + stream->write_function(stream, "-USAGE: %s\n", DUAL_TRANSFER_SYNTAX); + return SWITCH_STATUS_SUCCESS; + } + + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (argc != 3) { + stream->write_function(stream, "-USAGE: %s\n", DUAL_TRANSFER_SYNTAX); + goto done; + } + + tuuid = argv[0]; + dest1 = argv[1]; + dest2= argv[2]; + + if ((dp1 = strchr(dest1, '/'))) { + *dp1++ = '\0'; + if ((context1 = strchr(dp1, '/'))) { + *context1++ = '\0'; + } + } + + if ((dp2 = strchr(dest2, '/'))) { + *dp2++ = '\0'; + if ((context2 = strchr(dp2, '/'))) { + *context2++ = '\0'; + } + } + + if (zstr(tuuid) || !(tsession = switch_core_session_locate(tuuid))) { + stream->write_function(stream, "-ERR No Such Channel!\n"); + goto done; + } + + if (switch_core_session_get_partner(tsession, &other_session) == SWITCH_STATUS_SUCCESS) { + switch_ivr_session_transfer(other_session, dest2, dp2, context2); + switch_core_session_rwunlock(other_session); + } + + switch_ivr_session_transfer(tsession, dest1, dp1, context1); + + stream->write_function(stream, "+OK\n"); + + switch_core_session_rwunlock(tsession); + + done: + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + #define TONE_DETECT_SYNTAX " [ ]" SWITCH_STANDARD_API(tone_detect_session_function) { @@ -3423,6 +3483,12 @@ SWITCH_STANDARD_API(show_function) char hostname[256] = ""; gethostname(hostname, sizeof(hostname)); + + if (!(cflags & SCF_USE_SQL)) { + stream->write_function(stream, "-ERR SQL DISABLED NO DATA AVAILABLE!\n"); + return SWITCH_STATUS_SUCCESS; + } + if (switch_core_db_handle(&db) != SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "%s", "-ERR Databse Error!\n"); return SWITCH_STATUS_SUCCESS; @@ -3455,11 +3521,6 @@ SWITCH_STANDARD_API(show_function) holder.print_title = 1; - if (!(cflags & SCF_USE_SQL) && command && !strcasecmp(command, "channels")) { - stream->write_function(stream, "-ERR SQL DISABLED NO CHANNEL DATA AVAILABLE!\n"); - goto end; - } - /* If you change the field qty or order of any of these select */ /* statements, you must also change show_callback and friends to match! */ if (!command) { @@ -4630,6 +4691,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_setvar_multi", "uuid_setvar_multi", uuid_setvar_multi_function, SETVAR_MULTI_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_setvar", "uuid_setvar", uuid_setvar_function, SETVAR_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_dual_transfer", "Transfer a session and its partner", dual_transfer_function, DUAL_TRANSFER_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root |
]"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " "); @@ -4749,6 +4811,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_setvar_multi ::console::list_uuid"); switch_console_set_complete("add uuid_setvar ::console::list_uuid"); switch_console_set_complete("add uuid_transfer ::console::list_uuid"); + switch_console_set_complete("add uuid_dual_transfer ::console::list_uuid"); switch_console_set_complete("add version"); switch_console_set_complete("add uuid_warning ::console::list_uuid"); switch_console_set_complete("add ..."); diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index ed62da107b..4cbb052994 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -40,6 +40,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown); SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL); +typedef enum { + CONF_SILENT_REQ = (1 << 0), + CONF_SILENT_DONE = (1 << 1) +} conf_app_flag_t; + static const char global_app_name[] = "conference"; static char *global_cf_name = "conference.conf"; static char *cf_pin_url_param_name = "X-ConfPin="; @@ -92,29 +97,6 @@ static struct { switch_event_node_t *node; } globals; -typedef enum { - CALLER_CONTROL_MUTE, - CALLER_CONTROL_MUTE_ON, - CALLER_CONTROL_MUTE_OFF, - CALLER_CONTROL_DEAF_MUTE, - CALLER_CONTROL_ENERGY_UP, - CALLER_CONTROL_ENERGY_EQU_CONF, - CALLER_CONTROL_ENERGY_DN, - CALLER_CONTROL_VOL_TALK_UP, - CALLER_CONTROL_VOL_TALK_ZERO, - CALLER_CONTROL_VOL_TALK_DN, - CALLER_CONTROL_VOL_LISTEN_UP, - CALLER_CONTROL_VOL_LISTEN_ZERO, - CALLER_CONTROL_VOL_LISTEN_DN, - CALLER_CONTROL_HANGUP, - CALLER_CONTROL_MENU, - CALLER_CONTROL_DIAL, - CALLER_CONTROL_EVENT, - CALLER_CONTROL_LOCK, - CALLER_CONTROL_TRANSFER, - CALLER_CONTROL_EXEC_APP -} caller_control_t; - /* forward declaration for conference_obj and caller_control */ struct conference_member; typedef struct conference_member conference_member_t; @@ -128,17 +110,10 @@ typedef struct call_list call_list_t; struct caller_control_actions; -typedef struct caller_control_fn_table { - char *key; - char *digits; - caller_control_t action; - void (*handler) (conference_member_t *, struct caller_control_actions *); -} caller_control_fn_table_t; - typedef struct caller_control_actions { - caller_control_fn_table_t *fndesc; char *binded_dtmf; - void *data; + char *data; + char *expanded_data; } caller_control_action_t; typedef struct caller_control_menu_info { @@ -266,12 +241,12 @@ typedef struct conference_obj { uint32_t max_members; char *maxmember_sound; uint32_t announce_count; - switch_ivr_digit_stream_parser_t *dtmf_parser; char *pin; char *pin_sound; char *bad_pin_sound; char *profile_name; char *domain; + char *caller_controls; uint32_t flags; member_flag_t mflags; switch_call_cause_t bridge_hangup_cause; @@ -357,8 +332,6 @@ struct conference_member { uint32_t resample_out_len; conference_file_node_t *fnode; conference_relationship_t *relationships; - switch_ivr_digit_stream_parser_t *dtmf_parser; - switch_ivr_digit_stream_t *digit_stream; switch_speech_handle_t lsh; switch_speech_handle_t *sh; uint32_t verbose_events; @@ -366,6 +339,7 @@ struct conference_member { uint32_t avg_itt; uint32_t avg_tally; struct conference_member *next; + switch_ivr_dmachine_t *dmachine; }; /* Record Node */ @@ -409,6 +383,7 @@ static void conference_send_all_dtmf(conference_member_t *member, conference_obj static switch_status_t conference_say(conference_obj_t *conference, const char *text, uint32_t leadin); static void conference_list(conference_obj_t *conference, switch_stream_handle_t *stream, char *delim); static conference_obj_t *conference_find(char *name); +static void member_bind_controls(conference_member_t *member, const char *controls); SWITCH_STANDARD_API(conf_api_main); @@ -651,6 +626,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe char msg[512]; /* conference count announcement */ call_list_t *call_list = NULL; switch_channel_t *channel; + const char *controls = NULL; switch_assert(conference != NULL); switch_assert(member != NULL); @@ -698,20 +674,21 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_clear_flag(conference, CFLAG_WAIT_MOD); } + channel = switch_core_session_get_channel(member->session); + switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id); + if (conference->count > 1) { if (conference->moh_sound && !switch_test_flag(conference, CFLAG_WAIT_MOD)) { /* stop MoH if any */ conference_stop_file(conference, FILE_STOP_ASYNC); } - if (conference->enter_sound) { + + if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ) && !zstr(conference->enter_sound)) { conference_play_file(conference, conference->enter_sound, CONF_DEFAULT_LEADIN, switch_core_session_get_channel(member->session), switch_test_flag(conference, CFLAG_WAIT_MOD) ? 0 : 1); } } - channel = switch_core_session_get_channel(member->session); - switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id); - call_list = (call_list_t *) switch_channel_get_private(channel, "_conference_autocall_list_"); @@ -720,7 +697,8 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_snprintf(saymsg, sizeof(saymsg), "Auto Calling %d parties", call_list->iteration); conference_member_say(member, saymsg, 0); } else { - if (zstr(conference->special_announce)) { + + if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ)) { /* announce the total number of members in the conference */ if (conference->count >= conference->announce_count && conference->announce_count > 1) { switch_snprintf(msg, sizeof(msg), "There are %d callers", conference->count); @@ -750,13 +728,32 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_set_flag(conference, CFLAG_ENFORCE_MIN); } - if (test_eflag(conference, EFLAG_ADD_MEMBER) && + if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "add-member"); switch_event_fire(&event); } + switch_channel_clear_app_flag_key("conf_silent", channel, CONF_SILENT_REQ); + + + switch_ivr_dmachine_create(&member->dmachine, "mod_conference", NULL, 500, 0, NULL, NULL, NULL); + + controls = switch_channel_get_variable(channel, "conference_controls"); + + if (zstr(controls)) { + controls = conference->caller_controls; + } + + if (zstr(controls)) { + controls = "default"; + } + + if (strcasecmp(controls, "none")) { + member_bind_controls(member, controls); + } + } unlock_member(member); switch_mutex_unlock(member->audio_out_mutex); @@ -787,6 +784,8 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe member->sh = NULL; unlock_member(member); + switch_ivr_dmachine_destroy(&member->dmachine); + switch_mutex_lock(conference->mutex); switch_mutex_lock(conference->member_mutex); switch_mutex_lock(member->audio_in_mutex); @@ -1454,8 +1453,6 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v switch_thread_rwlock_unlock(conference->rwlock); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write Lock OFF\n"); - switch_ivr_digit_stream_parser_destroy(conference->dtmf_parser); - if (conference->sh) { switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE; switch_core_speech_close(&conference->lsh, &flags); @@ -1685,6 +1682,7 @@ static void conference_loop_fn_volume_talk_zero(conference_member_t *member, cal switch_snprintf(msg, sizeof(msg), "Volume level %d", member->volume_out_level); conference_member_say(member, msg, 0); + } static void conference_loop_fn_volume_talk_dn(conference_member_t *member, caller_control_action_t *action) @@ -1793,7 +1791,7 @@ static void conference_loop_fn_event(conference_member_t *member, caller_control conference_add_event_member_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "dtmf"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DTMF-Key", action->binded_dtmf); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Data", action->data); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Data", action->expanded_data); switch_event_fire(&event); } } @@ -1812,12 +1810,12 @@ static void conference_loop_fn_transfer(conference_member_t *member, caller_cont if (test_eflag(member->conference, EFLAG_DTMF) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "transfer"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Dialplan", action->data); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Dialplan", action->expanded_data); switch_event_fire(&event); } switch_clear_flag_locked(member, MFLAG_RUNNING); - if ((mydata = switch_core_session_strdup(member->session, action->data))) { + if ((mydata = switch_core_session_strdup(member->session, action->expanded_data))) { if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 0) { exten = argv[0]; @@ -1830,7 +1828,7 @@ static void conference_loop_fn_transfer(conference_member_t *member, caller_cont } } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty transfer string [%s]\n", (char *) action->data); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty transfer string [%s]\n", (char *) action->expanded_data); goto done; } } else { @@ -1856,14 +1854,16 @@ static void conference_loop_fn_exec_app(conference_member_t *member, caller_cont switch_event_t *event = NULL; switch_channel_t *channel = NULL; + if (!action->expanded_data) return; + if (test_eflag(member->conference, EFLAG_DTMF) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "execute_app"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", action->data); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application", action->expanded_data); switch_event_fire(&event); } - if ((mydata = switch_core_session_strdup(member->session, action->data))) { + if ((mydata = switch_core_session_strdup(member->session, action->expanded_data))) { if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { if (argc > 0) { app = argv[0]; @@ -1873,7 +1873,8 @@ static void conference_loop_fn_exec_app(conference_member_t *member, caller_cont } } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty execute app string [%s]\n", (char *) action->data); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Empty execute app string [%s]\n", + (char *) action->expanded_data); goto done; } } else { @@ -1885,6 +1886,7 @@ static void conference_loop_fn_exec_app(conference_member_t *member, caller_cont switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Unable to find application.\n"); goto done; } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Execute app: %s, %s\n", app, arg); channel = switch_core_session_get_channel(member->session); @@ -1895,6 +1897,7 @@ static void conference_loop_fn_exec_app(conference_member_t *member, caller_cont switch_core_session_set_read_codec(member->session, &member->read_codec); switch_channel_clear_app_flag(channel, CF_APP_TAGGED); done: + return; } @@ -2299,29 +2302,6 @@ static void launch_conference_loop_input(conference_member_t *member, switch_mem switch_thread_create(&thread, thd_attr, conference_loop_input, member, pool); } -static caller_control_fn_table_t ccfntbl[] = { - {"mute", "0", CALLER_CONTROL_MUTE, conference_loop_fn_mute_toggle}, - {"mute on", NULL, CALLER_CONTROL_MUTE_ON, conference_loop_fn_mute_on}, - {"mute off", NULL, CALLER_CONTROL_MUTE_OFF, conference_loop_fn_mute_off}, - {"deaf mute", "*", CALLER_CONTROL_DEAF_MUTE, conference_loop_fn_deafmute_toggle}, - {"energy up", "9", CALLER_CONTROL_ENERGY_UP, conference_loop_fn_energy_up}, - {"energy equ", "8", CALLER_CONTROL_ENERGY_EQU_CONF, conference_loop_fn_energy_equ_conf}, - {"energy dn", "7", CALLER_CONTROL_ENERGY_DN, conference_loop_fn_energy_dn}, - {"vol talk up", "3", CALLER_CONTROL_VOL_TALK_UP, conference_loop_fn_volume_talk_up}, - {"vol talk zero", "2", CALLER_CONTROL_VOL_TALK_ZERO, conference_loop_fn_volume_talk_zero}, - {"vol talk dn", "1", CALLER_CONTROL_VOL_TALK_DN, conference_loop_fn_volume_talk_dn}, - {"vol listen up", "6", CALLER_CONTROL_VOL_LISTEN_UP, conference_loop_fn_volume_listen_up}, - {"vol listen zero", "5", CALLER_CONTROL_VOL_LISTEN_ZERO, conference_loop_fn_volume_listen_zero}, - {"vol listen dn", "4", CALLER_CONTROL_VOL_LISTEN_DN, conference_loop_fn_volume_listen_dn}, - {"hangup", "#", CALLER_CONTROL_HANGUP, conference_loop_fn_hangup}, - {"event", NULL, CALLER_CONTROL_EVENT, conference_loop_fn_event}, - {"lock", NULL, CALLER_CONTROL_LOCK, conference_loop_fn_lock_toggle}, - {"transfer", NULL, CALLER_CONTROL_TRANSFER, conference_loop_fn_transfer}, - {"execute_application", NULL, CALLER_CONTROL_EXEC_APP, conference_loop_fn_exec_app} -}; - -#define CCFNTBL_QTY (sizeof(ccfntbl)/sizeof(ccfntbl[0])) - /* marshall frames from the conference (or file or tts output) to the call leg */ /* NB. this starts the input thread after some initial setup for the call leg */ static void conference_loop_output(conference_member_t *member) @@ -2392,13 +2372,6 @@ static void conference_loop_output(conference_member_t *member) /* Start the input thread */ launch_conference_loop_input(member, switch_core_session_get_pool(member->session)); - /* build a digit stream object */ - if (member->conference->dtmf_parser != NULL - && switch_ivr_digit_stream_new(member->conference->dtmf_parser, &member->digit_stream) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, - "Danger Will Robinson, there is no digit parser stream object\n"); - } - if ((call_list = switch_channel_get_private(channel, "_conference_autocall_list_"))) { const char *cid_name = switch_channel_get_variable(channel, "conference_auto_outcall_caller_id_name"); const char *cid_num = switch_channel_get_variable(channel, "conference_auto_outcall_caller_id_number"); @@ -2408,7 +2381,7 @@ static void conference_loop_output(conference_member_t *member) const char *prefix = switch_channel_get_variable(channel, "conference_auto_outcall_prefix"); int to = 60; - if (ann) { + if (ann && !switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ)) { member->conference->special_announce = switch_core_strdup(member->conference->pool, ann); } @@ -2449,9 +2422,7 @@ static void conference_loop_output(conference_member_t *member) while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(member, MFLAG_ITHREAD) && switch_channel_ready(channel)) { char dtmf[128] = ""; - char *digit; switch_event_t *event; - caller_control_action_t *caller_action = NULL; int use_timer = 0; switch_buffer_t *use_buffer = NULL; uint32_t mux_used = 0; @@ -2505,40 +2476,13 @@ static void conference_loop_output(conference_member_t *member) if (switch_test_flag(member, MFLAG_DIST_DTMF)) { conference_send_all_dtmf(member, member->conference, dtmf); - } else { - if (member->conference->dtmf_parser != NULL) { - for (digit = dtmf; *digit && caller_action == NULL; digit++) { - caller_action = (caller_control_action_t *) - switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, member->digit_stream, *digit); - } - } + } else if (member->dmachine) { + switch_ivr_dmachine_feed(member->dmachine, dtmf, NULL); } - /* otherwise, clock the parser so that it can handle digit timeout detection */ - } else if (member->conference->dtmf_parser != NULL) { - caller_action = (caller_control_action_t *) switch_ivr_digit_stream_parser_feed(member->conference->dtmf_parser, member->digit_stream, '\0'); + } else if (member->dmachine) { + switch_ivr_dmachine_ping(member->dmachine, NULL); } - /* if a caller action has been detected, handle it */ - if (caller_action != NULL && caller_action->fndesc != NULL && caller_action->fndesc->handler != NULL) { - char *param = NULL; - - if (caller_action->fndesc->action != CALLER_CONTROL_MENU) { - param = caller_action->data; - } -#ifdef INTENSE_DEBUG - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), - SWITCH_LOG_INFO, - "executing caller control '%s' param '%s' on call '%u, %s\n", - caller_action->fndesc->key, param ? param : "none", member->id, switch_channel_get_name(channel)); -#endif - - caller_action->fndesc->handler(member, caller_action); - - /* set up for next pass */ - caller_action = NULL; - } - - use_buffer = NULL; mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer); @@ -2582,6 +2526,7 @@ static void conference_loop_output(conference_member_t *member) } if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_mutex_unlock(member->audio_out_mutex); break; } } @@ -2647,10 +2592,6 @@ static void conference_loop_output(conference_member_t *member) } /* Rinse ... Repeat */ - if (member->digit_stream != NULL) { - switch_ivr_digit_stream_destroy(&member->digit_stream); - } - switch_clear_flag_locked(member, MFLAG_RUNNING); switch_core_timer_destroy(&timer); @@ -2933,6 +2874,10 @@ static switch_status_t conference_play_file(conference_obj_t *conference, char * switch_assert(conference != NULL); + if (zstr(file)) { + return SWITCH_STATUS_NOTFOUND; + } + switch_mutex_lock(conference->mutex); switch_mutex_lock(conference->member_mutex); count = conference->count; @@ -4366,8 +4311,9 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc if ((profiles = switch_xml_child(cfg, "profiles"))) { xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name); } - - xml_cfg.controls = switch_xml_child(cfg, "caller-controls"); + + /* Create the conference object. */ + new_conference = conference_new(conf_name, xml_cfg, pool); /* Release the config registry handle */ if (cxml) { @@ -4375,9 +4321,6 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc cxml = NULL; } - /* Create the conference object. */ - new_conference = conference_new(conf_name, xml_cfg, pool); - if (!new_conference) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); if (pool != NULL) { @@ -5328,7 +5271,6 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference } - /* Application interface function that is called from the dialplan to join the channel to a conference */ SWITCH_STANDARD_APP(conference_function) { @@ -5353,7 +5295,10 @@ SWITCH_STANDARD_APP(conference_function) switch_event_t *params = NULL; int locked = 0; - + if (!switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_DONE) && + (switch_channel_test_flag(channel, CF_RECOVERED) || switch_true(switch_channel_get_variable(channel, "conference_silent_entry")))) { + switch_channel_set_app_flag_key("conf_silent", channel, CONF_SILENT_REQ); + } if (switch_channel_answer(channel) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Channel answer failed.\n"); @@ -5444,8 +5389,6 @@ SWITCH_STANDARD_APP(conference_function) xml_cfg.profile = switch_xml_find_child(profiles, "profile", "name", profile_name); } - xml_cfg.controls = switch_xml_child(cfg, "caller-controls"); - /* if this is a bridging call, and it's not a duplicate, build a */ /* conference object, and skip pin handling, and locked checking */ @@ -5656,7 +5599,7 @@ SWITCH_STANDARD_APP(conference_function) } } - if (conference->special_announce) { + if (conference->special_announce && !switch_channel_test_app_flag_key("conf_silent", channel, CONF_SILENT_REQ)) { conference_local_play_file(conference, session, conference->special_announce, CONF_DEFAULT_LEADIN, NULL, 0); } @@ -5777,9 +5720,6 @@ SWITCH_STANDARD_APP(conference_function) switch_buffer_destroy(&member.resample_buffer); switch_buffer_destroy(&member.audio_buffer); switch_buffer_destroy(&member.mux_buffer); - if (conference && member.dtmf_parser != conference->dtmf_parser) { - switch_ivr_digit_stream_parser_destroy(member.dtmf_parser); - } if (conference) { switch_mutex_lock(conference->mutex); @@ -5928,88 +5868,6 @@ static switch_status_t chat_send(const char *proto, const char *from, const char return SWITCH_STATUS_SUCCESS; } -static switch_status_t conf_default_controls(conference_obj_t *conference) -{ - switch_status_t status = SWITCH_STATUS_FALSE; - uint32_t i; - caller_control_action_t *action; - - switch_assert(conference != NULL); - - for (i = 0, status = SWITCH_STATUS_SUCCESS; status == SWITCH_STATUS_SUCCESS && i < CCFNTBL_QTY; i++) { - if (!zstr(ccfntbl[i].digits)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Installing default caller control action '%s' bound to '%s'.\n", ccfntbl[i].key, ccfntbl[i].digits); - action = (caller_control_action_t *) switch_core_alloc(conference->pool, sizeof(caller_control_action_t)); - if (action != NULL) { - action->fndesc = &ccfntbl[i]; - action->data = NULL; - status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser, ccfntbl[i].digits, action); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "unable to alloc memory for caller control binding '%s' to '%s'\n", ccfntbl[i].key, ccfntbl[i].digits); - status = SWITCH_STATUS_MEMERR; - } - } - } - - return status; -} - -static switch_status_t conference_new_install_caller_controls_custom(conference_obj_t *conference, switch_xml_t xml_controls, switch_xml_t xml_menus) -{ - switch_status_t status = SWITCH_STATUS_FALSE; - switch_xml_t xml_kvp; - - switch_assert(conference != NULL); - - if (!xml_controls) { - return status; - } - - /* parse the controls tree for caller control digit strings */ - for (xml_kvp = switch_xml_child(xml_controls, "control"); xml_kvp; xml_kvp = xml_kvp->next) { - char *key = (char *) switch_xml_attr(xml_kvp, "action"); - char *val = (char *) switch_xml_attr(xml_kvp, "digits"); - char *data = (char *) switch_xml_attr_soft(xml_kvp, "data"); - - if (!zstr(key) && !zstr(val)) { - uint32_t i; - - /* scan through all of the valid actions, and if found, */ - /* set the new caller control action digit string, then */ - /* stop scanning the table, and go to the next xml kvp. */ - for (i = 0, status = SWITCH_STATUS_NOOP; i < CCFNTBL_QTY && status == SWITCH_STATUS_NOOP; i++) { - - if (strcasecmp(ccfntbl[i].key, key) == 0) { - - caller_control_action_t *action; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Installing caller control action '%s' bound to '%s'.\n", key, val); - action = (caller_control_action_t *) switch_core_alloc(conference->pool, sizeof(caller_control_action_t)); - if (action != NULL) { - action->fndesc = &ccfntbl[i]; - action->data = (void *) switch_core_strdup(conference->pool, data); - action->binded_dtmf = switch_core_strdup(conference->pool, val); - status = switch_ivr_digit_stream_parser_set_event(conference->dtmf_parser, val, action); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "unable to alloc memory for caller control binding '%s' to '%s'\n", ccfntbl[i].key, ccfntbl[i].digits); - status = SWITCH_STATUS_MEMERR; - } - } - } - if (status == SWITCH_STATUS_NOOP) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control action name '%s'.\n", key); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid caller control config entry pair action = '%s' digits = '%s'\n", key, val); - } - } - - return status; -} - static conference_obj_t *conference_find(char *name) { conference_obj_t *conference; @@ -6252,7 +6110,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m conference->comfort_noise_level = comfort_noise_level; conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name); conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number); - + conference->caller_controls = switch_core_strdup(conference->pool, caller_controls); + if (!zstr(perpetual_sound)) { conference->perpetual_sound = switch_core_strdup(conference->pool, perpetual_sound); @@ -6376,7 +6235,6 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m } conference->rate = rate; conference->interval = interval; - conference->dtmf_parser = NULL; conference->eflags = 0xFFFFFFFF; if (!zstr(suppress_events)) { @@ -6394,27 +6252,6 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m conference->verbose_events = 1; } - /* caller control configuration chores */ - if (switch_ivr_digit_stream_parser_new(conference->pool, &conference->dtmf_parser) == SWITCH_STATUS_SUCCESS) { - - /* if no controls, or default controls specified, install default */ - if (caller_controls == NULL || *caller_controls == '\0' || strcasecmp(caller_controls, "default") == 0) { - status = conf_default_controls(conference); - } else if (strcasecmp(caller_controls, "none") != 0) { - /* try to build caller control if the group has been specified and != "none" */ - switch_xml_t xml_controls = switch_xml_find_child(cfg.controls, "group", "name", caller_controls); - status = conference_new_install_caller_controls_custom(conference, xml_controls, NULL); - - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to install caller controls group '%s'\n", caller_controls); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "No caller controls installed.\n"); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to allocate caller control digit parser.\n"); - } - /* Activate the conference mutex for exclusivity */ switch_mutex_init(&conference->mutex, SWITCH_MUTEX_NESTED, conference->pool); switch_mutex_init(&conference->flag_mutex, SWITCH_MUTEX_NESTED, conference->pool); @@ -6529,6 +6366,145 @@ static void send_presence(switch_event_types_t id) } } +typedef void (*conf_key_callback_t) (conference_member_t *, struct caller_control_actions *); + +typedef struct { + conference_member_t *member; + caller_control_action_t action; + conf_key_callback_t handler; +} key_binding_t; + + +static switch_status_t dmachine_dispatcher(switch_ivr_dmachine_match_t *match) +{ + key_binding_t *binding = match->user_data; + switch_channel_t *channel; + + if (!binding) return SWITCH_STATUS_FALSE; + + channel = switch_core_session_get_channel(binding->member->session); + switch_channel_set_variable(channel, "conference_last_matching_digits", match->match_digits); + + if (binding->action.data) { + binding->action.expanded_data = switch_channel_expand_variables(channel, binding->action.data); + } + + binding->handler(binding->member, &binding->action); + + if (binding->action.expanded_data != binding->action.data) { + free(binding->action.expanded_data); + binding->action.expanded_data = NULL; + } + + switch_set_flag_locked(binding->member, MFLAG_FLUSH_BUFFER); + + return SWITCH_STATUS_SUCCESS; +} + +static void do_binding(conference_member_t *member, conf_key_callback_t handler, const char *digits, const char *data) +{ + key_binding_t *binding; + + binding = switch_core_alloc(member->pool, sizeof(*binding)); + binding->member = member; + + binding->action.binded_dtmf = switch_core_strdup(member->pool, digits); + + if (data) { + binding->action.data = switch_core_strdup(member->pool, data); + } + + binding->handler = handler; + switch_ivr_dmachine_bind(member->dmachine, "conf", digits, 0, dmachine_dispatcher, binding); + +} + +struct _mapping { + const char *name; + conf_key_callback_t handler; +}; + +static struct _mapping control_mappings[] = { + {"mute", conference_loop_fn_mute_toggle}, + {"mute on", conference_loop_fn_mute_on}, + {"mute off", conference_loop_fn_mute_off}, + {"deaf mute", conference_loop_fn_deafmute_toggle}, + {"energy up", conference_loop_fn_energy_up}, + {"energy equ", conference_loop_fn_energy_equ_conf}, + {"energy dn", conference_loop_fn_energy_dn}, + {"vol talk up", conference_loop_fn_volume_talk_up}, + {"vol talk zero", conference_loop_fn_volume_talk_zero}, + {"vol talk dn", conference_loop_fn_volume_talk_dn}, + {"vol listen up", conference_loop_fn_volume_listen_up}, + {"vol listen zero", conference_loop_fn_volume_listen_zero}, + {"vol listen dn", conference_loop_fn_volume_listen_dn}, + {"hangup", conference_loop_fn_hangup}, + {"event", conference_loop_fn_event}, + {"lock", conference_loop_fn_lock_toggle}, + {"transfer", conference_loop_fn_transfer}, + {"execute_application", conference_loop_fn_exec_app} +}; +#define MAPPING_LEN (sizeof(control_mappings)/sizeof(control_mappings[0])) + +static void member_bind_controls(conference_member_t *member, const char *controls) +{ + switch_xml_t cxml, cfg, xgroups, xcontrol; + switch_event_t *params; + int i; + + switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Conf-Name", member->conference->name); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-controls"); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Controls", controls); + + if (!(cxml = switch_xml_open_cfg(global_cf_name, &cfg, params))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf_name); + goto end; + } + + if (!(xgroups = switch_xml_child(cfg, "caller-controls"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find caller-controls in %s\n", global_cf_name); + goto end; + } + + if (!(xgroups = switch_xml_find_child(xgroups, "group", "name", controls))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find caller-controls in %s\n", global_cf_name); + goto end; + } + + + for (xcontrol = switch_xml_child(xgroups, "control"); xcontrol; xcontrol = xcontrol->next) { + const char *key = switch_xml_attr(xcontrol, "action"); + const char *digits = switch_xml_attr(xcontrol, "digits"); + const char *data = switch_xml_attr_soft(xcontrol, "data"); + + if (zstr(key) || zstr(digits)) continue; + + for(i = 0; i < MAPPING_LEN; i++) { + if (!strcasecmp(key, control_mappings[i].name)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s binding '%s' to '%s'\n", + switch_core_session_get_name(member->session), digits, key); + + do_binding(member, control_mappings[i].handler, digits, data); + } + } + } + + end: + + /* Release the config registry handle */ + if (cxml) { + switch_xml_free(cxml); + cxml = NULL; + } + + if (params) switch_event_destroy(¶ms); + +} + + + + /* Called by FreeSWITCH when the module loads */ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) { diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 06f545928d..4fd6a676ea 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -111,6 +111,8 @@ static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t switch_event_t *event; switch_status_t status; + switch_channel_set_variable(channel, "last_non_matching_digits", match->match_digits); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n", switch_channel_get_name(channel), match->match_digits); @@ -141,6 +143,8 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) char *string = act->string; switch_channel_t *channel = switch_core_session_get_channel(act->session); + switch_channel_set_variable(channel, "last_matching_digits", match->match_digits); + if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n", switch_channel_get_name(channel), act->string, act->value); diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 560b1cd6ad..3943ac6ea6 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -29,6 +29,7 @@ * */ #include +#define FIFO_APP_KEY "mod_fifo" SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown); SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load); @@ -60,7 +61,8 @@ typedef struct { typedef enum { FIFO_APP_BRIDGE_TAG = (1 << 0), - FIFO_APP_TRACKING = (1 << 1) + FIFO_APP_TRACKING = (1 << 1), + FIFO_APP_DID_HOOK = (1 << 2) } fifo_app_flag_t; @@ -306,6 +308,8 @@ struct fifo_node { int outbound_per_cycle; char *outbound_name; outbound_strategy_t outbound_strategy; + int ring_timeout; + int default_lag; }; typedef struct fifo_node fifo_node_t; @@ -864,7 +868,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses caller_channel = switch_core_session_get_channel(caller_session); } - if (switch_channel_test_app_flag(consumer_channel, FIFO_APP_BRIDGE_TAG)) { + if (switch_channel_test_app_flag_key(FIFO_APP_KEY, consumer_channel, FIFO_APP_BRIDGE_TAG)) { char date[80] = ""; switch_time_exp_t tm; switch_time_t ts = switch_micro_time_now(); @@ -874,7 +878,7 @@ static void do_unbridge(switch_core_session_t *consumer_session, switch_core_ses char *sql; switch_event_t *event; - switch_channel_clear_app_flag_key(__FILE__, consumer_channel, FIFO_APP_BRIDGE_TAG); + switch_channel_clear_app_flag_key(FIFO_APP_KEY, consumer_channel, FIFO_APP_BRIDGE_TAG); switch_channel_set_variable(consumer_channel, "fifo_bridged", NULL); ts = switch_micro_time_now(); @@ -984,11 +988,11 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ switch_size_t retsize; const char *ced_name, *ced_number, *cid_name, *cid_number; - if (switch_channel_test_app_flag(consumer_channel, FIFO_APP_BRIDGE_TAG)) { + if (switch_channel_test_app_flag_key(FIFO_APP_KEY, consumer_channel, FIFO_APP_BRIDGE_TAG)) { goto end; } - switch_channel_set_app_flag_key(__FILE__, consumer_channel, FIFO_APP_BRIDGE_TAG); + switch_channel_set_app_flag_key(FIFO_APP_KEY, consumer_channel, FIFO_APP_BRIDGE_TAG); switch_channel_set_variable(consumer_channel, "fifo_bridged", "true"); switch_channel_set_variable(consumer_channel, "fifo_manual_bridge", "true"); @@ -996,8 +1000,10 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ if (caller_channel) { switch_channel_set_variable(caller_channel, "fifo_role", "caller"); - switch_process_import(consumer_session, caller_channel, "fifo_caller_consumer_import"); - switch_process_import(caller_session, consumer_channel, "fifo_consumer_caller_import"); + switch_process_import(consumer_session, caller_channel, "fifo_caller_consumer_import", + switch_channel_get_variable(consumer_channel, "fifo_import_prefix")); + switch_process_import(caller_session, consumer_channel, "fifo_consumer_caller_import", + switch_channel_get_variable(caller_channel, "fifo_import_prefix")); } @@ -1209,10 +1215,11 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void switch_event_create_brackets(h->originate_string, '{', '}', ',', &ovars, &parsed); switch_event_del_header(ovars, "fifo_outbound_uuid"); - if (!h->timeout) h->timeout = 60; + if (!h->timeout) h->timeout = node->ring_timeout; if (timeout < h->timeout) timeout = h->timeout; - stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s]%s,", h->timeout, h->uuid, parsed ? parsed : h->originate_string); + stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s]%s,", + h->timeout, h->uuid, node->name, parsed ? parsed : h->originate_string); stream2.write_function(&stream2, "%s,", h->uuid); switch_safe_free(parsed); @@ -1505,17 +1512,17 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj) switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "originate_timeout", "%d", h->timeout); if (switch_stristr("origination_caller", h->originate_string)) { - originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_hangup_check='%q'}%s", - node->name, h->originate_string); + originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q'}%s", + node->name, node->name, h->originate_string); } else { if (!zstr(node->outbound_name)) { - originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_hangup_check='%q'," + originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q'," "origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s", - node->name, node->outbound_name, h->originate_string); + node->name, node->name, node->outbound_name, h->originate_string); } else { - originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_hangup_check='%q'," + originate_string = switch_mprintf("{execute_on_answer='unset fifo_hangup_check',fifo_name='%q',fifo_hangup_check='%q'," "origination_caller_id_name=Queue,origination_caller_id_number='Queue: %q'}%s", - node->name, node->name, h->originate_string); + node->name, node->name, node->name, h->originate_string); } } @@ -2017,9 +2024,10 @@ static switch_status_t hanguphook(switch_core_session_t *session) switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_state_t state = switch_channel_get_state(channel); - if (state == CS_HANGUP) { + if (state >= CS_HANGUP && !switch_channel_test_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK)) { dec_use_count(session, SWITCH_TRUE); switch_core_event_hook_remove_state_change(session, hanguphook); + switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_DID_HOOK); } return SWITCH_STATUS_SUCCESS; @@ -2037,17 +2045,19 @@ SWITCH_STANDARD_APP(fifo_track_call_function) return; } - if (switch_channel_test_app_flag(channel, FIFO_APP_TRACKING)) { + if (switch_channel_test_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s trying to double-track call!\n", switch_channel_get_name(channel)); return; } + switch_core_event_hook_add_receive_message(session, messagehook); + switch_core_event_hook_add_state_run(session, hanguphook); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s tracking call on uuid %s!\n", switch_channel_get_name(channel), data); add_bridge_call(data); - switch_channel_set_app_flag_key(__FILE__, channel, FIFO_APP_TRACKING); + switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING); switch_channel_set_variable(channel, "fifo_outbound_uuid", data); switch_channel_set_variable(channel, "fifo_track_call", "true"); @@ -2083,9 +2093,6 @@ SWITCH_STANDARD_APP(fifo_track_call_function) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Caller-CID-Number", cid_number); switch_event_fire(&event); } - - switch_core_event_hook_add_receive_message(session, messagehook); - switch_core_event_hook_add_state_change(session, hanguphook); } @@ -2346,7 +2353,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_set_variable(channel, "fifo_timestamp", date); switch_channel_set_variable(channel, "fifo_serviced_uuid", NULL); - switch_channel_set_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG); + switch_channel_set_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); if (chime_list) { char *list_dup = switch_core_session_strdup(session, chime_list); @@ -2421,7 +2428,7 @@ SWITCH_STANDARD_APP(fifo_function) abort: - switch_channel_clear_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG); + switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); fifo_caller_del(switch_core_session_get_uuid(session)); @@ -2491,6 +2498,7 @@ SWITCH_STANDARD_APP(fifo_function) if (switch_core_event_hook_remove_receive_message(session, messagehook) == SWITCH_STATUS_SUCCESS) { dec_use_count(session, SWITCH_FALSE); switch_core_event_hook_remove_state_change(session, hanguphook); + switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_TRACKING); } if (!zstr(strat_str)) { @@ -2778,7 +2786,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_channel_set_flag(other_channel, CF_BREAK); while (switch_channel_ready(channel) && switch_channel_ready(other_channel) && - switch_channel_test_app_flag(other_channel, FIFO_APP_BRIDGE_TAG)) { + switch_channel_test_app_flag_key(FIFO_APP_KEY, other_channel, FIFO_APP_BRIDGE_TAG)) { status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); if (!SWITCH_READ_ACCEPTABLE(status)) { break; @@ -2842,8 +2850,8 @@ SWITCH_STANDARD_APP(fifo_function) switch_core_media_bug_resume(session); switch_core_media_bug_resume(other_session); - switch_process_import(session, other_channel, "fifo_caller_consumer_import"); - switch_process_import(other_session, channel, "fifo_consumer_caller_import"); + switch_process_import(session, other_channel, "fifo_caller_consumer_import", switch_channel_get_variable(channel, "fifo_import_prefix")); + switch_process_import(other_session, channel, "fifo_consumer_caller_import", switch_channel_get_variable(other_channel, "fifo_import_prefix")); if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]); @@ -3082,7 +3090,7 @@ SWITCH_STANDARD_APP(fifo_function) switch_mutex_unlock(globals.mutex); - switch_channel_clear_app_flag_key(__FILE__, channel, FIFO_APP_BRIDGE_TAG); + switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); switch_core_media_bug_resume(session); @@ -3512,6 +3520,12 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_per_cycle); switch_xml_set_attr_d(x_fifo, "outbound_per_cycle", tmp); + switch_snprintf(tmp, sizeof(buffer), "%u", node->ring_timeout); + switch_xml_set_attr_d(x_fifo, "ring_timeout", tmp); + + switch_snprintf(tmp, sizeof(buffer), "%u", node->default_lag); + switch_xml_set_attr_d(x_fifo, "default_lag", tmp); + switch_snprintf(tmp, sizeof(buffer), "%u", node->outbound_priority); switch_xml_set_attr_d(x_fifo, "outbound_priority", tmp); @@ -3922,6 +3936,8 @@ static switch_status_t load_config(int reload, int del_all) int taking_calls_i = 1; int timeout_i = 60; int lag_i = 10; + int ring_timeout = 60; + int default_lag = 30; name = switch_xml_attr(fifo, "name"); @@ -3975,11 +3991,29 @@ static switch_status_t load_config(int reload, int del_all) node->has_outbound = 1; } - + if ((val = switch_xml_attr(fifo, "outbound_ring_timeout"))) { + int tmp = atoi(val); + if (tmp > 10) { + ring_timeout = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid ring_timeout: must be > 10 for queue %s\n", node->name); + } + } + + if ((val = switch_xml_attr(fifo, "outbound_default_lag"))) { + int tmp = atoi(val); + if (tmp > 10) { + default_lag = tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid default_lag: must be > 10 for queue %s\n", node->name); + } + } + + node->ring_timeout = ring_timeout; node->outbound_per_cycle = outbound_per_cycle; node->outbound_priority = outbound_priority; + node->default_lag = default_lag; - if (outbound_strategy) { node->outbound_strategy = parse_strat(outbound_strategy); node->has_outbound = 1; @@ -4011,14 +4045,14 @@ static switch_status_t load_config(int reload, int del_all) if (timeout) { if ((timeout_i = atoi(timeout)) < 10) { - timeout_i = 60; + timeout_i = ring_timeout; } } if (lag) { if ((lag_i = atoi(lag)) < 0) { - lag_i = 10; + lag_i = default_lag; } } diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c index aa7d05cf9e..005924194f 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c @@ -140,7 +140,7 @@ switch_status_t spandsp_inband_dtmf_session(switch_core_session_t *session) } if ((status = switch_core_media_bug_add(session, "spandsp_dtmf_detect", NULL, - inband_dtmf_callback, pvt, 0, SMBF_READ_REPLACE, &bug)) != SWITCH_STATUS_SUCCESS) { + inband_dtmf_callback, pvt, 0, SMBF_READ_REPLACE | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { return status; } diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 758e5dcf25..e939d7f315 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -69,7 +69,8 @@ typedef enum { typedef enum { VM_MOVE_NEXT, - VM_MOVE_PREV + VM_MOVE_PREV, + VM_MOVE_SAME } msg_move_t; #define VM_PROFILE_CONFIGITEM_COUNT 100 @@ -107,6 +108,7 @@ struct vm_profile { char rew_key[2]; char prev_msg_key[2]; char next_msg_key[2]; + char repeat_msg_key[2]; char urgent_key[2]; char operator_key[2]; char vmain_key[2]; @@ -480,7 +482,7 @@ vm_profile_t *profile_set_config(vm_profile_t *profile) SWITCH_CONFIG_SET_ITEM(profile->config[i++], "skip-greet-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->skip_greet_key, "#", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "skip-info-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, - &profile->skip_info_key, "", &config_dtmf, NULL, NULL); + &profile->skip_info_key, "*", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "config-menu-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->config_menu_key, "5", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "record-greeting-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, @@ -510,9 +512,11 @@ vm_profile_t *profile_set_config(vm_profile_t *profile) SWITCH_CONFIG_SET_ITEM(profile->config[i++], "ff-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->ff_key, "6", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "rew-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->rew_key, "4", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "previous-message-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, - &profile->prev_msg_key, "", &config_dtmf, NULL, NULL); + &profile->prev_msg_key, "1", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "next-message-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, - &profile->next_msg_key, "", &config_dtmf, NULL, NULL); + &profile->next_msg_key, "3", &config_dtmf, NULL, NULL); + SWITCH_CONFIG_SET_ITEM(profile->config[i++], "repeat-message-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, + &profile->repeat_msg_key, "0", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "urgent-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->urgent_key, "*", &config_dtmf, NULL, NULL); SWITCH_CONFIG_SET_ITEM(profile->config[i++], "operator-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, @@ -823,7 +827,8 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in if (!cc->noexit && (dtmf->digit == *cc->profile->delete_file_key || dtmf->digit == *cc->profile->save_file_key - || dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key + || dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key + || dtmf->digit == *cc->profile->repeat_msg_key || dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key || dtmf->digit == *cc->profile->email_key || dtmf->digit == *cc->profile->forward_key)) { *cc->buf = dtmf->digit; @@ -1483,6 +1488,8 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t } if (!strcmp(input, profile->prev_msg_key)) { cbt->move = VM_MOVE_PREV; + } else if (!strcmp(input, profile->repeat_msg_key)) { + cbt->move = VM_MOVE_SAME; } else if (!strcmp(input, profile->next_msg_key)) { cbt->move = VM_MOVE_NEXT; } else if (!strcmp(input, profile->listen_file_key)) { @@ -1538,6 +1545,7 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t if (voicemail_inject(cmd, session) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Sent Carbon Copy to %s\n", vm_cc); TRY_CODE(switch_ivr_phrase_macro(session, VM_ACK_MACRO, "saved", NULL, NULL)); + cbt->move = VM_MOVE_SAME; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to Carbon Copy to %s\n", vm_cc); TRY_CODE(switch_ivr_phrase_macro(session, VM_INVALID_EXTENSION_MACRO, vm_cc, NULL, NULL)); @@ -1884,7 +1892,10 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p } else { cur_message -= 2; } + } else if (cbt.move == VM_MOVE_SAME) { + cur_message -= 1; } + if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { break; } @@ -2893,6 +2904,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p char *read_flags = NORMAL_FLAG_STRING; int priority = 3; int email_attach = 1; + char *operator_ext = NULL; char buf[2]; char key_buf[80]; char *greet_path = NULL; @@ -2973,6 +2985,8 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p vm_enabled = !switch_false(val); } else if (!strcasecmp(var, "vm-message-ext")) { vm_ext = switch_core_session_strdup(session, val); + } else if (!strcasecmp(var, "vm-operator-extension")) { + operator_ext = switch_core_session_strdup(session, val); } } } @@ -3089,12 +3103,13 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p greet_key_press: if (switch_stristr(buf, profile->login_keys)) { voicemail_check_main(session, profile, domain_name, id, 0); - } else if (!zstr(profile->operator_ext) && !zstr(profile->operator_key) && !strcasecmp(buf, profile->operator_key) ) { + } else if ((!zstr(profile->operator_ext) || !zstr(operator_ext)) && !zstr(profile->operator_key) && !strcasecmp(buf, profile->operator_key) ) { int argc; char *argv[4]; char *mycmd; - if (!zstr(profile->operator_ext) && (mycmd = switch_core_session_strdup(session, profile->operator_ext))) { + if ((!zstr(operator_ext) && (mycmd = switch_core_session_strdup(session, operator_ext))) || + (!zstr(profile->operator_ext) && (mycmd = switch_core_session_strdup(session, profile->operator_ext)))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); if (argc >= 1 && argc <= 4) { switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]); diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.2010.vcxproj b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.2010.vcxproj index ca533a4cfa..7028e53447 100644 --- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.2010.vcxproj +++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.2010.vcxproj @@ -189,6 +189,9 @@ {b4b62169-5ad4-4559-8707-3d933ac5db39} + + {df018947-0fff-4eb3-bdee-441dc81da7a4} + {70a49bc2-7500-41d0-b75d-edcc5be987a0} diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c index c84dac4509..21bfb958d4 100644 --- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c +++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c @@ -33,7 +33,6 @@ */ #include "switch.h" -#include "g711.h" #include @@ -41,7 +40,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sangoma_codec_shutdown); SWITCH_MODULE_DEFINITION(mod_sangoma_codec, mod_sangoma_codec_load, mod_sangoma_codec_shutdown, NULL); -#define IANA_ULAW 0 +#define IANA_LINEAR 10 #define SANGOMA_SESS_HASH_KEY_FORMAT "sngtc%lu" /* it seemed we need higher PTIME than the calling parties, so we assume nobody will use higher ptime than 40 */ @@ -82,6 +81,8 @@ typedef struct vocallo_codec_s { int autoinit; /* initialize on start loop or manually */ } vocallo_codec_t; +#define ILBC_133_PAYLOAD 97 +#define ILBC_152_PAYLOAD 98 vocallo_codec_t g_codec_map[] = { { SNGTC_CODEC_PCMU, 0, "PCMU", "Sangoma PCMU", 40, 64000, 10000, 80, 160, 80, 1 }, @@ -90,9 +91,10 @@ vocallo_codec_t g_codec_map[] = { SNGTC_CODEC_G729AB, 18, "G729", "Sangoma G729", 40, 8000, 10000, 80, 160, 10, 1 }, { SNGTC_CODEC_G726_32, 122, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 1 }, { SNGTC_CODEC_GSM_FR, 3, "GSM", "Sangoma GSM", 20, 13200, 20000, 160, 320, 33, 0 }, + { SNGTC_CODEC_ILBC_133, ILBC_133_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, 0 }, + { SNGTC_CODEC_ILBC_152, ILBC_152_PAYLOAD, "iLBC", "Sangoma iLBC", -1, -1, -1, -1, -1, -1, 0 }, + { SNGTC_CODEC_G723_1_63, 4, "G723", "Sangoma G723", 90, 6300, 30000, 240, 480, 24, 0}, #if 0 - /* FIXME: grandstream crashes with iLBC implementation */ - { SNGTC_CODEC_ILBC, 97, "iLBC", "Sangoma ILBC", -1, -1, -1, -1, -1, -1, 0 }, /* FIXME: sampling rate seems wrong with this, audioooo soooundssssss sloooooow ... */ { SNGTC_CODEC_G722, 9, "G722", "Sangoma G722", 20, 64000, 20000, 160, 640, 160, 0 }, #endif @@ -103,11 +105,17 @@ vocallo_codec_t g_codec_map[] = #define IANACODE_CN 13 /* default codec list to load, users may override, special codec 'all' registers everything available unless listed in noregister */ -static char g_codec_register_list[1024] = "all"; +static char g_codec_register_list[1024] = "G729"; /* default codec list to NOT load, users may override */ static char g_codec_noregister_list[1024] = ""; +#define SANGOMA_RTP_QUEUE_SIZE 4 +struct sangoma_rtp_payload { + uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE]; + int32_t datalen; +}; + struct codec_data { /* sngtc request and reply */ sngtc_codec_request_t request; @@ -131,7 +139,15 @@ struct codec_data { /* avg Rx time */ switch_time_t avgrxus; switch_time_t last_rx_time; + switch_time_t last_func_call_time; + /* RTP queue. The bigger the queue, the bigger the possible delay */ + struct sangoma_rtp_payload rtp_queue[SANGOMA_RTP_QUEUE_SIZE]; + uint8_t queue_windex; + uint8_t queue_rindex; + uint8_t queue_size; + uint8_t queue_max_ever; + unsigned debug_timing:1; }; struct sangoma_transcoding_session { @@ -172,6 +188,17 @@ static vocallo_codec_t *get_codec_from_iana(int iana) return NULL; } +static vocallo_codec_t *get_codec_from_id(int id) +{ + int i; + for (i = 0; g_codec_map[i].codec_id != -1; i++) { + if (id == g_codec_map[i].codec_id) { + return &g_codec_map[i]; + } + } + return NULL; +} + static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p_rtp_port, void **rtp_fd) { struct in_addr local_ip_addr = { 0 }; @@ -229,8 +256,8 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r sngtc_codec_ipv4_hex_to_str(codec_reply_leg->codec_ip, codec_ip); iana = codec_id_to_iana(codec_req_leg->codec_id); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Creating RTP session for host (%s/%d) vocallo(%s/%d) Iana=%d ms=%d idx=%lu\n", - local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Creating RTP session for host (%s/%d) vocallo(%s/%d) Iana=%d CodecId=%d ms=%d idx=%lu\n", + local_ip, rtp_port, codec_ip, codec_reply_leg->codec_udp_port, iana, codec_req_leg->codec_id, codec_req_leg->ms*1000, sess->sessid); /* create the RTP socket */ @@ -268,11 +295,11 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f struct sangoma_transcoding_session *sess = NULL; vocallo_codec_t *vcodec; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma init called.\n"); - encoding = (flags & SWITCH_CODEC_FLAG_ENCODE); decoding = (flags & SWITCH_CODEC_FLAG_DECODE); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma init called (encoding = %d, decoding = %d, iana = %d)\n", encoding ? 1 : 0, decoding ? 1 : 0, codec->implementation->ianacode); + if (!(encoding || decoding)) { return SWITCH_STATUS_FALSE; } @@ -295,7 +322,7 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f if (encoding) { sess->encoder.request.usr_priv = sess; sess->encoder.request.a.host_ip = g_rtpip; - sess->encoder.request.a.codec_id = SNGTC_CODEC_PCMU; + sess->encoder.request.a.codec_id = SNGTC_CODEC_L16_1; sess->encoder.request.a.ms = codec->implementation->microseconds_per_packet/1000; sess->encoder.request.b.host_ip = g_rtpip; @@ -310,7 +337,7 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f sess->decoder.request.a.ms = codec->implementation->microseconds_per_packet/1000; sess->decoder.request.b.host_ip = g_rtpip; - sess->decoder.request.b.codec_id = SNGTC_CODEC_PCMU; + sess->decoder.request.b.codec_id = SNGTC_CODEC_L16_1; sess->decoder.request.b.ms = codec->implementation->microseconds_per_packet/1000; } @@ -319,6 +346,7 @@ static switch_status_t switch_sangoma_init(switch_codec_t *codec, switch_codec_f switch_snprintf(sess->hashkey, sizeof(sess->hashkey), SANGOMA_SESS_HASH_KEY_FORMAT, sess->sessid); switch_core_hash_insert(g_sessions_hash, sess->hashkey, sess); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sangoma init done for codec %s/%s, iana = %d\n", codec->implementation->iananame, vcodec->fs_name, codec->implementation->ianacode); switch_mutex_unlock(g_sessions_lock); codec->private_info = sess; @@ -352,6 +380,35 @@ static switch_status_t switch_sangoma_init_ilbc(switch_codec_t *codec, switch_co return switch_sangoma_init(codec, flags, codec_settings); } + +static void flush_rtp(switch_rtp_t *rtp) +{ + switch_status_t sres; + switch_frame_t read_frame; + int flushed = 0; + int sanity = 1000; + while (sanity--) { + sres = switch_rtp_zerocopy_read_frame(rtp, &read_frame, SWITCH_IO_FLAG_NOBLOCK); + if (sres == SWITCH_STATUS_GENERR) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session while flushing: %d\n", sres); + return; + } + if (!read_frame.datalen) { + break; + } + flushed++; + } + if (!sanity) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Insanely big UDP queue!\n"); + } +} + +#define SAFE_INDEX_INC(array, index) \ + (index)++; \ + if ((index) == switch_arraylen((array))) { \ + (index) = 0; \ + } + static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec_t *other_codec, /* codec that was used by the other side */ void *decoded_data, /* decoded data that we must encode */ uint32_t decoded_data_len /* decoded data length */ , @@ -363,16 +420,21 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec { /* FS core checks the actual samples per second and microseconds per packet to determine the buffer size in the worst case scenario, no need to check * whether the buffer passed in by the core (encoded_data) will be big enough */ - switch_frame_t ulaw_frame; + switch_frame_t linear_frame; switch_frame_t encoded_frame; - switch_status_t sres; - switch_time_t now_time, difftime; - unsigned char ebuf_ulaw[decoded_data_len / 2]; - short *dbuf_linear; + switch_status_t sres = SWITCH_STATUS_FALSE; + uint16_t decoded_byteswapped_data[SWITCH_RECOMMENDED_BUFFER_SIZE]; + uint16_t *decoded_data_linear = decoded_data; + switch_time_t now_time = 0, difftime = 0; + switch_time_t func_start_time = 0, func_end_time = 0; int i = 0; int res = 0; struct sangoma_transcoding_session *sess = codec->private_info; + if (sess->encoder.debug_timing) { + func_start_time = switch_micro_time_now(); + } + /* start assuming we will not encode anything */ *encoded_data_len = 0; @@ -390,23 +452,30 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec sess->encoder.txrtp = sess->encoder.reply.tx_fd; sess->encoder.rxrtp = sess->encoder.reply.rx_fd; switch_mutex_unlock(g_sessions_lock); + flush_rtp(sess->encoder.rxrtp); } - /* transcode to ulaw first */ - dbuf_linear = decoded_data; - - for (i = 0; i < decoded_data_len / sizeof(short); i++) { - ebuf_ulaw[i] = linear_to_ulaw(dbuf_linear[i]); + if (sess->encoder.debug_timing && sess->encoder.last_func_call_time) { + difftime = func_start_time - sess->encoder.last_func_call_time; + if (difftime > 25000 || difftime < 15000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%ldus since last read on encoding session %lu\n", (long)difftime, sess->sessid); + } } - + /* do the writing */ - memset(&ulaw_frame, 0, sizeof(ulaw_frame)); - ulaw_frame.source = __FUNCTION__; - ulaw_frame.data = ebuf_ulaw; - ulaw_frame.datalen = i; - ulaw_frame.payload = IANA_ULAW; + memset(&linear_frame, 0, sizeof(linear_frame)); + linear_frame.source = __FUNCTION__; + linear_frame.data = decoded_byteswapped_data; + linear_frame.datalen = decoded_data_len; + linear_frame.payload = IANA_LINEAR; - res = switch_rtp_write_frame(sess->encoder.txrtp, &ulaw_frame); + /* copy and byte-swap */ + for (i = 0; i < decoded_data_len/2; i++) { + decoded_byteswapped_data[i] = (decoded_data_linear[i] << 8) | (decoded_data_linear[i] >> 8); + } + + + res = switch_rtp_write_frame(sess->encoder.txrtp, &linear_frame); if (-1 == res) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to write to Sangoma encoder RTP session.\n"); return SWITCH_STATUS_FALSE; @@ -420,38 +489,80 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec sess->encoder.tx++; /* do the reading */ - memset(&encoded_frame, 0, sizeof(encoded_frame)); for ( ; ; ) { +#if 0 + prevread_time = switch_micro_time_now(); +#endif sres = switch_rtp_zerocopy_read_frame(sess->encoder.rxrtp, &encoded_frame, SWITCH_IO_FLAG_NOBLOCK); if (sres == SWITCH_STATUS_GENERR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma encoder RTP session: %d\n", sres); return SWITCH_STATUS_FALSE; } +#if 0 + afterread_time = switch_micro_time_now(); + difftime = afterread_time - prevread_time; + if (difftime > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to read on encoding session %lu.\n", (long)difftime, sess->sessid); + } +#endif if (0 == encoded_frame.datalen) { break; } - if (encoded_frame.payload != codec->implementation->ianacode - && encoded_frame.payload != IANACODE_CN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", - encoded_frame.payload, codec->implementation->ianacode); - break; + if (encoded_frame.payload == IANACODE_CN) { + /* confort noise is treated as silence by us */ + continue; } - if (*encoded_data_len) { - sess->encoder.rxdiscarded++; + if (encoded_frame.datalen != codec->implementation->encoded_bytes_per_packet) { + /* seen when silence suppression is enabled */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring encoded frame of %d bytes intead of %d bytes\n", encoded_frame.datalen, codec->implementation->encoded_bytes_per_packet); + continue; } - memcpy(encoded_data, encoded_frame.data, encoded_frame.datalen); - *encoded_data_len = encoded_frame.datalen; + if (encoded_frame.payload != codec->implementation->ianacode) { + if (sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_152 || sess->encoder.request.b.codec_id == SNGTC_CODEC_ILBC_133) { + /* since we moved to SOAP based communications, the mapping between vocallo IANA and our IANA does not work, + * some codecs checks cannot be completely done, like iLBC */ + if (encoded_frame.payload != ILBC_152_PAYLOAD && encoded_frame.payload != ILBC_133_PAYLOAD) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting either %d or %d\n", + encoded_frame.payload, ILBC_152_PAYLOAD, ILBC_133_PAYLOAD); + break; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma encoder RTP session, expecting %d\n", + encoded_frame.payload, codec->implementation->ianacode); + break; + } + } + + if (sess->encoder.queue_windex == sess->encoder.queue_rindex) { + if (sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen) { + /* if there is something where we want to write, we're dropping it */ + sess->encoder.rxdiscarded++; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Discarding encoded frame of %d bytes from RTP session %lu, windex = %d, rindex = %d\n", + sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen, sess->sessid, sess->encoder.queue_windex, sess->encoder.queue_rindex); + SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_rindex); + sess->encoder.queue_size--; + } + } + + memcpy(sess->encoder.rtp_queue[sess->encoder.queue_windex].data, encoded_frame.data, encoded_frame.datalen); + sess->encoder.rtp_queue[sess->encoder.queue_windex].datalen = encoded_frame.datalen; + SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_windex); + + /* monitor the queue size */ + sess->encoder.queue_size++; + if (sess->encoder.queue_size > sess->encoder.queue_max_ever) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoder Rx queue for RTP session %lu is now %d, windex = %d, rindex = %d\n", sess->sessid, sess->encoder.queue_size, + sess->encoder.queue_windex, sess->encoder.queue_rindex); + sess->encoder.queue_max_ever = sess->encoder.queue_size; + } } - /* update encoding stats if we received a frame */ - if (*encoded_data_len) { - if (*encoded_data_len != codec->implementation->encoded_bytes_per_packet) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd encoded frame of %d bytes intead of %d bytes\n", *encoded_data_len, codec->implementation->encoded_bytes_per_packet); - } + /* update encoding stats if we have a frame to give */ + if (sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen) { sess->encoder.rx++; now_time = switch_micro_time_now(); if (!sess->encoder.last_rx_time) { @@ -469,10 +580,28 @@ static switch_status_t switch_sangoma_encode(switch_codec_t *codec, switch_codec } } sess->encoder.lastrxseqno = encoded_frame.seq; + + /* pop the data from the queue */ + *encoded_data_len = sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen; + memcpy(encoded_data, sess->encoder.rtp_queue[sess->encoder.queue_rindex].data, *encoded_data_len); + sess->encoder.rtp_queue[sess->encoder.queue_rindex].datalen = 0; + SAFE_INDEX_INC(sess->encoder.rtp_queue, sess->encoder.queue_rindex); + sess->encoder.queue_size--; + if (*encoded_data_len != codec->implementation->encoded_bytes_per_packet) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd encoded frame of %d bytes intead of %d bytes\n", *encoded_data_len, codec->implementation->encoded_bytes_per_packet); + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output from sangoma encoder\n"); } + if (sess->encoder.debug_timing) { + func_end_time = switch_micro_time_now(); + difftime = func_end_time - func_start_time; + if (difftime > 5000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%ldus to execute encoding function in session %lu.\n", (long)difftime, sess->sessid); + } + sess->encoder.last_func_call_time = func_end_time; + } return SWITCH_STATUS_SUCCESS; } @@ -489,14 +618,21 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses /* FS core checks the actual samples per second and microseconds per packet to determine the buffer size in the worst case scenario, no need to check * whether the buffer passed in by the core will be enough */ switch_frame_t encoded_frame; - switch_frame_t ulaw_frame; - switch_status_t sres; - switch_time_t now_time, difftime; - short *dbuf_linear; - int i = 0; + switch_frame_t linear_frame; + switch_status_t sres = SWITCH_STATUS_FALSE; + switch_time_t now_time = 0, difftime = 0; + switch_time_t func_start_time = 0, func_end_time = 0; + uint16_t *dbuf_linear; + uint16_t *linear_frame_data; + uint16_t *rtp_data_linear; int res = 0; + int i = 0; struct sangoma_transcoding_session *sess = codec->private_info; + if (sess->decoder.debug_timing) { + func_start_time = switch_micro_time_now(); + } + dbuf_linear = decoded_data; /* start assuming we will not decode anything */ @@ -522,6 +658,14 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses sess->decoder.txrtp = sess->decoder.reply.tx_fd; sess->decoder.rxrtp = sess->decoder.reply.rx_fd; switch_mutex_unlock(g_sessions_lock); + flush_rtp(sess->decoder.rxrtp); + } + + if (sess->decoder.debug_timing && sess->decoder.last_func_call_time) { + difftime = func_start_time - sess->decoder.last_func_call_time; + if (difftime > 25000 || difftime < 15000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldms since last read on decoding session %lu.\n", (long)difftime, sess->sessid); + } } /* do the writing */ @@ -546,40 +690,70 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses sess->decoder.tx++; /* do the reading */ - memset(&ulaw_frame, 0, sizeof(ulaw_frame)); for ( ; ; ) { - sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &ulaw_frame, SWITCH_IO_FLAG_NOBLOCK); +#if 0 + prevread_time = switch_micro_time_now(); +#endif + sres = switch_rtp_zerocopy_read_frame(sess->decoder.rxrtp, &linear_frame, SWITCH_IO_FLAG_NOBLOCK); if (sres == SWITCH_STATUS_GENERR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read on Sangoma decoder RTP session: %d\n", sres); return SWITCH_STATUS_FALSE; } - if (0 == ulaw_frame.datalen) { +#if 0 + afterread_time = switch_micro_time_now(); + difftime = afterread_time - prevread_time; + if (difftime > 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to read on decoding session %lu.\n", (long)difftime, sess->sessid); + } +#endif + if (0 == linear_frame.datalen) { break; } - if (ulaw_frame.payload != IANA_ULAW - && ulaw_frame.payload != IANACODE_CN) { + if (linear_frame.payload == IANACODE_CN) { + /* confort noise is treated as silence by us */ + continue; + } + + if (linear_frame.payload != IANA_LINEAR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read unexpected payload %d in Sangoma decoder RTP session, expecting %d\n", - ulaw_frame.payload, IANA_ULAW); + linear_frame.payload, IANA_LINEAR); break; } - if (*decoded_data_len) { - sess->decoder.rxdiscarded++; + + if (sess->decoder.queue_windex == sess->decoder.queue_rindex) { + if (sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen) { + /* if there is something where we want to write, we're dropping it */ + sess->decoder.rxdiscarded++; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Discarding decoded frame of %d bytes from RTP session %lu, windex = %d, rindex = %d\n", + sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen, sess->sessid, sess->decoder.queue_windex, sess->decoder.queue_rindex); + SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_rindex); + sess->decoder.queue_size--; + } } - /* transcode to linear */ - for (i = 0; i < ulaw_frame.datalen; i++) { - dbuf_linear[i] = ulaw_to_linear(((char *)ulaw_frame.data)[i]); + /* byteswap the received data */ + rtp_data_linear = (unsigned short *)sess->decoder.rtp_queue[sess->decoder.queue_windex].data; + linear_frame_data = linear_frame.data; + for (i = 0; i < linear_frame.datalen/2; i++) { + rtp_data_linear[i] = (linear_frame_data[i] << 8) | (linear_frame_data[i] >> 8); + } + sess->decoder.rtp_queue[sess->decoder.queue_windex].datalen = linear_frame.datalen; + + SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_windex); + + /* monitor the queue size */ + sess->decoder.queue_size++; + if (sess->decoder.queue_size > sess->decoder.queue_max_ever) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoder Rx queue for RTP session %lu is now %d, windex = %d, rindex = %d\n", sess->sessid, sess->decoder.queue_size, + sess->decoder.queue_windex, sess->decoder.queue_rindex); + sess->decoder.queue_max_ever = sess->decoder.queue_size; } - *decoded_data_len = i * 2; } - if (*decoded_data_len) { - if (*decoded_data_len != codec->implementation->decoded_bytes_per_packet) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd decoded frame of %d bytes intead of %d bytes\n", *decoded_data_len, codec->implementation->decoded_bytes_per_packet); - } + if (sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen) { /* update decoding stats */ sess->decoder.rx++; @@ -594,17 +768,37 @@ static switch_status_t switch_sangoma_decode(switch_codec_t *codec, /* codec ses /* check sequence and bump lost rx packets count if needed */ if (sess->decoder.lastrxseqno >= 0) { - if (ulaw_frame.seq > (sess->decoder.lastrxseqno + 2) ) { - sess->decoder.rxlost += ulaw_frame.seq - sess->decoder.lastrxseqno - 1; + if (linear_frame.seq > (sess->decoder.lastrxseqno + 2) ) { + sess->decoder.rxlost += linear_frame.seq - sess->decoder.lastrxseqno - 1; } } - sess->decoder.lastrxseqno = ulaw_frame.seq; + sess->decoder.lastrxseqno = linear_frame.seq; + + /* pop the data from the queue */ + memcpy(dbuf_linear, sess->decoder.rtp_queue[sess->decoder.queue_rindex].data, sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen); + *decoded_data_len = sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen; + sess->decoder.rtp_queue[sess->decoder.queue_rindex].datalen = 0; + SAFE_INDEX_INC(sess->decoder.rtp_queue, sess->decoder.queue_rindex); + sess->decoder.queue_size--; + + if (*decoded_data_len != codec->implementation->decoded_bytes_per_packet) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Returning odd decoded frame of %d bytes intead of %d bytes\n", *decoded_data_len, codec->implementation->decoded_bytes_per_packet); + } } else { *decoded_data_len = codec->implementation->decoded_bytes_per_packet; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No output from sangoma decoder, returning silent frame of %d bytes\n", *decoded_data_len); memset(dbuf_linear, 0, *decoded_data_len); } + if (sess->decoder.debug_timing) { + func_end_time = switch_micro_time_now(); + difftime = func_end_time - func_start_time; + if (difftime > 5000) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%ldus to execute decoding function in session %lu.\n", (long)difftime, sess->sessid); + } + sess->decoder.last_func_call_time = func_end_time; + } + return SWITCH_STATUS_SUCCESS; } @@ -652,7 +846,7 @@ static void sangoma_print_stats(switch_stream_handle_t *stream, switch_rtp_numbe stream->write_function(stream, "Flush packet count: %lu\n\n\n", stats->flush_packet_count); } -#define SANGOMA_SYNTAX "settings|sessions|stats " +#define SANGOMA_SYNTAX "settings|sessions|stats |debug |nodebug " SWITCH_STANDARD_API(sangoma_function) { char *argv[10] = { 0 }; @@ -756,38 +950,83 @@ SWITCH_STANDARD_API(sangoma_function) if (sess->encoder.rxrtp) { stats = switch_rtp_get_stats(sess->encoder.rxrtp, NULL); - stream->write_function(stream, "=== Encoder ===\n"); + stream->write_function(stream, "=== %s Encoder ===\n", sess->impl->iananame); - stream->write_function(stream, "Remote address: %s:%d\n\n", switch_rtp_get_remote_host(sess->encoder.rxrtp), switch_rtp_get_remote_port(sess->encoder.rxrtp)); + stream->write_function(stream, "Tx L16 from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n\n", SNGTC_NIPV4(sess->encoder.reply.a.host_ip), sess->encoder.reply.a.host_udp_port, + SNGTC_NIPV4(sess->encoder.reply.a.codec_ip), sess->encoder.reply.a.codec_udp_port); + stream->write_function(stream, "Rx %s at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", sess->impl->iananame, SNGTC_NIPV4(sess->encoder.reply.b.host_ip), sess->encoder.reply.b.host_udp_port, + SNGTC_NIPV4(sess->encoder.reply.b.codec_ip), sess->encoder.reply.b.codec_udp_port); - stream->write_function(stream, "-- Encoder Inbound Stats --\n"); + + stream->write_function(stream, "-- Inbound Stats --\n"); stream->write_function(stream, "Rx Discarded: %lu\n", sess->encoder.rxdiscarded); sangoma_print_stats(stream, &stats->inbound); stats = switch_rtp_get_stats(sess->encoder.txrtp, NULL); - stream->write_function(stream, "-- Encoder Outbound Stats --\n"); + stream->write_function(stream, "-- Outbound Stats --\n"); sangoma_print_stats(stream, &stats->outbound); - } else { - stream->write_function(stream, "\n=== No Encoder ===\n\n"); } if (sess->decoder.rxrtp) { stats = switch_rtp_get_stats(sess->decoder.rxrtp, NULL); - stream->write_function(stream, "=== Decoder ===\n"); - stream->write_function(stream, "Remote address: %s:%d\n\n", switch_rtp_get_remote_host(sess->decoder.rxrtp), switch_rtp_get_remote_port(sess->decoder.rxrtp)); + stream->write_function(stream, "=== %s Decoder ===\n", sess->impl->iananame); + stream->write_function(stream, "Tx %s from %d.%d.%d.%d:%d to %d.%d.%d.%d:%d\n\n", sess->impl->iananame, SNGTC_NIPV4(sess->decoder.reply.a.host_ip), sess->decoder.reply.a.host_udp_port, + SNGTC_NIPV4(sess->decoder.reply.a.codec_ip), sess->decoder.reply.a.codec_udp_port); + stream->write_function(stream, "Rx L16 at %d.%d.%d.%d:%d from %d.%d.%d.%d:%d\n\n", SNGTC_NIPV4(sess->decoder.reply.b.host_ip), sess->decoder.reply.b.host_udp_port, + SNGTC_NIPV4(sess->decoder.reply.b.codec_ip), sess->decoder.reply.b.codec_udp_port); - stream->write_function(stream, "-- Decoder Inbound Stats --\n"); + stream->write_function(stream, "-- Inbound Stats --\n"); stream->write_function(stream, "Rx Discarded: %lu\n", sess->decoder.rxdiscarded); sangoma_print_stats(stream, &stats->inbound); stats = switch_rtp_get_stats(sess->decoder.txrtp, NULL); - stream->write_function(stream, "-- Decoder Outbound Stats --\n"); + stream->write_function(stream, "-- Outbound Stats --\n"); sangoma_print_stats(stream, &stats->outbound); - } else { - stream->write_function(stream, "\n=== No Decoder ===\n\n"); } + } else if (!strcasecmp(argv[0], "debug")) { + struct sangoma_transcoding_session *sess; + unsigned long sessid = 0; + int ret = 0; + if (argc < 2) { + stream->write_function(stream, "%s", SANGOMA_SYNTAX); + goto done; + } + ret = sscanf(argv[1], "%lu", &sessid); + if (ret != 1) { + stream->write_function(stream, "%s", SANGOMA_SYNTAX); + goto done; + } + sess = sangoma_find_session(sessid); + if (!sess) { + stream->write_function(stream, "Failed to find session %lu\n", sessid); + goto done; + } + sess->encoder.debug_timing = 1; + sess->decoder.debug_timing = 1; + stream->write_function(stream, "Debug enabled for transcoding session: %lu\n", sessid); + } else if (!strcasecmp(argv[0], "nodebug")) { + struct sangoma_transcoding_session *sess; + unsigned long sessid = 0; + int ret = 0; + if (argc < 2) { + stream->write_function(stream, "%s", SANGOMA_SYNTAX); + goto done; + } + ret = sscanf(argv[1], "%lu", &sessid); + if (ret != 1) { + stream->write_function(stream, "%s", SANGOMA_SYNTAX); + goto done; + } + sess = sangoma_find_session(sessid); + if (!sess) { + stream->write_function(stream, "Failed to find session %lu\n", sessid); + goto done; + } + sess->encoder.debug_timing = 0; + sess->decoder.debug_timing = 0; + stream->write_function(stream, "Debug disabled for transcoding session: %lu\n", sessid); } else { stream->write_function(stream, "Unknown Command [%s]\n", argv[0]); } @@ -911,6 +1150,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_codec_interface_t *codec_interface = NULL; switch_api_interface_t *api_interface = NULL; int i = 0, c = 0; + int ilbc_done = 0; + vocallo_codec_t *ilbc_codec = NULL; int detected = 0, activated = 0; /* make sure we have valid configuration */ @@ -949,6 +1190,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading codecs, register='%s', noregister='%s'\n", g_codec_register_list, g_codec_noregister_list); for (c = 0; g_codec_map[c].codec_id != -1; c++) { + if (g_codec_map[c].codec_id == SNGTC_CODEC_L16_1) { + /* registering L16 does not make any sense */ + continue; + } + /* check if the codec is in the load list, otherwise skip it */ if (strcasecmp(g_codec_register_list, "all") && !strcasestr(g_codec_register_list, g_codec_map[c].iana_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Not loading codec %s because was not found in the load list\n", @@ -969,6 +1215,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) sngtc_set_iana_code_based_on_codec_id(g_codec_map[c].codec_id, g_codec_map[c].iana); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Mapped codec %d to IANA %d\n", g_codec_map[c].codec_id, g_codec_map[c].iana); + /* special check for iLBC to add a single codec interface for both ILBC bitrate versions */ + if ((g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_152 || g_codec_map[c].codec_id == SNGTC_CODEC_ILBC_133) && ilbc_done) { + continue; + } + /* SWITCH_ADD_CODEC allocates a codec interface structure from the pool the core gave us and adds it to the internal interface * list the core keeps, gets a codec id and set the given codec name to it. * At this point there is an empty shell codec interface registered, but not yet implementations */ @@ -1028,11 +1279,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ break; - case SNGTC_CODEC_ILBC: + case SNGTC_CODEC_ILBC_133: + case SNGTC_CODEC_ILBC_152: + ilbc_codec = get_codec_from_id(SNGTC_CODEC_ILBC_152); switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ - g_codec_map[c].iana_name, /* the IANA code name */ + ilbc_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + ilbc_codec->iana_name, /* the IANA code name */ "mode=20", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ 8000, /* samples transferred per second */ 8000, /* actual samples transferred per second */ @@ -1048,11 +1301,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_sangoma_decode, /* function to decode encoded data into slinear data */ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ -#if 0 + ilbc_codec = get_codec_from_id(SNGTC_CODEC_ILBC_133); switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ - g_codec_map[c].iana, /* 97, the IANA code number */ - g_codec_map[c].iana_name, /* the IANA code name */ + ilbc_codec->iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + ilbc_codec->iana_name, /* the IANA code name */ "mode=30", /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ 8000, /* samples transferred per second */ 8000, /* actual samples transferred per second */ @@ -1067,7 +1320,32 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_sangoma_encode, /* function to encode slinear data into encoded data */ switch_sangoma_decode, /* function to decode encoded data into slinear data */ switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ -#endif + ilbc_done = 1; + break; + + case SNGTC_CODEC_G723_1_63: + + for (i = 1; i <= 3; i++) { + switch_core_codec_add_implementation(pool, codec_interface, /* the codec interface we allocated and we want to register with the core */ + SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */ + g_codec_map[c].iana, /* the IANA code number, ie http://www.iana.org/assignments/rtp-parameters */ + g_codec_map[c].iana_name, /* the IANA code name */ + NULL, /* default fmtp to send (can be overridden by the init function), fmtp is used in SDP for format specific parameters */ + 8000, /* samples transferred per second */ + 8000, /* actual samples transferred per second */ + g_codec_map[c].bps, /* bits transferred per second */ + g_codec_map[c].mpf * i, /* microseconds per frame */ + g_codec_map[c].spf * i, /* samples per frame */ + g_codec_map[c].bpfd * i, /* number of bytes per frame decompressed */ + g_codec_map[c].bpfc * i, /* number of bytes per frame compressed */ + 1, /* number of channels represented */ + g_codec_map[c].spf * i, /* number of frames per network packet (I dont think this is used at all) */ + switch_sangoma_init, /* function to initialize a codec session using this implementation */ + switch_sangoma_encode, /* function to encode slinear data into encoded data */ + switch_sangoma_decode, /* function to decode encoded data into slinear data */ + switch_sangoma_destroy); /* deinitalize a codec handle using this implementation */ + } + break; case SNGTC_CODEC_G722: @@ -1103,6 +1381,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load) switch_console_set_complete("add sangoma_codec settings"); switch_console_set_complete("add sangoma_codec sessions"); switch_console_set_complete("add sangoma_codec stats"); + switch_console_set_complete("add sangoma_codec debug"); + switch_console_set_complete("add sangoma_codec nodebug"); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile index 070f941a94..d67bdbbabf 100644 --- a/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile +++ b/src/mod/endpoints/mod_gsmopen/alsa_nogsmlib_nocplusplus/mod_gsmopen/Makefile @@ -1,6 +1,7 @@ MODNAME=mod_gsmopen SVNDEF := -D'GSMOPEN_SVN_VERSION="$(shell svnversion -n .)"' -LOCAL_CFLAGS += $(SVNDEF) -Wno-error=address -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff +#LOCAL_CFLAGS += $(SVNDEF) -Wno-error=address -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff +LOCAL_CFLAGS += $(SVNDEF) -DNO_GSMLIB -I../../../../../../libs/spandsp/src -I../../../../../..//libs/tiff-3.8.2/libtiff LOCAL_LDFLAGS=-lasound -L../../../../../../libs/spandsp/src -lspandsp LOCAL_OBJS=gsmopen_protocol.o include ../../../../../../build/modmake.rules diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index 40a716671d..cb440d3bcb 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -1209,7 +1209,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_call_cause_t *cancel_cause) { private_t *tech_pvt = NULL; - if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) { + if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) { switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; char *rdest; diff --git a/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml new file mode 100644 index 0000000000..45268f304b --- /dev/null +++ b/src/mod/endpoints/mod_khomp/Install/files/khomp.conf.xml @@ -0,0 +1,536 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/endpoints/mod_khomp/Makefile b/src/mod/endpoints/mod_khomp/Makefile new file mode 100644 index 0000000000..94923c7cda --- /dev/null +++ b/src/mod/endpoints/mod_khomp/Makefile @@ -0,0 +1,41 @@ +MODNAME := mod_khomp +VERBOSE := 1 + +ifeq ($(strip $(FREESWITCH_PATH)),) + BASE := ../../../../ +else + BASE := $(FREESWITCH_PATH) +endif + +curr_dir := $(shell pwd) + +versions := -DFS_VERSION_MAJOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MAJOR" $(BASE)) -DFS_VERSION_MINOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MINOR" $(BASE)) -DFS_VERSION_MICRO=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MICRO" $(BASE)) + +LOCAL_CFLAGS = -I./ -I./include -I./commons -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS +LOCAL_CFLAGS += $(versions) + +LOCAL_LDFLAGS = -lk3l + +LOCAL_OBJS = ./commons/k3lapi.o ./commons/k3lutil.o ./commons/config_options.o ./commons/format.o ./commons/strings.o ./commons/ringbuffer.o ./commons/verbose.o ./commons/saved_condition.o ./commons/regex.o ./commons/timer.o ./commons/configurator/configfile.o ./commons/configurator/option.o ./commons/configurator/section.o ./commons/configurator/restriction.o +LOCAL_OBJS += ./support/klog-config.o ./support/klog-options.o ./support/config_defaults.o +LOCAL_OBJS += ./src/globals.o ./src/opt.o ./src/frame.o ./src/utils.o ./src/lock.o ./src/spec.o ./src/applications.o ./src/khomp_pvt_fxo.o ./src/khomp_pvt_gsm.o ./src/khomp_pvt_kxe1.o ./src/khomp_pvt_passive.o ./src/khomp_pvt.o ./src/logger.o ./src/cli.o + +conf_file_name := khomp.conf.xml +conf_file_dir := $(curr_dir)/Install/files +conf_file_dir_alt := $(curr_dir)/conf +conf_file_install = $(sysconfdir)/autoload_configs + +include $(BASE)/build/modmake.rules + +depend_install: + @echo "Copy $(conf_file_name)" + @if test -d $(conf_file_install) ; then \ + if test -f $(conf_file_dir)/$(conf_file_name) ; then \ + cp $(conf_file_dir)/$(conf_file_name) $(conf_file_install)/$(conf_file_name).new ;\ + else \ + cp $(conf_file_dir_alt)/$(conf_file_name) $(conf_file_install)/$(conf_file_name).new ;\ + fi; \ + if test ! -f "$(conf_file_install)/$(conf_file_name)" ; then \ + mv $(conf_file_install)/$(conf_file_name).new $(conf_file_install)/$(conf_file_name) ;\ + fi; \ + fi; diff --git a/src/mod/endpoints/mod_khomp/commons/atomic.hpp b/src/mod/endpoints/mod_khomp/commons/atomic.hpp new file mode 100644 index 0000000000..daa598c9b4 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/atomic.hpp @@ -0,0 +1,189 @@ +/* + KHOMP generic endpoint/channel library. + + This code was based on FreeBSD 7.X SVN (sys/i386/include/atomic.h), + with changes regarding optimizations and generalizations, and a + remake of the interface to fit use C++ features. + + Code is distributed under original license. + Original copyright follows: + + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +*/ + +#ifndef _ATOMIC_HPP_ +#define _ATOMIC_HPP_ + +namespace Atomic +{ + // Macros used to insert compare and exchange instructions easily into functions. + + #define MAKE_CMPXCHG_FUNCTION(INS, PTR, EXP, VAL, TYPE) \ + PunnedType pexp; pexp.valtype = EXP; \ + PunnedType pval; pval.valtype = VAL; \ + TYPE vexp = *(pexp.podtype); \ + TYPE vval = *(pval.podtype); \ + TYPE res; \ + unsigned char chg = 0; \ + asm volatile("lock;" INS "sete %1;" \ + : "=a" (res), /* 0 */ \ + "=q" (chg), /* 1 */ \ + "=m" (*(unsigned char **)(PTR)) /* 2 */ \ + : "r" (vval), /* 3 */ \ + "a" (vexp), /* 4 */ \ + "m" (*(unsigned char **)(PTR)) /* 5 */ \ + : "memory"); \ + *(pexp.podtype) = res; \ + return (chg != 0 ? true : false); + + #define MAKE_CMPXCHG8B_FUNCTION(PTR,EXP,VAL) \ + PunnedType pexp; pexp.valtype = EXP; \ + PunnedType pval; pval.valtype = VAL; \ + unsigned long long vexp = *(pexp.podtype); \ + unsigned long long vval = *(pval.podtype); \ + unsigned long long res = (unsigned long long)exp; \ + unsigned char chg = 0; \ + asm volatile("lock; cmpxchg8b %2; sete %1;" \ + : "+A" (vexp), /* 0 (result) */ \ + "=q" (chg) /* 1 */ \ + : "m" (*(unsigned char**)(PTR)), /* 2 */ \ + "b" ((unsigned long)(vval)), \ + "c" ((unsigned long)(vval >> 32))); \ + *(pexp.podtype) = vexp; \ + return (chg != 0 ? true : false); + + // Types used for making CMPXCHG instructions independent from base type. + + template < typename ValType, typename PodType > + union PunnedTypeTemplate + { + ValType * valtype; + PodType * podtype; + }; + + template < int SizeOfType, typename ReturnType > + struct HelperCreateCAS; + + template < typename ValType > + struct HelperCreateCAS<4, ValType> + { + #if !defined(__LP64__) && !defined(__LP64) + typedef unsigned long BaseType; + #else + typedef unsigned int BaseType; + #endif + + typedef PunnedTypeTemplate< ValType, BaseType > PunnedType; + + inline static bool apply(volatile void *p, ValType * exp, ValType now) + { + #if !defined(__LP64__) && !defined(__LP64) + MAKE_CMPXCHG_FUNCTION("cmpxchgl %3,%5;", p, exp, &now, BaseType); + #else + MAKE_CMPXCHG_FUNCTION("cmpxchgl %k3,%5;", p, exp, &now, BaseType); + #endif + } + }; + + template < typename ValType > + struct HelperCreateCAS<8, ValType> + { + #if !defined(__LP64__) && !defined(__LP64) + typedef unsigned long long BaseType; + #else + typedef unsigned long BaseType; + #endif + + typedef PunnedTypeTemplate< ValType, BaseType > PunnedType; + + inline static volatile ValType apply(volatile void *p, ValType * exp, ValType now) + { + #if !defined(__LP64__) && !defined(__LP64) + MAKE_CMPXCHG8B_FUNCTION(p, exp, &now); + #else + MAKE_CMPXCHG_FUNCTION("cmpxchgq %3,%5;", p, exp, &now, BaseType); + #endif + } + + }; + + // The CAS function itself. + + template < typename ValType > + inline bool doCAS(volatile ValType * p, ValType * o, ValType n) + { + return HelperCreateCAS::apply(static_cast(p), o, n); + }; + + template < typename ValType > + inline bool doCAS(volatile ValType * p, ValType o, ValType n) + { + return HelperCreateCAS::apply(static_cast(p), &o, n); + }; + + #undef MAKE_CMPXCHG_32_FUNCTION + #undef MAKE_CMPXCHG_64_FUNCTION + + #define MAKE_LOCKED_TEMPLATE(NAME) \ + template < typename ValType > inline void do##NAME(volatile ValType * p, ValType v); \ + template < typename ValType > inline void do##NAME(volatile ValType * p); + + #define MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \ + template < > inline void do##NAME < TYPE > (volatile TYPE * p, TYPE v){ asm volatile("lock;" INS : "=m" (*p) : CONS (VAL), "m" (*p)); } \ + template < > inline void do##NAME < TYPE > (volatile TYPE * p) { asm volatile("lock;" INS : "=m" (*p) : CONS (1), "m" (*p)); } + + #define MAKE_LOCKED_FUNCTIONS(NAME, TYPE, INS, CONS, VAL) \ + MAKE_LOCKED_FUNCTION(NAME, TYPE, INS, CONS, VAL) \ + MAKE_LOCKED_FUNCTION(NAME, unsigned TYPE, INS, CONS, VAL) + + MAKE_LOCKED_TEMPLATE(Add); + MAKE_LOCKED_TEMPLATE(Sub); + MAKE_LOCKED_TEMPLATE(SetBits); + MAKE_LOCKED_TEMPLATE(ClearBits); + + MAKE_LOCKED_FUNCTIONS(Add, int, "addl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(Sub, int, "subl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(SetBits, int, "orl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(ClearBits, int, "andl %1,%0", "ir", ~v); + + #if !defined(__LP64__) && !defined(__LP64) + + MAKE_LOCKED_FUNCTIONS(Add, long, "addl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(Sub, long, "subl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(SetBits, long, "orl %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andl %1,%0", "ir", ~v); + + #else + + MAKE_LOCKED_FUNCTIONS(Add, long, "addq %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(Sub, long, "subq %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(SetBits, long, "orq %1,%0", "ir", v); + MAKE_LOCKED_FUNCTIONS(ClearBits, long, "andq %1,%0", "ir", ~v); + + #endif +}; + +#endif /* _ATOMIC_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/config_commons.hpp b/src/mod/endpoints/mod_khomp/commons/config_commons.hpp new file mode 100644 index 0000000000..de8f327df4 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/config_commons.hpp @@ -0,0 +1,69 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _CONFIG_COMMONS_HPP_ +#define _CONFIG_COMMONS_HPP_ + +/****************************************************************************/ +/* ASTERISK */ +#if defined(COMMONS_LIBRARY_USING_ASTERISK) + #define COMMONS_IMPLEMENTATION asterisk +/****************************************************************************/ +/* CALLWEAVER */ +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) + #define COMMONS_IMPLEMENTATION callweaver +/****************************************************************************/ +/* FREESWITCH */ +#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) + #define COMMONS_IMPLEMENTATION freeswitch +/****************************************************************************/ +/* GNU/LINUX (generic) */ +#elif defined(COMMONS_LIBRARY_USING_GNU_LINUX) + #define COMMONS_IMPLEMENTATION gnulinux +/****************************************************************************/ +#else + #error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly. +#endif + +#define COMMONS_INCLUDE(file) + +#endif /* _CONFIG_COMMONS_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/config_options.cpp b/src/mod/endpoints/mod_khomp/commons/config_options.cpp new file mode 100644 index 0000000000..5383855f65 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/config_options.cpp @@ -0,0 +1,710 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, string_allowed_type allowed, bool list_me) +: _my_name(name), _value_data(new StringData(const_cast(value), defvalue, allowed), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, const ConfigOption::StringType & value, const ConfigOption::StringType defvalue, bool list_me) +: _my_name(name), _value_data(new StringData(const_cast(value), defvalue, string_allowed_type()), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, const ConfigOption::SignedIntType & value, const ConfigOption::SignedIntType defvalue, + ConfigOption::SignedIntType min, ConfigOption::SignedIntType max, ConfigOption::SignedIntType step, bool list_me) +: _my_name(name), _value_data(new SignedIntData(const_cast(value), defvalue, Range(min, max, step)), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, const ConfigOption::UnsignedIntType & value, const ConfigOption::UnsignedIntType defvalue, + ConfigOption::UnsignedIntType min, ConfigOption::UnsignedIntType max, ConfigOption::UnsignedIntType step, bool list_me) +: _my_name(name), _value_data(new UnsignedIntData(const_cast(value), defvalue, Range(min, max, step)), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, const ConfigOption::BooleanType & value, const ConfigOption::BooleanType defvalue, bool list_me) +: _my_name(name), _value_data(new BooleanData(const_cast(value), defvalue), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, string_allowed_type allowed, bool list_me) +: _my_name(name), _value_data(new FunctionData(fun, defvalue, allowed), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(std::string name, ConfigOption::FunctionType fun, std::string defvalue, bool list_me) +: _my_name(name), _value_data(new FunctionData(fun, defvalue, string_allowed_type()), true), + _list_me(list_me), _values(NULL), _loaded(false) +{}; + +ConfigOption::ConfigOption(const ConfigOption & o) +: _my_name(o._my_name), _value_data(o._value_data), + _list_me(o._list_me), _values(o._values), _loaded(o._loaded) +{}; + +ConfigOption::~ConfigOption(void) +{ + if (_values) + { + for (unsigned int i = 0; _values[i] != NULL; i++) + delete _values[i]; + + delete[] _values; + _values = NULL; + } +}; + +void ConfigOption::set(ConfigOption::StringType value) +{ + switch (_value_data.which()) + { + case ID_STRING: + { + try + { + StringData & tmp = _value_data.get(); + + if (tmp.string_allowed.empty()) + { + tmp.string_val = value; + _loaded = true; + } + else + { + if (tmp.string_allowed.find(value) != tmp.string_allowed.end()) + { + tmp.string_val = value; + _loaded = true; + return; + } + + std::string allowed_string; + + for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++) + { + allowed_string += " '"; + allowed_string += (*i); + allowed_string += "'"; + } + + throw ConfigProcessFailure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)") + % value % _my_name % allowed_string)); + } + break; + } + catch(ValueType::InvalidType & e) + { + throw; + } + } + + case ID_FUN: + { + try + { + FunctionData & tmp = _value_data.get(); + tmp.fun_val(value); + _loaded = true; + break; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + } + + default: + { + throw ConfigProcessFailure(STG(FMT("option '%s' is not of type string, nor function defined") % _my_name)); + } + } +} + +void ConfigOption::set(ConfigOption::SignedIntType value) +{ + try + { + SignedIntData & tmp = _value_data.get(); + + if (value < tmp.sint_Range.minimum) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name)); + + if (value > tmp.sint_Range.maximum) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name)); + + if (((value - tmp.sint_Range.minimum) % tmp.sint_Range.step) != 0) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name)); + + tmp.sint_val = value; + _loaded = true; + } + catch(ValueType::InvalidType & e) + { + throw; + } +} + +void ConfigOption::set(ConfigOption::UnsignedIntType value) +{ + try + { + UnsignedIntData & tmp = _value_data.get(); + + if (value < tmp.uint_Range.minimum) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too low)") % value % _my_name)); + + if (value > tmp.uint_Range.maximum) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (too high)") % value % _my_name)); + + if (((value - tmp.uint_Range.minimum) % tmp.uint_Range.step) != 0) + throw ConfigProcessFailure(STG(FMT("value '%d' out-of-Range for option '%s' (outside allowed step)") % value % _my_name)); + + tmp.uint_val = value; + _loaded = true; + } + catch(ValueType::InvalidType & e) + { + throw; + } +} + +void ConfigOption::set(ConfigOption::BooleanType value) +{ + try + { + BooleanData & tmp = _value_data.get(); + tmp.bool_val = value; + _loaded = true; + } + catch(ValueType::InvalidType & e) + { + throw; + } +} + +std::string & ConfigOption::name(void) { return _my_name; }; + +ConfigOption::value_id_type ConfigOption::type(void) +{ + return (value_id_type) _value_data.which(); +}; + +const char ** ConfigOption::values(void) +{ + if (_values != NULL) + return _values; + + switch ((value_id_type) _value_data.which()) + { + case ConfigOption::ID_BOOL: + { + _values = new const char*[3]; + + _values[0] = strdup("yes"); + _values[1] = strdup("no"); + _values[2] = NULL; + + return _values; + } + + case ConfigOption::ID_SINT: + { + try + { + SignedIntData & tmp = _value_data.get(); + + + unsigned int count = ((tmp.sint_Range.maximum - tmp.sint_Range.minimum) / tmp.sint_Range.step) + 1; + unsigned int index = 0; + + _values = new const char*[count + 1]; + + for (SignedIntType i = tmp.sint_Range.minimum; i <= tmp.sint_Range.maximum; i += tmp.sint_Range.step, index++) + _values[index] = strdup(STG(FMT("%d") % i).c_str()); + + _values[index] = NULL; + + return _values; + } + catch(ValueType::InvalidType & e) + { + throw; + } + } + + case ConfigOption::ID_UINT: + { + try + { + UnsignedIntData & tmp = _value_data.get(); + + unsigned int count = ((tmp.uint_Range.maximum - tmp.uint_Range.minimum) / tmp.uint_Range.step) + 1; + unsigned int index = 0; + + _values = new const char*[count + 1]; + + for (UnsignedIntType i = tmp.uint_Range.minimum; i <= tmp.uint_Range.maximum; i += tmp.uint_Range.step, index++) + _values[index] = strdup(STG(FMT("%d") % i).c_str()); + + _values[index] = NULL; + + return _values; + } + catch(ValueType::InvalidType & e) + { + throw; + } + } + + case ConfigOption::ID_STRING: + { + try + { + StringData & tmp = _value_data.get(); + + _values = new const char*[ tmp.string_allowed.size() + 1 ]; + + unsigned int index = 0; + + for (string_allowed_type::iterator i = tmp.string_allowed.begin(); i != tmp.string_allowed.end(); i++, index++) + _values[index] = strdup((*i).c_str()); + + _values[index] = NULL; + + return _values; + } + catch(ValueType::InvalidType & e) + { + throw; + } + } + + case ConfigOption::ID_FUN: + { + try + { + FunctionData & tmp = _value_data.get(); + + _values = new const char*[ tmp.fun_allowed.size() + 1 ]; + + unsigned int index = 0; + + for (string_allowed_type::iterator i = tmp.fun_allowed.begin(); i != tmp.fun_allowed.end(); i++, index++) + _values[index] = strdup((*i).c_str()); + + _values[index] = NULL; + return _values; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + } + + default: + throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } +}; + +void ConfigOption::reset(void) +{ + _loaded = false; +}; + +void ConfigOption::commit(void) +{ + if (_loaded) + return; + + switch ((value_id_type) _value_data.which()) + { + case ConfigOption::ID_BOOL: + { + try + { + BooleanData & tmp = _value_data.get(); + tmp.bool_val = tmp.bool_default; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + break; + } + + case ConfigOption::ID_SINT: + { + try + { + SignedIntData & tmp = _value_data.get(); + tmp.sint_val = tmp.sint_default; + } + catch(ValueType::InvalidType & e) + { + throw; + } + break; + } + + case ConfigOption::ID_UINT: + { + try + { + UnsignedIntData & tmp = _value_data.get(); + tmp.uint_val = tmp.uint_default; + } + catch(ValueType::InvalidType & e) + { + throw; + } + break; + } + + case ConfigOption::ID_STRING: + { + try + { + StringData & tmp = _value_data.get(); + tmp.string_val = tmp.string_default; + } + catch(ValueType::InvalidType & e) + { + throw; + } + break; + } + + case ConfigOption::ID_FUN: + { + try + { + FunctionData & tmp = _value_data.get(); + tmp.fun_val(tmp.fun_default); + } + catch(ValueType::InvalidType & e) + { + throw; + } + break; + } + + default: + throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } + + _loaded = true; +}; + +void ConfigOption::copy_from(ConfigOption & src) +{ + if (src._value_data.which() != _value_data.which()) + throw ConfigProcessFailure(STG(FMT("unable to copy options, source type differs from destination."))); + + if (!src._loaded) + return; + + switch ((value_id_type) _value_data.which()) + { + case ConfigOption::ID_BOOL: + { + try + { + BooleanData & stmp = src._value_data.get(); + BooleanData & dtmp = _value_data.get(); + /* do not copy references, but values.. */ + bool tmpval = stmp.bool_val; + dtmp.bool_val = tmpval; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + break; + } + + case ConfigOption::ID_SINT: + { + try + { + SignedIntData & stmp = src._value_data.get(); + SignedIntData & dtmp = _value_data.get(); + /* do not copy references, but values.. */ + int tmpval = stmp.sint_val; + dtmp.sint_val = tmpval; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + break; + } + + case ConfigOption::ID_UINT: + { + try + { + UnsignedIntData & stmp = src._value_data.get(); + UnsignedIntData & dtmp = _value_data.get(); + /* do not copy references, but values.. */ + unsigned int tmpval = stmp.uint_val; + dtmp.uint_val = tmpval; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + + break; + } + + case ConfigOption::ID_STRING: + { + try + { + StringData & stmp = src._value_data.get(); + StringData & dtmp = _value_data.get(); + /* do not copy references, but values.. */ + std::string tmpval = stmp.string_val; + dtmp.string_val = tmpval; + } + catch(ValueType::InvalidType & e) + { + throw; + } + + break; + } + + case ConfigOption::ID_FUN: + { + /* TO IMPLEMENT (NEEDS ANOTHER METHOD ON FUNCTION FOR GETTING VALUE) */ + +// FunctionData & tmp = boost::get(_value_data); +// +// if (!tmp.loaded) +// { +// tmp.fun_val(tmp.fun_default); +// tmp.loaded = true; +// } + break; + } + + default: + throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % _value_data.which())); + } + + _loaded = true; +}; + +/*********************************/ + +bool ConfigOptions::add(ConfigOption option) +{ + //option_map_type::iterator iter2 = _map.begin(); + + //boost::tie(iter2, ok2) + std::pair ret = _map.insert(option_pair_type(option.name(), option)); + + return ret.second; +} + +bool ConfigOptions::synonym(std::string equiv_opt, std::string main_opt) +{ + //syn_option_map_type::iterator iter = _syn_map.begin(); + + //boost::tie(iter, ok) + std::pair ret = _syn_map.insert(syn_option_pair_type(equiv_opt, main_opt)); + + return ret.second; +} + +ConfigOptions::string_set ConfigOptions::options(void) +{ + string_set res; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + res.insert((*i).first); + + return res; +} + +void ConfigOptions::process(const char * name, const char * value) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name)); + + try + { + switch ((*iter).second.type()) + { + case ConfigOption::ID_SINT: + set((*iter).first, Strings::toulong(value)); + return; + case ConfigOption::ID_UINT: + set((*iter).first, Strings::tolong(value)); + return; + case ConfigOption::ID_BOOL: + set((*iter).first, Strings::toboolean(value)); + return; + case ConfigOption::ID_STRING: + case ConfigOption::ID_FUN: + set((*iter).first, std::string(value)); + return; + default: + throw ConfigProcessFailure(STG(FMT("unknown type identifier '%d'") % (*iter).second.type())); + } + } + catch (Strings::invalid_value & e) + { + throw ConfigProcessFailure(STG(FMT("invalid value '%s' for option '%s'") % value % name)); + } +} + +const char ** ConfigOptions::values(const char * name) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option '%s'") % name)); + + return (*iter).second.values(); +} + +const char ** ConfigOptions::values(void) +{ + if (_values != NULL) + return _values; + + unsigned int count = 0; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + if ((*i).second.list_me()) + ++count; + + _values = new const char*[ count + 1 ]; + + unsigned int index = 0; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + { + if ((*i).second.list_me()) + { + _values[index] = strdup((*i).first.c_str()); + ++index; + } + } + + _values[index] = NULL; + + return _values; +} + +void ConfigOptions::reset(void) +{ + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + (*i).second.reset(); +} + +ConfigOptions::messages_type ConfigOptions::commit(void) +{ + messages_type msgs; + + for (option_map_type::iterator i = _map.begin(); i != _map.end(); i++) + { + try + { + (*i).second.commit(); + } + catch (ConfigProcessFailure & e) + { + msgs.push_back(e.msg); + } + } + + return msgs; +} + +bool ConfigOptions::loaded(std::string name) +{ + option_map_type::iterator iter = find_option(name); + + if (iter == _map.end()) + return false; + + return iter->second.loaded(); +} + +void ConfigOptions::copy_from(ConfigOptions & source, std::string name) +{ + option_map_type::iterator iter_src = source.find_option(name); + option_map_type::iterator iter_dst = find_option(name); + + if (iter_src == source._map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option '%s' on source") % name)); + + if (iter_dst == _map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option '%s' on destination") % name)); + + iter_dst->second.copy_from(iter_src->second); +} + +ConfigOptions::option_map_type::iterator ConfigOptions::find_option(std::string name) +{ + syn_option_map_type::iterator syn_iter = _syn_map.find(name); + + if (syn_iter != _syn_map.end()) + name = syn_iter->second; + + option_map_type::iterator iter = _map.find(name); + + return iter; +} diff --git a/src/mod/endpoints/mod_khomp/commons/config_options.hpp b/src/mod/endpoints/mod_khomp/commons/config_options.hpp new file mode 100644 index 0000000000..3cfe2e1c78 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/config_options.hpp @@ -0,0 +1,286 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +#ifndef _CONFIG_OPTIONS_HPP_ +#define _CONFIG_OPTIONS_HPP_ + +struct ConfigProcessFailure +{ + ConfigProcessFailure(std::string _msg): msg(_msg) {}; + std::string msg; +}; + +struct ConfigOption +{ + typedef int SignedIntType; + typedef unsigned int UnsignedIntType; + typedef bool BooleanType; + typedef std::string StringType; + + typedef Function::Function1 < void, std::string > FunctionType; + + typedef std::set < StringType > string_allowed_type; + + /* this should reflect 'variant.which()'! */ + typedef enum + { + ID_SINT = 0, + ID_UINT = 1, + ID_BOOL = 2, + ID_STRING = 3, + ID_FUN = 4, + } + value_id_type; + + template < typename number_type > + struct Range + { + Range(number_type _minimum, number_type _maximum, number_type _step) + : minimum(_minimum), maximum(_maximum), step(_step) {}; + + number_type minimum, maximum, step; + }; + + struct SignedIntData : public VariantBaseType < void > + { + SignedIntData(SignedIntType & _sint_val, SignedIntType _sint_default, Range< SignedIntType > _sint_Range) + : sint_val(_sint_val), sint_default(_sint_default), sint_Range(_sint_Range) {}; + + int which() + { + return ID_SINT; + } + + SignedIntType & sint_val; + SignedIntType sint_default; + Range sint_Range; + }; + + struct UnsignedIntData : public VariantBaseType < void > + { + UnsignedIntData(UnsignedIntType & _uint_val, UnsignedIntType _uint_default, Range< UnsignedIntType > _uint_Range) + : uint_val(_uint_val), uint_default(_uint_default), uint_Range(_uint_Range) {}; + + int which() + { + return ID_UINT; + } + + UnsignedIntType & uint_val; + UnsignedIntType uint_default; + Range uint_Range; + }; + + struct BooleanData : public VariantBaseType < void > + { + BooleanData(BooleanType & _bool_val, BooleanType _bool_default) + : bool_val(_bool_val), bool_default(_bool_default) {}; + + int which() + { + return ID_BOOL; + } + + BooleanType & bool_val; + BooleanType bool_default; + }; + + struct StringData : public VariantBaseType < void > + { + StringData(std::string & _string_val, std::string _string_default, string_allowed_type _string_allowed) + : string_val(_string_val), string_default(_string_default), string_allowed(_string_allowed) {}; + + int which() + { + return ID_STRING; + } + + std::string & string_val; + std::string string_default; + string_allowed_type string_allowed; + }; + + struct FunctionData : public VariantBaseType < void > + { + FunctionData(FunctionType _fun_val, std::string _fun_default, string_allowed_type _fun_allowed) + : fun_val(_fun_val), fun_default(_fun_default), fun_allowed(_fun_allowed) {}; + + int which() + { + return ID_FUN; + } + + FunctionType fun_val; + std::string fun_default; + string_allowed_type fun_allowed; + }; + + + typedef Variant < VariantBaseType < void > > ValueType; + + ConfigOption(std::string, const StringType &, const StringType, string_allowed_type allowed, bool list_me = true); + ConfigOption(std::string, const StringType &, const StringType = "", bool list_me = true); + ConfigOption(std::string, const SignedIntType &, const SignedIntType = 0, SignedIntType min = -INT_MAX, SignedIntType max = INT_MAX, SignedIntType step = 1, bool list_me = true); + ConfigOption(std::string, const UnsignedIntType &, const UnsignedIntType = 0, UnsignedIntType min = 0, UnsignedIntType max = UINT_MAX, UnsignedIntType step = 1, bool list_me = true); + ConfigOption(std::string, const BooleanType &, const BooleanType = false, bool list_me = true); + ConfigOption(std::string, FunctionType, std::string defvalue, string_allowed_type allowed, bool list_me = true); + ConfigOption(std::string, FunctionType, std::string defvalue = "", bool list_me = true); + + ConfigOption(const ConfigOption & o); + + ~ConfigOption(void); + + void set(StringType value); + + void set(SignedIntType value); + void set(UnsignedIntType value); + void set(BooleanType value); + + BooleanType get_bool(){ return _value_data.get().bool_val; } + std::string get_str(){ return _value_data.get().string_val; } + SignedIntType get_sint(){ return _value_data.get().sint_val; } + UnsignedIntType get_uint(){ return _value_data.get().uint_val; } + + std::string & name(void); + value_id_type type(void); + + const char ** values(void); + + void reset(void); + void commit(void); + + bool list_me(void) { return _list_me; }; + bool loaded(void) { return _loaded; }; + + void copy_from(ConfigOption &); + + protected: + std::string _my_name; + ValueType _value_data; + + bool _list_me; + const char ** _values; + bool _loaded; +}; + +struct ConfigOptions +{ + typedef std::vector < std::string > messages_type; + + ConfigOptions(void): _values(NULL) {}; + + typedef std::set < std::string > string_set; + + typedef std::map < std::string, ConfigOption > option_map_type; + typedef std::pair < std::string, ConfigOption > option_pair_type; + + typedef std::map < std::string, std::string > syn_option_map_type; + typedef std::pair < std::string, std::string > syn_option_pair_type; + + bool add(ConfigOption option); + + /* only valid in "process" (for backwards compatibility config files) */ + bool synonym(std::string, std::string); + + template + void set(std::string name, ValueType value) + { + option_map_type::iterator iter = _map.find(name); + + if (iter == _map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name)); + + (*iter).second.set(value); + } + + std::string get(std::string name) + { + option_map_type::iterator iter = _map.find(name); + + if (iter == _map.end()) + throw ConfigProcessFailure(STG(FMT("unknown option: %s") % name)); + + switch((*iter).second.type()) + { + case ConfigOption::ID_BOOL: return (*iter).second.get_bool() ? "yes" : "no"; + case ConfigOption::ID_STRING: return (*iter).second.get_str(); + case ConfigOption::ID_UINT: return STG(FMT("%d") % (*iter).second.get_uint()); + case ConfigOption::ID_SINT: return STG(FMT("%d") % (*iter).second.get_sint()); + case ConfigOption::ID_FUN: return ""; + } + } + + string_set options(void); + + void process(const char *, const char *); /* process option from file */ + + void reset(void); /* reset loaded opts */ + messages_type commit(void); /* set defaults */ + + const char ** values(const char *); /* option value */ + const char ** values(void); /* values from options */ + + bool loaded(std::string); /* return if config was loaded */ + + void copy_from(ConfigOptions &, std::string); + + protected: + option_map_type::iterator find_option(std::string); + + protected: + option_map_type _map; + syn_option_map_type _syn_map; + + const char ** _values; +}; + +#endif /* _CONFIG_OPTIONS_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp new file mode 100644 index 0000000000..6aa2e59201 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/configfile.cpp @@ -0,0 +1,241 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ +#include + +#include + +#if _MSC_VER >= 1400 +#undef close +#endif + +void Configfile::ignore(std::string str) +{ + _ignores.insert(str); +}; + +bool Configfile::select(Section **ptr, std::string str) +{ + /* default section == this! */ + *ptr = this; + + /* always success by default */ + return true; +}; + +bool Configfile::adjust(Section * section, std::string & opt, std::string & val) +{ + return section->load(opt, val); +}; + +bool Configfile::deserialize(std::ifstream& fd) +{ + Section * section = NULL; + + /* default selection! */ + if (!select(§ion)) + { + _errors.push_back("default selection has failed!"); + return false; + } + + size_t count = 0; + + while (fd.good()) + { + std::string str; + + /* read one line! */ + std::getline(fd, str); + + size_t lst = str.size() - 1; + + if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n + { + str.erase(lst,1); + --lst; + } + + /* empty line! */ + if (str.size() == 0) + continue; + + /* comment! */ + if (str[0] == '#') + continue; + + ++count; + + if (str[0] == '[' && str[lst] == ']') + { + str.erase(0,1); --lst; + str.erase(lst,1); --lst; + + if (!select(§ion, str)) + { + _errors.push_back(STG(FMT("erroneous section '%s'") % str)); + + /* ignore this section */ + section = NULL; + continue; + } + } + else + { + std::string::size_type pos = str.find('='); + + if (pos == std::string::npos) + { + _errors.push_back(STG(FMT("erroneous separator '%s'") % str)); + continue; + }; + + if (section == NULL) + { + _errors.push_back(STG(FMT("no section for option '%s'") % str)); + continue; + } + + std::string opt(str.substr(0,pos)); + std::string val(str.substr(pos+1)); + + if (_ignores.find(opt) != _ignores.end()) + continue; + + if (val == "@") val = ""; + + if (adjust(section, opt, val)) + continue; + + _errors.push_back(STG(FMT("option '%s' does " + "not exist or '%s' is not a valid value (at section '%s')") + % opt % val % section->name())); + } + } + + // retorna 'true' se arquivo tinha alguma coisa valida. + return (count != 0); +} + +bool Configfile::obtain() +{ + std::ifstream fd(_filename.c_str()); + + if (!fd.is_open()) + { + _errors.push_back(STG(FMT("unable to open file '%s': %s") + % _filename % strerror(errno))); + return false; + }; + + if (!deserialize(fd)) + { + fd.close(); + return false; + } + + fd.close(); + return true; +}; + +void Configfile::recurse(std::ofstream& fd, Section * section) +{ + typedef Section::SectionMap::iterator section_iter; + typedef Section::OptionMap::iterator option_iter; + + for (option_iter i = section->option_begin(); i != section->option_end(); i++) + { + std::string res; + + if ((*i).second.store(res)) + { + if (res == "") res = "@"; + fd << (*i).first << "=" << res << std::endl; + } + } + + if (!section->recursive()) + return; + + for (section_iter j = section->section_begin(); j != section->section_end(); j++) + recurse(fd, (*j).second); +} + +bool Configfile::serialize(std::ofstream& fd) +{ + recurse(fd, this); + return true; +} + +bool Configfile::provide() +{ + std::string tmp(_filename); + tmp += ".new"; + + std::ofstream fd(tmp.c_str()); + + if (!fd.good()) + { + _errors.push_back(STG(FMT("unable to open file '%s': %s") + % tmp % strerror(errno))); + return false; + } + + if (!serialize(fd)) + { + fd.close(); + return false; + } + + fd.close(); + + if (rename(tmp.c_str(), _filename.c_str()) != 0) + { + _errors.push_back(STG(FMT("unable to replace config file '%s': %s") + % _filename % strerror(errno))); + return false; + } + + return true; +} + +#if _MSC_VER >= 1400 +#define close _close +#endif \ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp new file mode 100644 index 0000000000..61f42469af --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/configfile.hpp @@ -0,0 +1,90 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include +#include + +#include + +#include + +#ifndef _CONFIG_CONFIGFILE_HPP_ +#define _CONFIG_CONFIGFILE_HPP_ + +struct Configfile: public Section +{ + typedef std::list < std::string > ErrorVector; + typedef std::set < std::string > NameSet; + + Configfile(std::string name, std::string desc) + : Section(name, desc), _good(false) {}; + + virtual ~Configfile() {}; + + bool good() { return _good; }; + std::string & filename() { return _filename; }; + + ErrorVector & errors() { return _errors; }; + + void ignore(std::string); + + virtual bool obtain(); + virtual bool provide(); + + protected: + virtual bool select(Section **, std::string str = ""); + virtual bool adjust(Section *, std::string & opt, std::string & val); + + virtual bool deserialize(std::ifstream &); + virtual bool serialize(std::ofstream &); + + void recurse(std::ofstream &, Section *); + + protected: + bool _good; + ErrorVector _errors; + NameSet _ignores; + std::string _filename; +}; + +#endif /* _CONFIG_CONFIGFILE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp new file mode 100644 index 0000000000..083883e63f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/option.cpp @@ -0,0 +1,185 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +bool Option::equals(std::string & value) +{ + switch (_restriction.numeral()) + { + case Restriction::N_UNIQUE: + { + Restriction::Value my_value; + + if (!_restriction.get(Restriction::F_USER, my_value)) + return false; + + return (my_value == value); + } + case Restriction::N_MULTIPLE: + { + Restriction::Vector my_values; + + if (!_restriction.get(Restriction::F_USER, my_values)) + return false; + + for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++) + { + if ((*i) == value) + return true; + } + + return false; + } + } + + return false; +} + +bool Option::load(std::string & value) +{ + bool ret = _restriction.set(Restriction::F_FILE, value); + + if (ret) _modified = false; + + return ret; +} + +bool Option::change(std::string & value) +{ + bool ret = _restriction.set(Restriction::F_FILE, value); + + if (ret) _modified = true; + + return ret; +} + +bool Option::store(std::string & value) +{ + switch (_restriction.numeral()) + { + case Restriction::N_UNIQUE: + return _restriction.get(Restriction::F_FILE, value); + + case Restriction::N_MULTIPLE: + { + Restriction::Vector values; + + if (!_restriction.get(Restriction::F_FILE, values)) + return false; + + Strings::Merger strs; + + for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++) + strs.add(*i); + + value = strs.merge(","); + + return true; + } + + default: + return false; + } +} + +Option::Flags Option::set(const char * value) +{ + std::string str_value(value); + return set(str_value); +} + + +Option::Flags Option::set(Restriction::Value & value) +{ + Restriction::Value last_value, curr_value; + Flags flags; + + bool ret1 = _restriction.get(Restriction::F_USER, last_value); + + if (!_restriction.set(Restriction::F_USER, value)) + return flags; + + flags[F_ADJUSTED] = true; + + bool ret2 = _restriction.get(Restriction::F_USER, curr_value); + + if (!ret1 || (ret2 && (last_value != curr_value))) + { + flags[F_MODIFIED] = true; + _modified = true; + } + + return flags; +} + +Option::Flags Option::set(Restriction::Vector & values) +{ + Restriction::Vector last_values, curr_values; + Flags flags; + + bool ret1 = _restriction.get(Restriction::F_USER, last_values); + + if (!_restriction.set(Restriction::F_USER, values)) + return flags; + + flags[F_ADJUSTED] = true; + + bool ret2 = _restriction.get(Restriction::F_USER, curr_values); + + if (!ret1 || (ret2 && (last_values != curr_values))) + { + flags[F_MODIFIED] = true; + _modified = true; + } + + return flags; +} + +bool Option::get(Restriction::Value & value) +{ + return _restriction.get(Restriction::F_USER, value); +} + +bool Option::get(Restriction::Vector & values) +{ + return _restriction.get(Restriction::F_USER, values); +} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/option.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/option.hpp new file mode 100644 index 0000000000..8aa103a0cc --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/option.hpp @@ -0,0 +1,122 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include +#include +#include + +#include + +#include + +#ifndef _CONFIG_OPTION_HPP_ +#define _CONFIG_OPTION_HPP_ + +struct Option +{ + enum FlagTypes + { + F_MODIFIED = 0x0, /* if option was modified */ + F_ADJUSTED = 0x1, /* if option was correctly formated */ + }; + + struct Flags: public std::vector + { + Flags(): std::vector(2) {}; + }; + + typedef Restriction::Value Value; + typedef Restriction::Vector Vector; + + /* exception */ + struct InvalidDefaultValue + { + InvalidDefaultValue(std::string name, std::string value) + : _name(name), _value(value) {}; + + std::string & name() { return _name; }; + std::string & value() { return _value; }; + + protected: + std::string _name; + std::string _value; + }; + + Option(std::string name, std::string desc, std::string defvalue, Restriction restriction) + : _name(name), _desc(desc), _restriction(restriction), _modified(true) + { + std::string value(defvalue); + + if (!(set(value)[F_ADJUSTED])) + throw InvalidDefaultValue(name, defvalue); + } + + const std::string & name() { return _name; }; + const std::string & description() { return _desc; }; + + Restriction & restriction() { return _restriction; }; + bool modified() { return _modified; }; + + public: + bool load(std::string &); + bool change(std::string &); + bool store(std::string &); + + Flags set(const char *); + Flags set(Value &); + Flags set(Vector &); + + bool get(Value &); + bool get(Vector &); + + bool equals(std::string &); + + protected: + std::string _name; + std::string _desc; + + Restriction _restriction; + bool _modified; +}; + +#endif /* _CONFIG_OPTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp new file mode 100644 index 0000000000..9653a7c608 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.cpp @@ -0,0 +1,353 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include + +#include +#include + +#include + +/* internal helper! */ +bool Restriction::equalNumber(const double a, const double b) +{ + char tmp1[64]; + char tmp2[64]; + + snprintf(tmp1, sizeof(tmp1), "%.3f", a); + snprintf(tmp2, sizeof(tmp2), "%.3f", b); + + if (strncmp(tmp1, tmp2, sizeof(tmp1))) + return false; + + return true; +} + +/* process value to our internal representation */ + +bool Restriction::process(Restriction::Format fmt, + const Restriction::Value & value, Restriction::Value & final) +{ + switch (_bounds) + { + case B_RANGE: + { + if (_kind != K_NUMBER) + return false; + + std::string tmpvalue; + + Restriction::Value::const_iterator itr = value.begin(); + Restriction::Value::const_iterator end = value.end(); + + tmpvalue.reserve(value.size()); + + // f*cking dot/comma notation! + for (; itr != end; ++itr) + tmpvalue += ((*itr) != ',' ? (*itr) : '.'); + + try + { + double newvalue = Strings::todouble(tmpvalue); + + if (newvalue < _init && newvalue > _fini) + return false; + + double res = (newvalue - _init) / _step; + + if (!equalNumber(res, rint(res))) + return false; + + final = value; + return true; + } + catch (...) + { + return false; + } + } + + case B_LIST: + for (List::iterator i = _list.begin(); i != _list.end(); i++) + { + Value & tmp = (*i); + + if (tmp == value) + { + final = value; + return true; + } + } + return false; + + case B_MAPS: + switch (fmt) + { + case F_USER: + { + Map::iterator i = _map_from_usr.find(std::string(value)); + + if (i == _map_from_usr.end()) + return false; + + Value & tmp = (*i).second; + + final = tmp; + return true; + } + + case F_FILE: + { + Map::iterator i = _map_from_cfg.find(std::string(value)); + + if (i == _map_from_cfg.end()) + return false; + + final = value; + return true; + } + + default: + break; + } + return false; + + case B_FREE: + final = value; + return true; + + default: + break; + } + + return false; +} + +/* unprocess the value (outputs the external representation) */ + +bool Restriction::unprocess(Restriction::Format fmt, + const Restriction::Value & value, Restriction::Value & final) +{ + switch (_bounds) + { + case B_MAPS: + + switch (fmt) + { + case F_USER: + { + Map::iterator i = _map_from_cfg.find(std::string(value)); + + if (i == _map_from_cfg.end()) + return false; + + final = (*i).second; + return true; + } + default: + break; + } + + default: + final = value; + return true; + } +} + +/***************************** *****************************/ + +bool Restriction::get(Restriction::Format fmt, Restriction::Value & value) +{ + if (_numeral != N_UNIQUE) + return false; + + if (!unprocess(fmt, _value._unique, value)) + return false; + + return true; +} + +bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values) +{ + if (_numeral != N_MULTIPLE) + return false; + + List & my_values = _value._multiple; + + for (List::iterator i = my_values.begin(); i != my_values.end(); i++) + { + Value & value = (*i); + Value final; + + if (!unprocess(fmt, value, final)) + return false; + + values.push_back(final); + }; + + return true; +} + +/***************************** *****************************/ + +bool Restriction::set(Restriction::Format fmt, Restriction::Value &value) +{ + switch (_numeral) + { + case N_UNIQUE: + { + Value final; + + if (!process(fmt, value, final)) + return false; + + _value._unique = final; + return true; + } + + case N_MULTIPLE: + { + if (value == "@" || value == "#" || value == "") + { + _value._multiple.clear(); + return true; + } + + Strings::vector_type values; + Strings::tokenize(value, values, ","); + + return set(fmt, values); + } + + default: + return false; + } +} + +bool Restriction::set(Restriction::Format fmt, Restriction::Vector & values) +{ + if (_numeral != N_MULTIPLE) + return false; + + if (values.empty()) + { + _value._multiple.clear(); + } + else + { + /* list needed to store temporary values */ + List finals; + + for (Vector::iterator i = values.begin(); i != values.end(); i++) + { + Value & value = (*i); + Value final; + + if (!process(fmt, value, final)) + return false; + + finals.push_back(final); + } + + List & lst = _value._multiple; + + /* need to clear values set before */ + lst.clear(); + + for (List::iterator i = finals.begin(); i != finals.end(); i++) + { + Value value = (*i); + lst.push_back(value); + } + }; + + return true; +} + +/***************************** *****************************/ + +void Restriction::allowed(Restriction::Vector &vals) +{ + switch (_bounds) + { + case B_FREE: + return; + + case B_LIST: + for (List::iterator i = _list.begin(); i != _list.end(); i++) + vals.push_back((*i)); + break; + + case B_MAPS: + for (Map::iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++) + vals.push_back((*i).first); + break; + + case B_RANGE: + { + if (_kind != K_NUMBER) + return; + + // is there any fraction? + bool has_fraction = (!equalNumber(_init, rint(_init))) || (!equalNumber(_fini, rint(_fini))) || (!equalNumber(_step, rint(_step))); + + const char * format = (has_fraction ? "%.2f" : "%02.0f"); + + for (double i = _init; i <= _fini; i += _step) + { + char tmp[32]; + snprintf(tmp, sizeof(tmp), format, i); + vals.push_back(std::string(tmp)); + } + break; + } + + default: + break; + } +} + +void Restriction::init_class() +{ + _value._unique.clear(); + _value._multiple.clear(); +} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp new file mode 100644 index 0000000000..0815ede3db --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/restriction.hpp @@ -0,0 +1,321 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include +#include +#include +#include + +#ifndef _CONFIG_RESTRICTION_HPP_ +#define _CONFIG_RESTRICTION_HPP_ + +struct Restriction +{ + /* generic types */ + enum Format + { + F_USER, + F_FILE + }; + + enum Kind + { +// K_INTEGER, +// K_FLOAT, + K_STRING, + K_NUMBER // = K_INTEGER // compatibility + }; + + enum Bounds + { + B_FREE, + B_RANGE, + B_LIST, + B_MAPS + }; + + enum Numeral + { + N_UNIQUE, + N_MULTIPLE + }; + + typedef std::string Value; + + /* types used for data input */ + struct Pair + { + const char *pretty; + const char *value; + }; + + typedef std::pair < Value, Value > PairMap; + typedef std::list < PairMap > ListMap; + + /* types used internally */ + typedef std::map < Value, Value > Map; + typedef std::vector < Value > Vector; + + typedef std::list < Value > List; + typedef std::pair < Value, Value > MapPair; + + struct Generic + { + Value _unique; + List _multiple; + }; + + Restriction(Kind kind, Numeral num) + : _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + init_class(); + } + +/* + Restriction(Kind kind, Numeral num, + int init, int fini, int step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(init), _ifini(fini), _istep(step), + _finit(-1), _ffini(-1), _fstep(-1) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *unit, int init, int fini, int step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(init), _ifini(fini), _istep(step), + _finit(-1), _ffini(-1), _fstep(-1) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + std::string unit, int init, int fini, int step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(init), _ifini(fini), _istep(step), + _finit(-1), _ffini(-1), _fstep(-1) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + float init, float fini, float step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(-1), _ifini(-1), _istep(-1) + _finit(init), _ffini(fini), _fstep(step), + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *unit, float init, float fini, float step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(-1), _ifini(-1), _istep(-1) + _finit(init), _ffini(fini), _fstep(step), + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + std::string unit, float init, float fini, float step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _iinit(-1), _ifini(-1), _istep(-1) + _finit(init), _ffini(fini), _fstep(step), + { + init_class(); + } +*/ + + Restriction(Kind kind, Numeral num, + double init, double fini, double step = 1) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *unit, double init, double fini, double step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + std::string unit, double init, double fini, double step = 1.0) + : _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit), + _init(init), _fini(fini), _step(step) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, + const char *first, ...) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + _list.push_back(std::string(first)); + + va_list ap; + va_start(ap, first); + + while (true) + { + const char *arg = va_arg(ap, const char *); + + if (arg == NULL) break; + + _list.push_back(std::string(arg)); + } + + init_class(); + } + + Restriction(Kind kind, const char *unit, Numeral num, + const char *first, ...) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit), + _init(-1), _fini(-1), _step(-1) + { + _list.push_back(std::string(first)); + + va_list ap; + va_start(ap, first); + + while (true) + { + const char *arg = va_arg(ap, const char *); + + if (arg == NULL) break; + + _list.push_back(std::string(arg)); + } + + init_class(); + } + + Restriction(Kind kind, Numeral num, + const struct Pair first, ...) + : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + _map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value))); + _map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty))); + + va_list ap; + va_start(ap, first); + + while (true) + { + Pair arg = va_arg(ap, Pair); + + if (arg.pretty == NULL) break; + + _map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value))); + _map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty))); + } + + init_class(); + } + + Restriction(Kind kind, Numeral num, List list) + : _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1), _list(list) + { + init_class(); + } + + Restriction(Kind kind, Numeral num, ListMap map) + : _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""), + _init(-1), _fini(-1), _step(-1) + { + for (ListMap::iterator i = map.begin(); i != map.end(); i++) + { + _map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second))); + _map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first))); + } + + init_class(); + } + + Kind kind() { return _kind; }; + Bounds bounds() { return _bounds; }; + Numeral numeral() { return _numeral; }; + + Value unit() { return _unit; }; + + bool set(Format, Vector &); + bool set(Format, Value &); + + bool get(Format, Vector &); + bool get(Format, Value &); + + void allowed(Vector &); + + private: + bool process(Format, const Value &, Value &); + bool unprocess(Format, const Value &, Value &); + void init_class(); + + bool equalNumber(const double, const double); + + protected: + Kind _kind; + Bounds _bounds; + Numeral _numeral; + + Value _unit; + + double _init, _fini, _step; + + Map _map_from_usr, + _map_from_cfg; + + List _list; + + Generic _value; +}; + +#endif /* _CONFIG_RESTRICTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/section.cpp b/src/mod/endpoints/mod_khomp/commons/configurator/section.cpp new file mode 100644 index 0000000000..5d26858054 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/section.cpp @@ -0,0 +1,130 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +void Section::options(Section::OptionVector & vec) +{ + for (OptionMap::iterator it = _options.begin(); it != _options.end();) + { + vec.push_back(&((*it).second)); + ++it; + } +} + +void Section::sections(Section::SectionVector & vec) +{ + for (SectionMap::iterator it = _sections.begin(); it != _sections.end();) + { + vec.push_back((*it).second); + ++it; + } +} + +/*********/ + +Option * Section::option_find(std::string & str, bool recurse) +{ + OptionMap::iterator i = _options.find(str); + + if (i == _options.end()) + { + if (!recurse) + throw not_found(); + + for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++) + { + try + { + return i->second->option_find(str, recurse); + } + catch (not_found & e) + { + /* keep looping! */ + }; + } + + throw not_found(); + } + + return &((*i).second); +} + +Option * Section::option_find(const char * str, bool recurse) +{ + std::string sstr(str); + return option_find(sstr, recurse); +} + +/*********/ + +Section * Section::section_find(std::string & str, bool recurse) +{ + SectionMap::iterator i = _sections.find(str); + + if (i == _sections.end()) + { + if (!recurse) + throw not_found(); + + for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++) + { + try + { + return i->second->section_find(str, recurse); + } + catch (not_found & e) + { + /* keep looping! */ + }; + } + + throw not_found(); + } + + return ((*i).second); +} + +Section * Section::section_find(const char * str, bool recurse) +{ + std::string sstr(str); + return section_find(sstr, recurse); +} diff --git a/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp b/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp new file mode 100644 index 0000000000..fdb782308a --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/configurator/section.hpp @@ -0,0 +1,226 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include +#include +#include + +#include + +#ifndef _CONFIG_SECTION_HPP_ +#define _CONFIG_SECTION_HPP_ + +struct Section +{ + typedef std::map < std::string, Option > OptionMap; + typedef std::vector< Option * > OptionVector; + + typedef std::map < std::string, Section * > SectionMap; + typedef std::vector < Section * > SectionVector; + + struct not_found {}; /* exception */ + +// protected: + Section(std::string name, std::string desc, bool recursive = true) + : _name(name), _description(desc), _recursive(recursive) {}; + + void add(Option o) + { + _options.insert(std::pair(o.name(), o)); + }; + + void del(std::string name) + { + _options.erase(name); + }; + + void add(Section *s) + { + _sections.insert(std::pair(s->name(), s)); + }; + + public: + const std::string & name() { return _name; }; + const std::string & description() { return _description; }; + const bool & recursive() { return _recursive; }; + + OptionMap::iterator option_begin() { return _options.begin(); }; + OptionMap::iterator option_end() { return _options.end(); }; + + SectionMap::iterator section_begin() { return _sections.begin(); }; + SectionMap::iterator section_end() { return _sections.end(); }; + + /**/ + + Option * option_find(const char *, bool recurse = false); + Section * section_find(const char *, bool recurse = false); + + Option * option_find(std::string &, bool recurse = false); + Section * section_find(std::string &, bool recurse = false); + + /**/ + + void options(OptionVector &); + void sections(SectionVector &); + + /**/ + + template + bool search_and_apply(std::string &key, std::string &value, F f) + { + OptionMap::iterator i = _options.find(key); + + if (i != _options.end()) + return f((*i).second); + + if (!_recursive) + return false; + + return (find_if(_sections.begin(), _sections.end(), f) != _sections.end()); + } + + private: + struct key_value + { + key_value(std::string &k, std::string &v): _k(k), _v(v) {}; + std::string & _k, & _v; + }; + + struct load_section: protected key_value + { + load_section(std::string &k, std::string &v): key_value(k,v) {}; + + bool operator()(Option &o) { return o.load(_v); }; + bool operator()(SectionMap::value_type &v) { return v.second->load(_k,_v); }; + }; + + struct change_section: protected key_value + { + change_section(std::string &k, std::string &v): key_value(k,v) {}; + + bool operator()(Option &o) { return o.change(_v); }; + bool operator()(SectionMap::value_type &v) { return v.second->change(_k,_v); }; + }; + + struct store_section: protected key_value + { + store_section(std::string &k, std::string &v): key_value(k,v) {}; + + bool operator()(Option &o) { return o.store(_v); }; + bool operator()(SectionMap::value_type &v) { return v.second->store(_k,_v); }; + }; + + struct set_section: protected key_value + { + set_section(std::string &k, std::string &v): key_value(k,v) {}; + + bool operator()(Option &o) { return (o.set(_v))[Option::F_ADJUSTED]; }; + bool operator()(SectionMap::value_type &v) { return v.second->set(_k,_v); }; + }; + + struct get_section: protected key_value + { + get_section(std::string &k, std::string &v): key_value(k,v) {}; + + bool operator()(Option &o) { return o.get(_v); }; + bool operator()(SectionMap::value_type &v) { return v.second->get(_k,_v); }; + }; + + struct modified_section + { + bool operator()(OptionMap::value_type &v) { return v.second.modified(); }; + bool operator()(SectionMap::value_type &v) { return v.second->modified(); }; + }; + + public: + bool load(const char * key, std::string value) + { + std::string skey(key); + return search_and_apply(skey, value, load_section(skey, value)); + } + + bool load(std::string &key, std::string &value) + { + return search_and_apply(key, value, load_section(key, value)); + } + + bool change(std::string &key, std::string &value) + { + return search_and_apply(key, value, change_section(key, value)); + } + + bool store(std::string &key, std::string &value) + { + return search_and_apply(key, value, store_section(key, value)); + } + + bool set(std::string &key, std::string &value) + { + return search_and_apply(key, value, set_section(key, value)); + } + + bool get(std::string &key, std::string &value) + { + return search_and_apply(key, value, get_section(key, value)); + } + + bool modified() + { + return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) || + (find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end())); + } + + private: + Section() {}; + + protected: + std::string _name; + std::string _description; + + OptionMap _options; + SectionMap _sections; + + bool _recursive; +}; + +#endif /* _CONFIG_SECTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/flagger.hpp b/src/mod/endpoints/mod_khomp/commons/flagger.hpp new file mode 100644 index 0000000000..49a4adda0f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/flagger.hpp @@ -0,0 +1,102 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include + +#ifndef _FLAGGER_HPP_ +#define _FLAGGER_HPP_ + +template < typename Flag > +struct Flagger +{ + protected: + struct Bool + { + Bool(): value(false) {}; + Bool(bool &v): value(v) {}; + + bool value; + }; + + typedef std::map< Flag, Bool > Map; + + public: + typedef Initializer< Flag > InitFlags; + + Flagger() {}; + + Flagger(InitFlags flags) + { + for (typename InitFlags::iterator i = flags.begin(); i != flags.end(); i++) + { + Flag & flag = (*i); + _map[flag].value = true; + }; + }; + + void set(Flag elt, bool value = true) + { + _map[elt].value = value; + } + + bool is_set(Flag elt) + { + return _map[elt].value; + } + + Flagger & operator&(Flag elt) + { + set(elt); + return *this; + }; + + bool operator[](Flag elt) + { + return is_set(elt); + }; + + protected: + Map _map; +}; + +#endif /* _FLAGGER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/format.cpp b/src/mod/endpoints/mod_khomp/commons/format.cpp new file mode 100644 index 0000000000..20f79204ec --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/format.cpp @@ -0,0 +1,331 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "format.hpp" +//#include + +Format::Format(const char * format_string, bool raise_exception) +: _format(format_string), _valid(true), _raise(raise_exception) +{ + initialize(format_string); +} + +/* +Format::Format(std::string & format_string, bool raise_exception) +: _format(NULL), _valid(true), _raise(raise_exception) +{ + initialize(format_string.c_str()); +} +*/ + +Format::Format(std::string format_string, bool raise_exception) +: _format(format_string), _valid(true), _raise(raise_exception) +{ + initialize(format_string.c_str()); +} + +void Format::initialize(const char * format_string) +{ + std::string txt; + + const char * ptr = format_string; + + while (*ptr != '\0') + { + if (*ptr != '%') + { + txt += *ptr; + ++ptr; + continue; + } + + const char * ptr2 = ptr+1; + + if (*ptr2 == '%') + { + txt += *ptr; + + ptr += 2; + continue; + } + + if (!txt.empty()) + push_argument(txt, T_LITERAL); + + std::string arg(1, *ptr); + + ++ptr; + + bool finished = false; + + short long_count = 0; + short short_count = 0; + + while(*ptr != '\0' && !finished) + { + switch (*ptr) + { + case ' ': + // uncomplete format with ' ', make it a literal. + arg += *ptr; + push_argument(arg, T_LITERAL); + finished = true; + break; + + case '%': + // uncomplete format with '%', make it a literal and start a new format. + push_argument(arg, T_LITERAL); + arg += *ptr; + break; + + case 'h': + short_count = std::min(short_count+1, 2); + long_count = 0; + arg += *ptr; + break; + + case 'l': + long_count = std::min(long_count+1, 2); + short_count = 0; + arg += *ptr; + break; + + case 'd': + case 'i': + arg += *ptr; + switch (long_count - short_count) + { + case 2: + push_argument(arg, T_SIGNED_LONG_LONG); + break; + case 1: + push_argument(arg, T_SIGNED_LONG); + break; + case 0: + push_argument(arg, T_SIGNED_INT); + break; + case -1: + push_argument(arg, T_SIGNED_SHORT); + break; + case -2: + push_argument(arg, T_SIGNED_SHORT_SHORT); + break; + default: + break; + } + finished = true; + break; + + case 'o': + case 'u': + case 'x': + case 'X': + arg += *ptr; + switch (long_count - short_count) + { + case 2: + push_argument(arg, T_UNSIGNED_LONG_LONG); + break; + case 1: + push_argument(arg, T_UNSIGNED_LONG); + break; + case 0: + push_argument(arg, T_UNSIGNED_INT); + break; + case -1: + push_argument(arg, T_UNSIGNED_SHORT); + break; + case -2: + push_argument(arg, T_UNSIGNED_SHORT_SHORT); + break; + default: + break; + } + finished = true; + break; + + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'a': + case 'A': + arg += *ptr; + push_argument(arg, T_FLOAT); + finished = true; + break; + + case 'c': + arg += *ptr; + push_argument(arg, T_CHAR); + finished = true; + break; + + case 's': + arg += *ptr; + push_argument(arg, T_STRING); + finished = true; + break; + + case 'p': + arg += *ptr; + push_argument(arg, T_POINTER); + finished = true; + break; + + case 'C': + case 'S': + case 'm': + case 'n': // unsupported for now. + arg += *ptr; + push_argument(arg, T_ANYTHING); + finished = true; + break; + + default: + arg += *ptr; + break; + } + + ++ptr; + } + + if (!arg.empty()) + push_argument(arg, T_LITERAL); + } + + if (!txt.empty()) + push_argument(txt, T_LITERAL); +} + +void Format::mark_invalid(std::string & msg) +{ + if (_valid) + { + _valid = false; + + std::string finalmsg; + + finalmsg += "** INVALID FORMAT: "; + finalmsg += msg; + finalmsg += " **"; + + _result = finalmsg; + } +} + +void Format::raise_check(void) +{ + if (!_valid && _raise) + throw InvalidFormat(_result); +} + +bool Format::validity_check(void) +{ + raise_check(); + + return _valid; +} + +const Format::Argument * Format::next_argument(void) +{ +// std::cerr << "size: " << _args.size() << std::endl; + + while (true) + { +// std::cerr << "loop size: " << _args.size() << std::endl; + + if (_args.empty()) + return NULL; // throw NoArgumentLeft(); + + const Argument & top = _args.front(); + + if (top.type() == T_LITERAL) + { +// std::cerr << "top type == LITERAL, looping..." << std::endl; + _result += top.fmts(); + pop_argument(); + } + else + { +// std::cerr << "top type: " << top.type() << std::endl; + return ⊤ + } + } +} + +void Format::pop_argument(void) +{ + _args.pop(); +} + +void Format::push_argument(std::string & data, Format::Type type) +{ +// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl; + + _args.push(Argument(data, type)); + data.clear(); +} + +std::string Format::str() +{ + if (!validity_check()) + return _result; + + if (next_argument() == NULL) + return _result; + + std::string msg; + + msg += "too few arguments passed for format '"; + msg += _format; + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + + return _result; +} + + diff --git a/src/mod/endpoints/mod_khomp/commons/format.hpp b/src/mod/endpoints/mod_khomp/commons/format.hpp new file mode 100644 index 0000000000..b1ebe74396 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/format.hpp @@ -0,0 +1,512 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _FORMAT_H_ +#define _FORMAT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 // WINDOWS +#include +#endif + + +/* macros used for shortening lines and making the code clearer */ +#define STG(x) (x).str() +#define FMT(x) Format(x) + +struct Format +{ + static const unsigned int strings_base_length = 64; + static const unsigned int generic_base_length = 64; + + struct InvalidFormat + { + InvalidFormat(std::string msg) : _msg(msg) {} + + std::string _msg; + }; + + explicit Format(const char * format_string, bool raise_exception = false); + explicit Format(std::string format_string, bool raise_exception = false); + + void initialize(const char *); + + std::string str(void); + + //////////////////////////////////////////////////////////// + + protected: + + enum Type + { + T_ANYTHING = 1, + + T_SIGNED_SHORT, + T_SIGNED_SHORT_SHORT, + T_SIGNED_INT, + T_SIGNED_LONG, + T_SIGNED_LONG_LONG, + + T_UNSIGNED_SHORT, + T_UNSIGNED_SHORT_SHORT, + T_UNSIGNED_INT, + T_UNSIGNED_LONG, + T_UNSIGNED_LONG_LONG, + + T_FLOAT, + T_CHAR, + + T_POINTER, + T_STRING, + + T_LITERAL + }; + + struct Argument + { + Argument(std::string fmts, Type type) + : _fmts(fmts), _type(type) {}; + + Type type(void) const { return _type; } + const std::string & fmts(void) const { return _fmts; } + + protected: + std::string _fmts; + Type _type; + }; + + typedef std::queue < Argument > ArgumentQueue; + + //////////////////////////////////////////////////////////// + + public: + + template < typename V > + Format & operator%( V value ) + { + if (!validity_check()) + return *this; + + const Argument * top = next_argument(); + + if (top == NULL) + { + std::string msg; + + msg += "too many arguments passed for format '"; + msg += _format; + msg += "'"; + + mark_invalid(msg); + } + else + { + char temp[generic_base_length]; + + if (!generic_verify(value, top->type())) + { + std::string msg; + + msg += "type mismatch: got type '"; + msg += typeid(value).name(); + msg += "' in format '"; + msg += top->fmts(); + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + return *this; + } + + snprintf(temp, sizeof(temp), top->fmts().c_str(), value); + _result += temp; + + pop_argument(); + } + + raise_check(); + return *this; + } + + template < typename V > + Format & operator%( V * value ) + { + if (!validity_check()) + return *this; + + const Argument * top = next_argument(); + + if (top == NULL) + { + std::string msg; + + msg += "too many arguments passed for format '"; + msg += _format; + msg += "'"; + + mark_invalid(msg); + } + else + { + switch (top->type()) + { + case T_POINTER: + { + char temp[generic_base_length]; + snprintf(temp, sizeof(temp), top->fmts().c_str(), value); + _result += temp; + break; + } + + case T_STRING: + { + if ((typeid(const char) == typeid(V)) || + (typeid(char) == typeid(V)) || + (typeid(const unsigned char) == typeid(V)) || + (typeid(unsigned char) == typeid(V)) || + (typeid(const void) == typeid(V)) || + (typeid(void) == typeid(V))) + { + int len = strlen((const char*)value)+strings_base_length+1; + + char * temp = new char[len]; + + snprintf(temp, len, top->fmts().c_str(), value); + _result += temp; + + delete[] temp; + } + else + { + std::string msg; + + msg += "type mismatch: got type '"; + msg += typeid(value).name(); + msg += "' in string format ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + } + break; + } + + default: + { + std::string msg; + + msg += "type mismatch: got pointer/string type in format '"; + msg += top->fmts(); + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + break; + } + } + + pop_argument(); + } + + raise_check(); + return *this; + } + +/* + Format & operator%( std::string value ) + { + return operator%(value); + } +*/ + + Format & operator%( const std::string value ) + { + if (!validity_check()) + return *this; + + const Argument * top = next_argument(); + + if (top == NULL) + { + std::string msg; + + msg += "too many arguments passed for format '"; + msg += _format; + msg += "'"; + + mark_invalid(msg); + } + else + { + if (top->type() == T_STRING) + { + int len = value.length()+strings_base_length+1; + + char * temp = new char[len]; + + snprintf(temp, len, top->fmts().c_str(), value.c_str()); + _result += temp; + + delete[] temp; + } + else + { + std::string msg; + + msg += "type mismatch: got string type in format '"; + msg += top->fmts(); + msg += "' ("; + msg += _format; + msg += ")"; + + mark_invalid(msg); + } + + pop_argument(); + } + + raise_check(); + return *this; + } + + protected: + + template < typename V > + bool number_verify_signed_short( V value ) + { + return + ((typeid(V) == typeid(short int) || + typeid(V) == typeid(short) || + typeid(V) == typeid(const short int) || + typeid(V) == typeid(const short) || + typeid(V) == typeid(volatile short int) || + typeid(V) == typeid(volatile short)) && + sizeof(V) == sizeof(short)); + } + + template < typename V > + bool number_verify_unsigned_short( V value ) + { + return + ((typeid(V) == typeid(unsigned short int) || + typeid(V) == typeid(unsigned short) || + typeid(V) == typeid(const unsigned short int) || + typeid(V) == typeid(const unsigned short) || + typeid(V) == typeid(volatile unsigned short int) || + typeid(V) == typeid(volatile unsigned short)) && + sizeof(V) == sizeof(unsigned short)); + } + + template < typename V > + bool number_verify_signed_long( V value ) + { + return + ((typeid(V) == typeid(long int) || + typeid(V) == typeid(long) || + typeid(V) == typeid(const long int) || + typeid(V) == typeid(const long) || + typeid(V) == typeid(volatile long int) || + typeid(V) == typeid(volatile long)) && + sizeof(V) == sizeof(long)); + } + + template < typename V > + bool number_verify_unsigned_long( V value ) + { + return + ((typeid(V) == typeid(unsigned long int) || + typeid(V) == typeid(unsigned long) || + typeid(V) == typeid(const unsigned long int) || + typeid(V) == typeid(const unsigned long) || + typeid(V) == typeid(volatile unsigned long int) || + typeid(V) == typeid(volatile unsigned long)) && + sizeof(V) == sizeof(long long)); + } + + template < typename V > + bool number_verify_signed_long_long( V value ) + { + return + ((typeid(V) == typeid(long long int) || + typeid(V) == typeid(long long) || + typeid(V) == typeid(const long long int) || + typeid(V) == typeid(const long long) || + typeid(V) == typeid(volatile long long) || + typeid(V) == typeid(volatile long long int)) && + sizeof(V) == sizeof(long long)); + } + + template < typename V > + bool number_verify_unsigned_long_long( V value ) + { + return + ((typeid(V) == typeid(unsigned long long int) || + typeid(V) == typeid(unsigned long long) || + typeid(V) == typeid(const unsigned long long int) || + typeid(V) == typeid(const unsigned long long) || + typeid(V) == typeid(volatile unsigned long long) || + typeid(V) == typeid(volatile unsigned long long int)) && + sizeof(V) == sizeof(unsigned long long)); + } + + template < typename V > + bool number_verify_signed_int( V value ) + { + return + (sizeof(V) <= sizeof(int) || + typeid(V) == typeid(int) || + typeid(V) == typeid(const int) || + typeid(V) == typeid(volatile int)); + } + + template < typename V > + bool number_verify_unsigned_int( V value ) + { + return + (sizeof(V) <= sizeof(unsigned int) || + typeid(V) == typeid(unsigned int) || + typeid(V) == typeid(const unsigned int) || + typeid(V) == typeid(volatile unsigned int)); + } + + template < typename V > + bool generic_verify( V value, Type type ) + { + switch (type) + { + /* EXCEPTION: consider any number an valid input. */ + case T_SIGNED_INT: + case T_UNSIGNED_INT: + return + (number_verify_signed_int(value) || + number_verify_unsigned_int(value) || + number_verify_signed_long(value) || + number_verify_unsigned_long(value) || + number_verify_signed_short(value) || + number_verify_unsigned_short(value)); + + case T_SIGNED_SHORT_SHORT: + return (typeid(V) == typeid(char) || typeid(V) == typeid(const char)); + + case T_SIGNED_SHORT: + return number_verify_signed_short(value); + + case T_SIGNED_LONG: + return number_verify_signed_long(value); + + case T_SIGNED_LONG_LONG: + return number_verify_signed_long_long(value); + + case T_UNSIGNED_SHORT_SHORT: + return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char)); + + case T_UNSIGNED_SHORT: + return number_verify_unsigned_short(value); + + case T_UNSIGNED_LONG: + return number_verify_unsigned_long(value); + + case T_UNSIGNED_LONG_LONG: + return number_verify_unsigned_long_long(value); + + case T_FLOAT: + return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) || + typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double)); + + case T_CHAR: + return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) || + typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char)); + + case T_POINTER: + case T_STRING: + return false; + + case T_ANYTHING: + return true; + + case T_LITERAL: + return false; + } + + return false; + }; + + void mark_invalid(std::string &); + + bool validity_check(void); + void raise_check(void); + +/* + struct NoArgumentLeft + { + NoArgumentLeft(): empty(0) {}; + + unsigned int empty; + }; +*/ + + const Argument * next_argument(void); + + void pop_argument(void); + void push_argument(std::string & data, Type type); + + private: + std::string _format; + + bool _valid; + bool _raise; + + std::string _result; + ArgumentQueue _args; +}; + +#endif /* _FORMAT_H_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp b/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp new file mode 100644 index 0000000000..29169f3d54 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.cpp @@ -0,0 +1,62 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "saved_condition.hpp" + +bool SavedCondition::wait(unsigned int msec) +{ + bool ret = true; + + switch_mutex_lock(_mutex); + + if (!_signaled) + { + /* msec * 1000 = The amount of time in microseconds to wait. */ + if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0) + ret = false; + } + + _signaled = false; + + switch_mutex_unlock(_mutex); + + return ret; +} diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp b/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp new file mode 100644 index 0000000000..8acf0f3e0b --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/freeswitch/saved_condition.hpp @@ -0,0 +1,136 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _SAVED_CONDITION_ +#define _SAVED_CONDITION_ + +#include + +extern "C" +{ + #include +} + +struct SavedCondition : public SavedConditionCommon// : public RefCounter < SavedCondition > +{ + typedef switch_thread_cond_t BaseConditionType; + typedef switch_mutex_t BaseMutexType; + + SavedCondition(switch_memory_pool_t *pool=NULL): + _pool(pool), + _can_delete_pool(false) + { + if(!_pool) + { + switch_core_new_memory_pool(&_pool); + _can_delete_pool = true; + } + + switch_thread_cond_create(&_condition, _pool); + switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool); + } + + //SavedCondition(const SavedCondition &); + ~SavedCondition() + { + switch_thread_cond_destroy(_condition); + switch_mutex_destroy(_mutex); + + if(_can_delete_pool) + switch_core_destroy_memory_pool(&_pool); + } + + void signal(void) + { + switch_mutex_lock(_mutex); + + _signaled = true; + switch_thread_cond_signal(_condition); + + switch_mutex_unlock(_mutex); + } + + void broadcast(void) + { + switch_mutex_lock(_mutex); + + _signaled = true; + switch_thread_cond_broadcast(_condition); + + switch_mutex_unlock(_mutex); + } + + void wait(void) + { + switch_mutex_lock(_mutex); + + if (!_signaled) + switch_thread_cond_wait(_condition, _mutex); + + _signaled = false; + + switch_mutex_unlock(_mutex); + } + + bool wait(unsigned int); + + void reset(void) + { + switch_mutex_lock(_mutex); + + _signaled = false; + + switch_mutex_unlock(_mutex); + } + + BaseMutexType * mutex() { return _mutex; }; + BaseConditionType * condition() { return _condition; }; + + protected: + + BaseConditionType *_condition; + BaseMutexType *_mutex; + switch_memory_pool_t *_pool; + bool _can_delete_pool; +}; + +#endif /* _SAVED_CONDITION_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp b/src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp new file mode 100644 index 0000000000..530d912ee1 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/freeswitch/simple_lock.hpp @@ -0,0 +1,177 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _SIMPLE_LOCK_HPP_ +#define _SIMPLE_LOCK_HPP_ + +#include + +extern "C" +{ + #include +} + +template < typename Implementor > +struct SimpleLockBasic: public SimpleLockCommon < Implementor > +{ + typedef SimpleLockCommon < Implementor > Super; + typedef typename Super::Result Result; + + typedef switch_mutex_t BaseMutexType; + + SimpleLockBasic(switch_memory_pool_t *pool = NULL) + : _pool(pool), _can_delete_pool( (_pool == NULL) ) + + { + if(!_pool) + switch_core_new_memory_pool(&_pool); + + //switch_mutex_init(&_mutex, SWITCH_MUTEX_DEFAULT, _pool); + switch_mutex_init(&_mutex, SWITCH_MUTEX_NESTED, _pool); + } + + virtual ~SimpleLockBasic() + { + /* do nothing */ + }; + + void unreference() + { + switch_mutex_destroy(_mutex); + + if (_can_delete_pool) + switch_core_destroy_memory_pool(&_pool); + } + + Result trylock() + { + switch (switch_mutex_trylock(_mutex)) + { + case SWITCH_STATUS_SUCCESS: + return Super::SUCCESS; + case SWITCH_STATUS_FALSE: + case SWITCH_STATUS_TERM: + case SWITCH_STATUS_NOTIMPL: + case SWITCH_STATUS_MEMERR: + case SWITCH_STATUS_GENERR: + case SWITCH_STATUS_SOCKERR: + case SWITCH_STATUS_NOTFOUND: + case SWITCH_STATUS_UNLOAD: + case SWITCH_STATUS_NOUNLOAD: + case SWITCH_STATUS_NOT_INITALIZED: + return Super::FAILURE; + //case SWITCH_STATUS_INUSE: + default: + return Super::ISINUSE; + } + } + + void unlock() + { + switch_mutex_unlock(_mutex); + } + + BaseMutexType * mutex() { return _mutex; }; + + protected: + BaseMutexType *_mutex; + switch_memory_pool_t *_pool; + bool _can_delete_pool; +}; + +struct SimpleLock: public SimpleLockBasic < SimpleLock > +{ + typedef SimpleLockBasic < SimpleLock > Super; + typedef Super::Result Result; + + SimpleLock(switch_memory_pool_t *pool = NULL) + : Super(pool) {}; + + Result lock() + { + switch (switch_mutex_lock(_mutex)) + { + case SWITCH_STATUS_SUCCESS: + return Super::SUCCESS; + case SWITCH_STATUS_FALSE: + case SWITCH_STATUS_TERM: + case SWITCH_STATUS_NOTIMPL: + case SWITCH_STATUS_MEMERR: + case SWITCH_STATUS_GENERR: + case SWITCH_STATUS_SOCKERR: + case SWITCH_STATUS_NOTFOUND: + case SWITCH_STATUS_UNLOAD: + case SWITCH_STATUS_NOUNLOAD: + case SWITCH_STATUS_NOT_INITALIZED: + return Super::FAILURE; + //case SWITCH_STATUS_INUSE: + default: + return Super::ISINUSE; + } + } +}; + +template < unsigned int Retries = 10, unsigned int Interval = 50 > +struct SimpleNonBlockLock: public SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > > +{ + typedef SimpleLockBasic < SimpleNonBlockLock < Retries, Interval > > Super; + typedef typename Super::Result Result; + + SimpleNonBlockLock(switch_memory_pool_t *pool = NULL) + : Super(pool) {}; + + inline Result lock() + { + for (unsigned int i = 0; i < Retries; i++) + { + Result ret = Super::trylock(); + + if (ret != Super::ISINUSE) + return ret; + + usleep(Interval * 1000); + } + + return Super::ISINUSE; + } +}; + +#endif /* _SIMPLE_LOCK_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp b/src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp new file mode 100644 index 0000000000..af50240307 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/freeswitch/thread.hpp @@ -0,0 +1,327 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _THREAD_HPP_ +#define _THREAD_HPP_ + +#include + +extern "C" +{ + #include +} + +struct Thread : ThreadCommon +{ + typedef switch_thread_t BaseThreadType; + + template + struct ThreadData : ThreadDataCommon + { + ThreadData(T data, A arg) : _data(data), _arg(arg) {} + + int run() + { + return _data(_arg); + } + + T _data; + A _arg; + }; + + template + struct ThreadData < T, R, void > : ThreadDataCommon + { + ThreadData(T data) : _data(data) {} + + int run() + { + return _data(); + } + + T _data; + }; + + template + struct ThreadData < T, void, A > : ThreadDataCommon + { + ThreadData(T data, A arg) : _data(data), _arg(arg) {} + + int run() + { + _data(_arg); + return 0; + } + + T _data; + A _arg; + }; + + + template + struct ThreadData < T, void, void > : ThreadDataCommon + { + ThreadData(T data) : _data(data) {} + + int run() + { + _data(); + return 0; + } + + T _data; + }; + + template + Thread(T obj, switch_memory_pool_t *pool=NULL) : + _thread_info(new ThreadData::Return, void>(obj)), + _pool(pool), + _can_delete_pool(false) + { + if(!_pool) + { + switch_core_new_memory_pool(&_pool); + _can_delete_pool = true; + } + + _thread_info->_thread = this; + _thread_info->_self = NULL; + _thread_info->_attribute = NULL; + + if(switch_threadattr_create( + (switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0) + { + _thread_info->_attribute = NULL; + return; + } + + switch_threadattr_stacksize_set( + (switch_threadattr_t *)_thread_info->_attribute, + SWITCH_THREAD_STACKSIZE); + + if(!priority()) + { + _thread_info->_attribute = NULL; + } + + } + + template + Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) : + _thread_info(new ThreadData::Return, A>(obj, arg)), + _pool(pool), + _can_delete_pool(false) + { + if(!_pool) + { + switch_core_new_memory_pool(&_pool); + _can_delete_pool = true; + } + + _thread_info->_thread = this; + _thread_info->_self = NULL; + _thread_info->_attribute = NULL; + + if(switch_threadattr_create( + (switch_threadattr_t **)&_thread_info->_attribute, _pool) != 0) + { + _thread_info->_attribute = NULL; + return; + } + + switch_threadattr_stacksize_set( + (switch_threadattr_t *)_thread_info->_attribute, + SWITCH_THREAD_STACKSIZE); + + if(!priority()) + { + _thread_info->_attribute = NULL; + } + + } + + ~Thread() + { + if(_thread_info) + delete _thread_info; + + if (_can_delete_pool) + switch_core_destroy_memory_pool(&_pool); + } + + void detach(bool d = true) + { + if(!_thread_info->_attribute) + return; + + /* Non-zero if detached threads should be created. */ + switch_threadattr_detach_set( + (switch_threadattr_t *)_thread_info->_attribute, d ? 1 : 0); + } + + bool start() + { + if(!_pool || !_thread_info->_attribute) + return false; + + switch_thread_create((switch_thread_t**)&_thread_info->_self, + (switch_threadattr_t *)_thread_info->_attribute, + run, + _thread_info, + _pool); + + if(!_thread_info->_self) + return false; + + return true; + } + + int join() + { + /* + * block until the desired thread stops executing. + * @param retval The return value from the dead thread. + * @param thd The thread to join + * + * SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd); + */ + + if(!_thread_info->_self) + return -2; + + int retval = 0; + + if(switch_thread_join((switch_status_t*)&retval, + (switch_thread_t *)_thread_info->_self) != 0) + return -1; + + return retval; + } + + BaseThreadType * self() + { + //switch_thread_self(); + //apr_os_thread_current(); + return (BaseThreadType *)_thread_info->_self; + } + +private: + void exit(int status) + { + /** + * stop the current thread + * @param thd The thread to stop + * @param retval The return value to pass back to any thread that cares + */ + //SWITCH_DECLARE(switch_status_t) switch_thread_exit(switch_thread_t *thd, switch_status_t retval); + switch_thread_exit((switch_thread_t *)_thread_info->_self, (switch_status_t)status); + + } + +#ifndef WIN32 + struct apr_threadattr_t { + apr_pool_t *pool; + pthread_attr_t attr; + }; +#endif + + bool priority() + { +#ifndef WIN32 + struct sched_param param; + + struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute; + + if (pthread_attr_setschedpolicy( + (pthread_attr_t *)&myattr->attr, SCHED_RR) < 0) + return false; + + if (pthread_attr_getschedparam( + (pthread_attr_t *)&myattr->attr, ¶m) < 0) + return false; + + param.sched_priority = sched_get_priority_max(SCHED_RR); + + if (pthread_attr_setschedparam( + (pthread_attr_t *)&myattr->attr, ¶m) < 0) + return false; + +#endif + return true; + +/* + //BUG in Freeswitch + if(switch_threadattr_priority_increase( + (switch_threadattr_t *)_thread_info->_attribute) != 0) + return false; + + return true; +*/ + } + + +protected: + ThreadDataCommon * _thread_info; + switch_memory_pool_t *_pool; + bool _can_delete_pool; + +protected: + + static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj) + { + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + // "Starting new Thread\n"); + + ThreadDataCommon * data = (ThreadDataCommon *)obj; + int retval = data->run(); + + //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + // "Stopping new Thread = %d\n", retval); + + ((Thread *)(data->_thread))->exit(retval); + + return NULL; + } + +}; + + +#endif /* _THREAD_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/function.hpp b/src/mod/endpoints/mod_khomp/commons/function.hpp new file mode 100644 index 0000000000..c448299acd --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/function.hpp @@ -0,0 +1,337 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the "LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#ifndef _FUNCTION_HPP_ +#define _FUNCTION_HPP_ + +namespace Function +{ + struct EmptyFunction {}; + + /**/ + + template < typename FunctionTraits > + struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >) + { + typedef typename FunctionTraits::BaseType BaseType; + + typedef typename FunctionTraits::FunType FunType; + typedef typename FunctionTraits::ObjType ObjType; + + template < typename Functor > + StorageBase(Functor f) + : _object(reinterpret_cast(new Functor(f))), + _function(reinterpret_cast(&(Functor::operator()))), + _malloced(true) + {}; + + template < typename Functor > + StorageBase(Functor & f, bool malloced) + : _object(reinterpret_cast((malloced ? new Functor(f) : &f))), + _function(reinterpret_cast(&(Functor::operator()))), + _malloced(malloced) + {}; + + StorageBase() + : _object(reinterpret_cast(0)), + _function(reinterpret_cast(0)), + _malloced(false) + {}; + + StorageBase(const StorageBase & o) + : INC_REFCOUNTER(o, StorageBase < FunctionTraits >), + _object(o._object), _function(o._function), _malloced(o._malloced) + {}; + + virtual ~StorageBase() {}; + + void unreference() + { + // TODO: will this work if we delete a different type? // + if (_malloced) + delete _object; + }; + + template < typename Functor > + void operator=(Functor f) + { + _object = reinterpret_cast(new Functor(f)), + _function = reinterpret_cast(&(Functor::operator())); + _malloced = false; + } + + protected: + ObjType _object; + FunType _function; + bool _malloced; + }; + + /**/ + + template < typename R > + struct VTable0 + { + R operator()(void) { return R(); }; + }; + + template < > + struct VTable0< void > + { + void operator()(void) { return; }; + }; + + template < typename R > + struct Function0Traits + { + typedef VTable0 BaseType; + + typedef R (BaseType::* FunType)(void); + typedef BaseType * ObjType; + }; + + /**/ + + template < typename R, typename A0 > + struct VTable1 + { + R operator()(A0 a0) { return R(); }; + }; + + template < typename A0 > + struct VTable1< void, A0 > + { + void operator()(A0 a0) { return; }; + }; + + template < typename R, typename A0 > + struct Function1Traits + { + typedef VTable1 BaseType; + + typedef R (BaseType::* FunType)(A0); + typedef BaseType * ObjType; + }; + + /**/ + + template < typename R, typename A0, typename A1 > + struct VTable2 + { + R operator()(A0 a0, A1) { return R(); }; + }; + + template < typename A0, typename A1 > + struct VTable2< void, A0, A1 > + { + void operator()(A0 a0, A1 a1) { return; }; + }; + + template < typename R, typename A0, typename A1 > + struct Function2Traits + { + typedef VTable2 BaseType; + + typedef R (BaseType::* FunType)(A0, A1); + typedef BaseType * ObjType; + }; + + /**/ + + template < typename R, typename A0, typename A1, typename A2 > + struct VTable3 + { + R operator()(A0 a0, A1 a1, A2 a2) { return R(); }; + }; + + template < typename A0, typename A1, typename A2 > + struct VTable3< void, A0, A1, A2 > + { + void operator()(A0 a0, A1 a1, A2 a2) { return; }; + }; + + template < typename R, typename A0, typename A1, typename A2 > + struct Function3Traits + { + typedef VTable3 BaseType; + + typedef R (BaseType::* FunType)(A0, A1, A2); + typedef BaseType * ObjType; + }; + + /**/ + + template < typename R, typename A0, typename A1, typename A2, typename A3 > + struct VTable4 + { + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return R(); }; + }; + + template < typename A0, typename A1, typename A2, typename A3 > + struct VTable4< void, A0, A1, A2, A3 > + { + void operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return; }; + }; + + template < typename R, typename A0, typename A1, typename A2, typename A3 > + struct Function4Traits + { + typedef VTable4 BaseType; + + typedef R (BaseType::* FunType)(A0, A1, A2, A3); + typedef BaseType * ObjType; + }; + + /**/ + + template < typename R, typename A0 > + struct Function0 : public StorageBase < Function0Traits < R > > + { + typedef StorageBase < Function0Traits < R > > Storage; + + template < typename Functor > + Function0(Functor f): Storage(f) {}; + + template < typename Functor > + Function0(Functor & f, bool m): Storage(f, m) {}; + + Function0() {}; + + R operator()(void) + { + if (reinterpret_cast(Storage::_object) == 0) + throw EmptyFunction(); + + return ((Storage::_object)->*(Storage::_function))(); + } + }; + + template < typename R, typename A0 > + struct Function1 : public StorageBase < Function1Traits < R, A0 > > + { + typedef StorageBase < Function1Traits < R, A0 > > Storage; + + template < typename Functor > + Function1(Functor f): Storage(f) {}; + + template < typename Functor > + Function1(Functor & f, bool m): Storage(f, m) {}; + + Function1() {}; + + R operator()(A0 a0) + { + if (reinterpret_cast(Storage::_object) == 0) + throw EmptyFunction(); + + return ((Storage::_object)->*(Storage::_function))(a0); + } + }; + + template < typename R, typename A0, typename A1 > + struct Function2 : public StorageBase < Function2Traits < R, A0, A1 > > + { + typedef StorageBase < Function2Traits < R, A0, A1 > > Storage; + + template < typename Functor > + Function2(Functor f): Storage(f) {}; + + template < typename Functor > + Function2(Functor & f, bool m): Storage(f, m) {}; + + Function2() {}; + + R operator()(A0 a0, A1 a1) + { + if (reinterpret_cast(Storage::_object) == 0) + throw EmptyFunction(); + + return ((Storage::_object)->*(Storage::_function))(a0, a1); + } + }; + + template < typename R, typename A0, typename A1, typename A2 > + struct Function3 : public StorageBase < Function3Traits < R, A0, A1, A2 > > + { + typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage; + + template < typename Functor > + Function3(Functor f): Storage(f) {}; + + template < typename Functor > + Function3(Functor & f, bool m): Storage(f, m) {}; + + Function3() {}; + + R operator()(A0 a0, A1 a1, A2 a2) + { + if (reinterpret_cast(Storage::_object) == 0) + throw EmptyFunction(); + + return ((Storage::_object)->*(Storage::_function))(a0, a1, a2); + } + }; + + template < typename R, typename A0, typename A1, typename A2, typename A3 > + struct Function4 : public StorageBase < Function4Traits < R, A0, A1, A2, A3 > > + { + typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage; + + template < typename Functor > + Function4(Functor f): Storage(f) {}; + + template < typename Functor > + Function4(Functor & f, bool m): Storage(f, m) {}; + + Function4() {}; + + R operator()(A0 a0, A1 a1, A2 a2, A3 a3) + { + if (reinterpret_cast(Storage::_object) == 0) + throw EmptyFunction(); + + return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3); + } + }; +}; + +#endif /* _FUNCTION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/initializer.hpp b/src/mod/endpoints/mod_khomp/commons/initializer.hpp new file mode 100644 index 0000000000..e0e110d49c --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/initializer.hpp @@ -0,0 +1,80 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#ifndef _INITIALIZER_HPP_ +#define _INITIALIZER_HPP_ + +template < typename Type > +struct Initializer: public std::vector< Type > +{ + typedef std::vector< Type > super; + + Initializer(Type e) { push_back(e); }; + Initializer(Type & e) { push_back(e); }; + + Initializer & operator&(Initializer v) + { + insert(super::end(), v.begin(), v.end()); + return *this; + }; + + Initializer & operator&(Initializer & v) + { + insert(super::end(), v.begin(), v.end()); + return *this; + }; + + Initializer & operator&(Type v) + { + insert(super::end(), v); + return *this; + }; + + Initializer & operator&(Type & v) + { + insert(super::end(), v); + return *this; + }; +}; + +#endif /* _INITIALIZER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/k3lapi.cpp b/src/mod/endpoints/mod_khomp/commons/k3lapi.cpp new file mode 100644 index 0000000000..f5afa1348f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/k3lapi.cpp @@ -0,0 +1,313 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include +#include + +K3LAPI::K3LAPI(bool has_exceptions) +: _has_exceptions(has_exceptions), + _device_count(0), _channel_count(0), _link_count(0), + _device_config(0), _channel_config(0), _link_config(0) +{}; + +/* initialize the whole thing! */ + +void K3LAPI::start(void) +{ + /* tie the used k3l to the compiled k3l version */ + char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion); + + if (ret && *ret) + throw start_failed(ret); + + /* call init automagically */ + init(); +} + +void K3LAPI::stop(void) +{ + k3lStop(); + fini(); +} + +/* envio de comandos para placa */ + +void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +{ + KMixerCommand mix; + + mix.Track = track; + mix.Source = src; + mix.SourceIndex = index; + + command(dev, obj, CM_MIXER, (const char *) &mix); +} + +void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +{ + /* estes buffers *NAO PODEM SER ESTATICOS*! */ + char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff }; + + switch (src) + { + case kmsChannel: + cmd[4] = 0x05; + cmd[5] = (char)index; + break; + + case kmsNoDelayChannel: + cmd[4] = 0x0a; + cmd[5] = (char)index; + break; + + case kmsGenerator: + cmd[4] = 0x09; + + switch ((KMixerTone)index) + { + case kmtSilence: + cmd[5] = 0x0F; + break; + case kmtDial: + cmd[5] = 0x08; + break; + case kmtBusy: + cmd[5] = 0x0D; + break; + + case kmtFax: + case kmtVoice: + case kmtEndOf425: + case kmtCollect: + case kmtEndOfDtmf: + /* TODO: exception, unable to generate */ + break; + } + break; + + case kmsCTbus: + case kmsPlay: + /* TODO: exception, not implemented! */ + break; + } + + int32 dsp = get_dsp(dev, DSP_AUDIO); + + raw_command(dev, dsp, cmd, sizeof(cmd)); +} + +void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) +{ + KMixerCommand mix; + + mix.Track = track; + mix.Source = src; + mix.SourceIndex = index; + + command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix); +} + +void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str) +{ + command(dev, obj, code, str.c_str()); +} + +void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms) +{ + K3L_COMMAND cmd; + + cmd.Cmd = code; + cmd.Object = obj; + cmd.Params = (byte *)parms; + + int32 rc = k3lSendCommand(dev, &cmd); + + if (rc != ksSuccess) + throw failed_command(code, dev, obj, rc); +} + +void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str) +{ + raw_command(dev, dsp, str.data(), str.size()); +} + +void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) +{ + std::string str(cmds, size); + + int32 rc = k3lSendRawCommand(dev, dsp, (void *)cmds, size); + + if (rc != ksSuccess) + throw failed_raw_command(dev, dsp, rc); +} + +KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res) +{ + char tmp_param[256]; + memset((void*)tmp_param, 0, sizeof(tmp_param)); + + int32 rc = k3lGetEventParam (ev, (sbyte *)name, (sbyte *)tmp_param, sizeof(tmp_param)-1); + + if (rc != ksSuccess) + return (KLibraryStatus)rc; + + res.append(tmp_param, strlen(tmp_param)); + return ksSuccess; +} + +std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name) +{ + std::string res; + + KLibraryStatus rc = get_param(ev, name, res); + + if (rc != ksSuccess) + throw get_param_failed(name, rc); + + return res; +} + +void K3LAPI::init(void) +{ + if (_device_count != 0) return; + + _device_count = k3lGetDeviceCount(); + + _device_type = new KDeviceType[_device_count]; + _device_config = new device_conf_type[_device_count]; + _channel_config = new channel_ptr_conf_type[_device_count]; + _link_config = new link_ptr_conf_type[_device_count]; + _channel_count = new unsigned int[_device_count]; + _link_count = new unsigned int[_device_count]; + + for (unsigned int dev = 0; dev < _device_count; dev++) + { + KLibraryStatus ret = ksSuccess; + + _device_type[dev] = (KDeviceType) k3lGetDeviceType(dev); + + /* caches each device config */ + ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev])); + + if (ret != ksSuccess) + throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d): %s") % dev % Verbose::status(ret))); + + /* adjust channel/link count for device */ + _channel_count[dev] = _device_config[dev].ChannelCount; + _link_count[dev] = _device_config[dev].LinkCount; + + /* caches each channel config */ + _channel_config[dev] = new channel_conf_type[_channel_count[dev]]; + + for (unsigned int obj = 0; obj < _channel_count[dev]; obj++) + { + ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), sizeof(_channel_config[dev][obj])); + + if (ret != ksSuccess) + throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,chan=%d): %s") % dev % obj % Verbose::status(ret))); + } + + /* adjust link count for device */ + _link_count[dev] = _device_config[dev].LinkCount; + + /* caches each link config */ + _link_config[dev] = new link_conf_type[_link_count[dev]]; + + for (unsigned int obj = 0; obj < _link_count[dev]; obj++) + { + ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), sizeof(_link_config[dev][obj])); + + if (ret != ksSuccess) + throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,link=%d): %s") % dev % obj % Verbose::status(ret))); + } + } +} + +void K3LAPI::fini(void) +{ + for (unsigned int dev = 0; dev < _device_count; dev++) + { + if (_channel_config[dev]) + { + delete[] _channel_config[dev]; + _channel_config[dev] = NULL; + } + + if (_link_config[dev]) + { + delete[] _link_config[dev]; + _link_config[dev] = NULL; + } + } + + _device_count = 0; + + if (_device_type) { delete[] _device_type; _device_type = NULL; } + if (_device_config) { delete[] _device_config; _device_config = NULL; } + if (_channel_config) { delete[] _channel_config; _channel_config = NULL; } + if (_link_config) { delete[] _link_config; _link_config = NULL; } + if (_channel_count) { delete[] _channel_count; _channel_count = NULL; } + if (_link_count) { delete[] _link_count; _link_count = NULL; } +} + +int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type) +{ + switch (device_type(dev)) + { + case kdtFXO: + case kdtFXOVoIP: +#if K3L_AT_LEAST(1,6,0) + case kdtGSM: + case kdtGSMSpx: +#endif +#if K3L_AT_LEAST(2,1,0) + case kdtGSMUSB: + case kdtGSMUSBSpx: +#endif + return 0; + + default: + return (type == DSP_AUDIO ? 1 : 0); + } +} + diff --git a/src/mod/endpoints/mod_khomp/commons/k3lapi.hpp b/src/mod/endpoints/mod_khomp/commons/k3lapi.hpp new file mode 100644 index 0000000000..596548405b --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/k3lapi.hpp @@ -0,0 +1,408 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include + +/* if using full k3l.h (for softpbx), version already defined. */ +#ifndef k3lApiMajorVersion +# include +#endif + +#ifdef __GNUC_PREREQ +#if __GNUC_PREREQ(4,3) +#include +#endif +#endif + +#include + +#ifndef _K3LAPI_HPP_ +#define _K3LAPI_HPP_ + +struct K3LAPI +{ + /* exceptions */ + + struct start_failed + { + start_failed(const char * _msg) : msg(_msg) {}; + start_failed(std::string _msg) : msg(_msg) {}; + std::string msg; + }; + + struct failed_command + { + failed_command(int32 _code, unsigned short _dev, unsigned short _obj, int32 _rc) + : code(_code), dev(_dev), obj(_obj), rc(_rc) {}; + + int32 code; + unsigned short dev; + unsigned short obj; + int32 rc; + }; + + struct failed_raw_command + { + failed_raw_command(unsigned short _dev, unsigned short _dsp, int32 _rc) + : dev(_dev), dsp(_dsp), rc(_rc) {}; + + unsigned short dev; + unsigned short dsp; + int32 rc; + }; + + struct invalid_device + { + invalid_device(int32 _device) + : device(_device) {}; + + int32 device; + }; + + struct invalid_channel + { + invalid_channel(int32 _device, int32 _channel) + : device(_device), channel(_channel) {}; + + int32 device, channel; + }; + + struct invalid_link + { + invalid_link(unsigned int _device, unsigned int _link) + : device(_device), link(_link) {}; + + int32 device, link; + }; + + struct get_param_failed + { + get_param_failed(std::string _name, int32 _rc) + : name(_name), rc((KLibraryStatus)_rc) {}; + + std::string name; + KLibraryStatus rc; + }; + + typedef K3L_DEVICE_CONFIG device_conf_type; + typedef K3L_CHANNEL_CONFIG channel_conf_type; + typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type; + typedef K3L_LINK_CONFIG link_conf_type; + typedef K3L_LINK_CONFIG * link_ptr_conf_type; + + /* constructors/destructors */ + + K3LAPI(bool has_exceptions = false); + virtual ~K3LAPI() {}; + + /* (init|final)ialize the whole thing! */ + + void start(void); + void stop(void); + + /* verificacao de intervalos */ + + inline bool valid_device(int32 dev) + { + return (dev >= 0 && dev < ((int32)_device_count)); + } + + inline bool valid_channel(int32 dev, int32 obj) + { + return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev])); + } + + inline bool valid_link(int32 dev, int32 obj) + { + return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev])); + } + + /*! + \brief High level object identifier + Since Khomp works with an object concept, this is used to map the + object id with its proper type. + */ + struct target + { + /*! The types a target can have */ + typedef enum { DEVICE, CHANNEL, MIXER, LINK } target_type; + + target(K3LAPI & k3lapi, target_type type_init, int32 device_value, int32 object_value) + : type(type_init), + device((unsigned short)device_value), + object((unsigned short)object_value) + { + switch (type_init) + { + case DEVICE: + if (!k3lapi.valid_device(device_value)) + throw invalid_device(device_value); + break; + + case CHANNEL: + case MIXER: + if (!k3lapi.valid_channel(device_value, object_value)) + throw invalid_channel(device_value, object_value); + break; + + case LINK: + if (!k3lapi.valid_link(device_value, object_value)) + throw invalid_link(device_value, object_value); + break; + } + + }; + + const target_type type; + + const unsigned short device; + const unsigned short object; + }; + + /* envio de comandos para placa (geral) */ + + void raw_command(int32 dev, int32 dsp, std::string & str); + void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size); + + /* obter dados 'cacheados' (geral) */ + + inline unsigned int device_count(void) + { + return _device_count; + } + + /* envio de comandos para placa (sem identificadores) */ + + void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index); + + void command (int32 dev, int32 obj, int32 code, std::string & str); + void command (int32 dev, int32 obj, int32 code, const char * parms = NULL); + + /* obter dados 'cacheados' (sem identificadores) */ + + inline unsigned int channel_count(int32 dev) + { + if (!valid_device(dev)) + { + if (_has_exceptions) + throw invalid_device(dev); + else + return 0; + } + + return _channel_count[dev]; + } + + inline unsigned int link_count(int32 dev) + { + if (!valid_device(dev)) + { + if (_has_exceptions) + throw invalid_device(dev); + else + return 0; + } + + return _link_count[dev]; + } + + inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) + { + if (!valid_channel(dev, obj)) + { + if (_has_exceptions) + throw invalid_channel(dev, obj); + else + return 0; + } + + uint32 res_value = (uint32)-1; + stt_code stt_res = ksFail; + +#if K3L_AT_LEAST(2,1,0) + stt_res = k3lGetChannelStats(dev, obj, index, &res_value); +#endif + + if(stt_res != ksSuccess) + { + return (uint32)-1; + } + + return res_value; + } + + KDeviceType device_type(int32 dev) + { + if (!valid_device(dev)) + { + if (_has_exceptions) + throw invalid_device(dev); + else + return kdtDevTypeCount; + } + + return _device_type[dev]; + } + + + K3L_DEVICE_CONFIG & device_config(int32 dev) + { + if (!valid_device(dev)) + throw invalid_device(dev); + + return _device_config[dev]; + } + + K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) + { + if (!valid_channel(dev, obj)) + throw invalid_channel(dev, obj); + + return _channel_config[dev][obj]; + } + + K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) + { + if (!valid_link(dev, obj)) + throw invalid_channel(dev, obj); + + return _link_config[dev][obj]; + } + + /* envio de comandos para placa (com identificadores) */ + + void mixer(target & tgt, byte track, KMixerSource src, int32 index) + { + mixer((int32)tgt.device, (int32)tgt.object, track, src, index); + } + + void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index) + { + mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index); + } + + void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index) + { + mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index); + } + + void command (target & tgt, int32 code, std::string & str) + { + command((int32)tgt.device, (int32)tgt.object, code, str); + }; + + void command (target & tgt, int32 code, const char * parms = NULL) + { + command((int32)tgt.device, (int32)tgt.object, code, parms); + }; + + /* obter dados 'cacheados' (com indentificadores) */ + + inline unsigned int channel_count(target & tgt) + { + return _channel_count[tgt.device]; + } + + inline unsigned int link_count(target & tgt) + { + return _link_count[tgt.device]; + } + + KDeviceType device_type(target & tgt) + { + return _device_type[tgt.device]; + } + + + K3L_DEVICE_CONFIG & device_config(target & tgt) + { + return _device_config[tgt.device]; + } + + K3L_CHANNEL_CONFIG & channel_config(target & tgt) + { + return _channel_config[tgt.device][tgt.object]; + } + + K3L_LINK_CONFIG & link_config(target & tgt) + { + return _link_config[tgt.device][tgt.object]; + } + + /* pega valores em strings de eventos */ + + KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res); + std::string get_param(K3L_EVENT *ev, const char *name); + + /* inicializa valores em cache */ + + void init(void); + void fini(void); + + /* utilidades diversas e informacoes */ + + enum DspType + { + DSP_AUDIO, + DSP_SIGNALING, + }; + + int32 get_dsp(int32, DspType); + + protected: + + const bool _has_exceptions; + + unsigned int _device_count; + unsigned int * _channel_count; + unsigned int * _link_count; + + device_conf_type * _device_config; + channel_ptr_conf_type * _channel_config; + link_ptr_conf_type * _link_config; + KDeviceType * _device_type; +}; + +#endif /* _K3LAPI_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/k3lutil.cpp b/src/mod/endpoints/mod_khomp/commons/k3lutil.cpp new file mode 100644 index 0000000000..83ac82efae --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/k3lutil.cpp @@ -0,0 +1,234 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +std::string K3LUtil::channelStatus(int32 dev, int32 channel, + Verbose::Presentation fmt) +{ + try + { + K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel); + K3L_CHANNEL_STATUS status; + + KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev, + channel + ksoChannel, &status, sizeof(status)); + + switch (ret) + { + case ksSuccess: return Verbose::channelStatus(config.Signaling, + status.AddInfo, fmt); + default: return (fmt == Verbose::EXACT ? "" + : "Unknown (fail)"); + } + } + catch(K3LAPI::invalid_channel & e) + { + return (fmt == Verbose::EXACT ? "" : "Unknown (fail)"); + } +} + +std::string K3LUtil::callStatus(int32 dev, int32 channel, + Verbose::Presentation fmt) +{ + K3L_CHANNEL_STATUS status; + + KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus(dev, + channel + ksoChannel, &status, sizeof(status)); + + switch (ret) + { + case ksSuccess: return Verbose::callStatus(status.CallStatus, fmt); + default: return (fmt == Verbose::EXACT ? "" + : "Unknown (fail)"); + } +} + +std::string K3LUtil::linkStatus(int32 dev, int32 link, + Verbose::Presentation fmt, KSignaling sig) +{ + try + { + if (sig == ksigInactive) + { + K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link); + sig = config.Signaling; + } + + K3L_LINK_STATUS status; + + KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev, + link + ksoLink, &status, sizeof(status)); + + switch (ret) + { + case ksSuccess: return Verbose::linkStatus(sig, status.E1, fmt); + default: return (fmt == Verbose::EXACT ? + "" : "Unknown (failure)"); + } + } + catch(K3LAPI::invalid_channel & e) + { + return (fmt == Verbose::EXACT ? "" + : "Unknown (failure)"); + } +} + +std::string K3LUtil::getLinkStatus(int32 dev, int32 link, + Verbose::Presentation fmt) +{ + switch (_k3lapi.device_type(dev)) + { +#if K3L_AT_LEAST(1,6,0) + case kdtFXS: + case kdtFXSSpx: + return linkStatus(dev, link, fmt, ksigAnalogTerminal); + +#if K3L_AT_LEAST(2,1,0) + case kdtE1FXSSpx: + if (link == 1) + return linkStatus(dev, link, fmt, ksigAnalogTerminal); +#endif +#endif + default: + break; + } + + K3L_LINK_CONFIG & conf = _k3lapi.link_config(dev, link); + + std::string res = linkStatus(dev, link, fmt); + + if (conf.ReceivingClock & 0x01) + res += (fmt == Verbose::EXACT ? ",sync" : " (sync)"); + + return res; +} + +unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual) +{ + unsigned int number = 0; + + try + { + switch (_k3lapi.device_type(dev)) + { +#if K3L_AT_LEAST(1,6,0) + case kdtFXS: + number = (count_virtual ? (_k3lapi.channel_count(dev) < 50 ? 1 : 2) : 0); + break; + + case kdtFXSSpx: + number = (count_virtual ? (_k3lapi.channel_count(dev) < 30 ? 1 : 2) : 0); + break; +#endif + +#if K3L_AT_LEAST(2,1,0) + case kdtE1FXSSpx: + number = (count_virtual ? 2 : 1); + break; +#endif + + /* E1 boards */ + case kdtE1: + case kdtE1Spx: + case kdtE1IP: + number = _k3lapi.link_count(dev); + break; + + case kdtPR: + case kdtE1GW: + number = 1; + break; + +#if K3L_AT_LEAST(1,6,0) + case kdtFXO: + case kdtFXOVoIP: + case kdtGSM: + case kdtGSMSpx: +#else + case kdtFX: + case kdtFXVoIP: +#endif + case kdtConf: + case kdtGWIP: +#if K3L_AT_LEAST(2,1,0) + case kdtGSMUSB: + case kdtGSMUSBSpx: + case kdtReserved1: // just to avoid warnings. + case kdtDevTypeCount: // just to avoid warnings. +#endif + number = 0; + break; + } + } + catch(K3LAPI::invalid_device & e) + { + return 0; + } + + return number; +} + + +K3LUtil::ErrorCountType K3LUtil::linkErrorCount(int32 dev, int32 link, + Verbose::Presentation fmt) +{ + ErrorCountType result; + K3L_LINK_ERROR_COUNTER status; + + KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev, + link + ksoLinkMon, &status, sizeof(status)); + + switch (ret) + { + case ksSuccess: + for (unsigned int i = klecChangesToLock; i < klecCount; i++) + { + result.push_back(ErrorCountPairType(Verbose::linkErrorCounter + ((KLinkErrorCounter)i, fmt), status.ErrorCounters[i])); + } + /* fall */ + + default: + return result; + } +} + diff --git a/src/mod/endpoints/mod_khomp/commons/k3lutil.hpp b/src/mod/endpoints/mod_khomp/commons/k3lutil.hpp new file mode 100644 index 0000000000..e547f3df6e --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/k3lutil.hpp @@ -0,0 +1,82 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include + +#include +#include + +#ifndef _K3LUTIL_HPP_ +#define _K3LUTIL_HPP_ + +struct K3LUtil +{ + typedef std::pair < std::string, unsigned int > ErrorCountPairType; + typedef std::list < ErrorCountPairType > ErrorCountType; + + K3LUtil(K3LAPI & k3lapi): _k3lapi(k3lapi) {}; + + std::string callStatus(int32 dev, int32 channel, + Verbose::Presentation fmt = Verbose::HUMAN); + + std::string channelStatus(int32, int32, + Verbose::Presentation fmt = Verbose::HUMAN); + + std::string linkStatus(int32, int32, + Verbose::Presentation fmt = Verbose::HUMAN, + KSignaling sig = ksigInactive); + + std::string getLinkStatus(int32, int32, + Verbose::Presentation fmt = Verbose::HUMAN); + + unsigned int physicalLinkCount(int32 dev, bool count_virtual = false); + + ErrorCountType linkErrorCount(int32, int32, + Verbose::Presentation fmt = Verbose::HUMAN); + + protected: + K3LAPI & _k3lapi; +}; + +#endif /* _K3LUTIL_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/logger.hpp b/src/mod/endpoints/mod_khomp/commons/logger.hpp new file mode 100644 index 0000000000..6fcf7bffe3 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/logger.hpp @@ -0,0 +1,644 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#if defined(COMMONS_LIBRARY_USING_ASTERISK) +extern "C" +{ + #include +} +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) +extern "C" +{ + #include +} +#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) +extern "C" +{ + #include +} +#endif +/* + +******************************************************************************** +***************************** 'Logger' user manual ***************************** +******************************************************************************** + +* Description: + +This class does the management of log messages for applications. It works with +the following axioms: + +<*> There are several class of messages. +<*> There are some outputs, which may be files, sockets, or a console device. +<*> There are options for classes, for outputs and for the association of both. + +The last rule also shows the order in which options are processed: first the +'classes' options are processed, then 'output' options are processed, and then +the options for the tuple '(class, output)' are processed. + +The options are mapped like this: + + -> options [prefix, flags] + -> options [prefix] +( , ) -> options [prefix, flags] + + - "prefix" means a fixed string prefix before the real message. + - "flags" means auxiliary flags (DATETIME, THREADID) which are + used to add information based on OS or process context info. + +* Example of use: + +typedef enum +{ + C_DBG_FUNC, + C_DBG_LOCK, + C_WARNING, + C_ERROR, + C_CLI, +} +AstClassId; + +typedef enum +{ + F_CONSOLE, + F_GENERIC, + F_TRACE, +} +AstOutputId; + +// used to indicate the console log // +struct AstConsoleLog {}; + +struct AstPrinter: public Logger::DefaultPrinter +{ + typedef Logger::DefaultPrinter Super; + + using namespace Tagged; + + using Super::operator()(int); + + // just 2 type of descriptors // + typedef Union < int, Union < AstConsoleLog > > Container; + + ast_printer(std::string & msg): Super(msg) {}; + + bool operator()(const AstConsoleLog & log) + { + ast_console_puts(_msg.c_str()); + return true; + }; + +#if 0 + bool operator()(int log) + { + return Super::operator()(log); + }; +#endif +}; + +bool start_log() +{ + typedef Logger::Manager LogManager; + + LogManager logger; + + // shortcut definition // + typedef LogManager::Option LogOption; + + FILE * log_file = fopen( "output.log", "a"); + + if (!log_file) + return false; + + logger.add( F_CONSOLE, AstConsoleLog(), "chan_khomp: "); + logger.add( F_GENERIC, log_file); + + logger.classe( C_WARNING ) + & LogOption(F_CONSOLE, "WARNING: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME))) + & LogOption(F_GENERIC, "W: ", LogOption::Flags(LogOption::Flag(LogOption::DATETIME))) + + logger.classe( C_DBG_LOCK ).enabled(false); + + logger.classe( C_DBG_LOCK ) + & LogOption(F_GENERIC, "L: ", LogOption::Flags + (LogOption::flag_type(LogOption::ENABLED) & + LogOption::flag_type(LogOption::DATETIME)) + + logger(C_WARNING, "eu sou uma mensagem de warning"); + + logger.classe(C_WARNING).set(F_GENERIC, LogOption::ENABLED, true); + logger.classe(C_WARNING).set(F_CONSOLE, LogOption::ENABLED, false); + + logger.classe(C_CLI).prefix(""); + + return true; +} + +void message_the_user(int fd) +{ + logger(C_CLI, fd, "eu sou uma mensagem de cli!"); + logger(C_WARNING, "eu sou um warning"); +} + +******************************************************************************** +******************************************************************************** + +Now, the code..! + +*/ + +#ifndef _LOGGER_HPP_ +#define _LOGGER_HPP_ + +#include + +struct Logger +{ + /*** a base struct for printing messages in many ways ***/ + + struct DefaultPrinter + { + typedef Tagged::Union < int, Tagged::Union < FILE *, Tagged::Union < std::ostream * > > > BaseType; + + typedef bool ReturnType; + + DefaultPrinter(std::string & msg): _msg(msg) {}; + + bool operator()(std::ostream * out) + { + (*out) << _msg; + out->flush(); + + return out->good(); + } + + bool operator()(FILE * out) + { + if (fputs(_msg.c_str(), out) < 0) + return false; + + if (fflush(out) < 0) + return false; + + return true; + } + + bool operator()(int out) + { +#ifndef KWIN32 + return (write(out, _msg.c_str(), _msg.size()) == (int)_msg.size()); +#else + // no need for file descriptors on windows + return false; +#endif + } + + std::string & msg() { return _msg; } + + protected: + std::string & _msg; + }; + + /*** manage the printing of messages ***/ + + template + struct Manager + { + typedef typename Printer::BaseType BaseType; + + protected: + /* holds a stream, and an optimal message prefix */ + struct OutputOptions + { + OutputOptions(BaseType & stream, std::string & prefix) + : _stream(stream), _prefix(prefix) {}; + + BaseType _stream; + std::string _prefix; + LockType _lock; + }; + + typedef std::map < OutputId, OutputOptions > OutputMap; + + public: + + /* print in a specific 'message class' */ + struct ClassType + { + ClassType(void) + : _enabled(true) + {}; + +// ClassType(ClassType & o) +// : _stream_map(o._stream_map), _prefix(o.prefix), +// _lock(o._lock),_enabled(o._enabled) +// {}; + + /* initializes the options of the (class, stream) pair */ + struct Option + { + typedef enum { ENABLED, DATETIME, THREADID, DATETIMEMS } EnumType; + + typedef Flagger< EnumType > Flags; + typedef typename Flags::InitFlags InitFlags; + + Option(OutputId output, const char * prefix, + Flags flags = InitFlags(ENABLED)) + : _output(output), _prefix(prefix), _flags(flags) {}; + + Option(OutputId output, std::string prefix, + Flags flags = InitFlags(ENABLED)) + : _output(output), _prefix(prefix), _flags(flags) {}; + + Option(OutputId output, + Flags flags = InitFlags(ENABLED)) + : _output(output), _flags(flags) {}; + + OutputId _output; + std::string _prefix; + Flags _flags; + }; + + protected: + + /* holds a prefix and a activation status */ + struct OptionContainer + { + OptionContainer(std::string prefix, typename Option::Flags flags) + : _prefix(prefix), _flags(flags) {}; + + std::string _prefix; + typename Option::Flags _flags; + }; + + typedef std::multimap < OutputId, OptionContainer > OptionMap; + + /* utility function for printing */ + bool print(std::string & msg, BaseType & stream, LockType & lock) + { + lock.lock(); + + Printer p(msg); + bool ret = stream.visit(p); + + lock.unlock(); + + return ret; + }; + +/* + bool print(std::string & msg, BaseType & stream, LockType & lock) + { + lock.lock(); + + Printer p(msg); + bool ret = stream.visit(p); + + lock.unlock(); + + return ret; + }; +*/ + + public: + ClassType & operator&(const Option & value) + { + add(value._output, value._prefix, value._flags); + return *this; + } + + void add(OutputId output_id, std::string prefix, + typename Option::Flags flags) + { + typedef std::pair < OutputId, OptionContainer > pair_type; + _stream_map.insert(pair_type(output_id, OptionContainer(prefix, flags))); + } + + /* get and set methods for active mode */ + void set(OutputId id, typename Option::EnumType flag, bool value = true) + { + typename OptionMap::iterator iter = _stream_map.find(id); + + if (iter == _stream_map.end()) + return; + + (*iter).second._flags.set(flag, value); + } + + bool get(OutputId idx, typename Option::EnumType flag) + { + typename OptionMap::iterator iter = _stream_map.find(idx); + + if (iter == _stream_map.end()) + return false; + + return (*iter).second._flags.is_set(flag); + } + + /* get/adjust the enable/disable value for the class */ + void enabled(bool enabled) { _enabled = enabled; }; + bool enabled() { return _enabled; }; + + /* get/adjust the classe prefix */ + void prefix(const char * prefix) { _prefix = prefix; } + void prefix(std::string & prefix) { _prefix = prefix; } + std::string & prefix() { return _prefix; } + + /* printing function (operator, actually) */ + bool operator()(OutputMap & out_map, std::string & msg) + { + if (!_enabled) + return true; + + typedef typename OptionMap::iterator Iter; + + bool ret = true; + + for (Iter iter = _stream_map.begin(); iter != _stream_map.end(); iter++) + { + OptionContainer & opt = (*iter).second; + + if (!opt._flags[Option::ENABLED]) + continue; + + typename OutputMap::iterator out_iter = out_map.find((*iter).first); + + /* this stream have been added already? if not, skip! */ + if (out_iter == out_map.end()) + continue; + + /* final message */ + std::string out_msg; + + if (opt._flags[Option::DATETIME]) + { +#if defined(COMMONS_LIBRARY_USING_ASTERISK) +#if ASTERISK_AT_LEAST(1,6,0) + struct timeval tv; + struct ast_tm lt; + + gettimeofday(&tv, NULL); + +#else + time_t tv; + struct tm lt; + + time (&tv); +#endif + +#if ASTERISK_AT_LEAST(1,4,5) + ast_localtime (&tv, <, NULL); +#else + localtime_r (&tv, <); +#endif + + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour + % lt.tm_min % lt.tm_sec); + +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) + time_t tv; + struct tm lt; + + time (&tv); + + localtime_r (&tv, <); + + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour + % lt.tm_min % lt.tm_sec); + +#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) + time_t tv; + struct tm lt; + + time (&tv); + + localtime_r (&tv, <); + + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour + % lt.tm_min % lt.tm_sec); + +#endif + } + + if (opt._flags[Option::DATETIMEMS]) + { +#if defined(COMMONS_LIBRARY_USING_ASTERISK) +#if ASTERISK_AT_LEAST(1,6,0) + struct timeval tv; + struct ast_tm lt; + + gettimeofday(&tv, NULL); + +#else + time_t tv; + struct tm lt; + + time (&tv); +#endif + +#if ASTERISK_AT_LEAST(1,4,5) + ast_localtime (&tv, <, NULL); +#else + localtime_r (&tv, <); +#endif + +#if ASTERISK_AT_LEAST(1,6,0) + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + % lt.tm_sec % (tv.tv_usec / 1000)); +#else + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + % lt.tm_sec % (tv * 1000)); +#endif + +#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) + time_t tv; + struct tm lt; + + time (&tv); + + localtime_r (&tv, <); + + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + % lt.tm_sec % (tv * 1000)); + +#elif defined(COMMONS_LIBRARY_USING_FREESWITCH) + time_t tv; + struct tm lt; + + time (&tv); + + localtime_r (&tv, <); + + out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ") + % (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min + % lt.tm_sec % (tv * 1000)); + +#endif + } + + OutputOptions & out_opt = (*out_iter).second; + + if (opt._flags[Option::THREADID]) + { +#if defined (COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH) + out_msg += STG(FMT("t=%08p ") % ((void*)pthread_self())); +#endif + } + + out_msg += _prefix; + out_msg += out_opt._prefix; + out_msg += opt._prefix; + out_msg += msg; + out_msg += "\n"; + + ret |= print(out_msg, out_opt._stream, out_opt._lock); + } + + return ret; + } + + bool operator()(BaseType & stream, std::string & msg) + { + std::string final_msg; + + final_msg += _prefix; + final_msg += msg; + final_msg += "\n"; + + return print(final_msg, stream, _lock); + } + + protected: + OptionMap _stream_map; + std::string _prefix; + LockType _lock; + bool _enabled; + }; + + /* util declaration */ + typedef typename ClassType::Option Option; + + /* class_id_type -> ClassType mapper */ + typedef std::map < ClassId, ClassType > ClassMap; + + /* local option pair */ + typedef std::pair < OutputId, OutputOptions > OutputOptionPair; + + void add(OutputId output, BaseType stream, const char * prefix = "") + { + std::string str_prefix(prefix); + + _output_map.insert(OutputOptionPair(output, OutputOptions(stream, str_prefix))); + } + + void add(OutputId output, BaseType stream, std::string prefix) + { + _output_map.insert(OutputOptionPair(output, OutputOptions(stream, prefix))); + } + + ClassType & classe(ClassId classeid) + { + return _classe_map[classeid]; + } + + bool operator()(ClassId classeid, const char * msg) + { + std::string str_msg(msg); + return _classe_map[classeid](_output_map, str_msg); + } + + bool operator()(ClassId classeid, std::string & msg) + { + return _classe_map[classeid](_output_map, msg); + } + + bool operator()(ClassId classeid, Format fmt) + { + std::string str_fmt = STG(fmt); + return _classe_map[classeid](_output_map, str_fmt); + } + + bool operator()(ClassId classeid, BaseType stream, const char * msg) + { + std::string str_msg(msg); + return _classe_map[classeid](stream, str_msg); + } + + bool operator()(ClassId classeid, BaseType stream, std::string & msg) + { + return _classe_map[classeid](stream, msg); + } + + bool operator()(ClassId classeid, BaseType stream, Format fmt) + { + std::string str_fmt = STG(fmt); + return _classe_map[classeid](stream, str_fmt); + } + + protected: + ClassMap _classe_map; + OutputMap _output_map; + }; + + private: + Logger(); +}; + +#endif /* _LOGGER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/noncopyable.hpp b/src/mod/endpoints/mod_khomp/commons/noncopyable.hpp new file mode 100644 index 0000000000..d32faa8913 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/noncopyable.hpp @@ -0,0 +1,54 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _NONCOPYABLE_HPP_ +#define _NONCOPYABLE_HPP_ + +struct NonCopyable +{ + NonCopyable() {}; + private: + NonCopyable(NonCopyable const &) { }; + NonCopyable & operator=(NonCopyable const &) { return *this; }; +}; + +#endif /* _NONCOPYABLE_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/refcounter.hpp b/src/mod/endpoints/mod_khomp/commons/refcounter.hpp new file mode 100644 index 0000000000..6ba8ae8b2f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/refcounter.hpp @@ -0,0 +1,263 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the "LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/* This struct uses static polymorphism, and derived classes should implement * + * the "unreference()" method, which should release all resources when called */ + +#ifndef _REFCOUNTER_HPP_ +#define _REFCOUNTER_HPP_ + +#define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ > +#define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o)) + +#include + +#include +#include + +#ifdef DEBUG +# include +#endif + +struct ReferenceData: public NonCopyable +{ + ReferenceData() + : _data_count(1) + {}; + + inline unsigned int increment(void) + { + if (!_data_count) + abort(); + + Atomic::doAdd(&_data_count); + + return _data_count; + } + + inline unsigned int decrement(void) + { + if (!_data_count) + abort(); + + Atomic::doSub(&_data_count); + return _data_count; + } + + volatile unsigned int _data_count; +}; + +template < typename T > +struct ReferenceCounter +{ + typedef T Type; + + ReferenceCounter(bool create_counter = true) + : _reference_count(0) + { + reference_restart(create_counter); + +#ifdef DEBUG + std::cerr << ((void*)this) << ": ReferenceCounter() [ref_count=" + << (_reference_count ? (*_reference_count) : -1) << "]" << std::endl; +#endif + }; + + ReferenceCounter(const ReferenceCounter & o) + : _reference_count(0) + { + reference_reflect(o); + +#ifdef DEBUG + std::cerr << ((void*)this) << ": ReferenceCounter(" << ((void*)(&o)) << ") [ref_count=" + << (_reference_count ? (*_reference_count) : -1) << "]" << std::endl; +#endif + }; + + virtual ~ReferenceCounter() + { +#ifdef DEBUG + std::cerr << ((void*)this) << ": ~ReferenceCounter() [ref_count=" + << (_reference_count ? (*_reference_count) : -1) << "]" << std::endl; +#endif + reference_disconnect(_reference_count); + } + + ReferenceCounter & operator=(const ReferenceCounter & o) + { + reference_reflect(o); + +#ifdef DEBUG + std::cerr << ((void*)this) << ": ReferenceCounter::operator=(" << ((void*)(&o)) << ") [ref_count=" + << (_reference_count ? (*_reference_count) : -1) << "]" << std::endl; +#endif + + return *this; + }; + + protected: + inline void reference_restart(bool create_counter = false) + { + ReferenceData * oldref = _reference_count; + + _reference_count = (create_counter ? new ReferenceData() : 0); + + if (oldref) reference_disconnect(oldref); + } + + inline void reference_reflect(const ReferenceCounter & other) + { + ReferenceData * newref = other._reference_count; + ReferenceData * oldref = _reference_count; + + /* NOTE: increment before, avoid our reference being zero, even * + * for a short period of time. */ + + if (newref) newref->increment(); + + _reference_count = newref; + + if (oldref) reference_disconnect(oldref); + }; + + inline void reference_disconnect(ReferenceData *& counter) + { + if (counter) + { + unsigned int result = counter->decrement(); + + if (!result) + { + static_cast< Type * >(this)->unreference(); + delete counter; + } + + counter = 0; + } + }; + + private: + ReferenceData * _reference_count; +}; + +template < typename T > +struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >) +{ + /* type */ + typedef T Type; + + /* shorthand */ + typedef ReferenceCounter < ReferenceContainer< Type > > Counter; + + // TODO: make this a generic exception someday + struct NotFound {}; + + ReferenceContainer() + : Counter(false), + _reference_value(0) + {}; + + ReferenceContainer(Type * value) + : _reference_value(value) + {}; + + ReferenceContainer(const ReferenceContainer & value) + : Counter(false), + _reference_value(0) + { + operator()(value); + }; + + virtual ~ReferenceContainer() + {}; + + ReferenceContainer operator=(const ReferenceContainer & value) + { + operator()(value); + return *this; + }; + + /**/ + + void unreference() + { + if (_reference_value) + { + delete _reference_value; + _reference_value = 0; + } + } + + // simulates a copy constructor + void operator()(const ReferenceContainer & value) + { + Counter::reference_reflect(value); + + _reference_value = const_cast(value._reference_value); + }; + + // shortcut for operator below + void operator=(const Type * value) + { + operator()(value); + }; + + // accept value (pointer)! + void operator()(const Type * value) + { + Counter::reference_restart((value != 0)); + + _reference_value = const_cast(value); + }; + + // return value (pointer)! + Type * operator()(void) + { + return _reference_value; + }; + + protected: + Type * _reference_value; + + protected: +}; + +#endif /* _REFCOUNTER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/regex.cpp b/src/mod/endpoints/mod_khomp/commons/regex.cpp new file mode 100644 index 0000000000..61f941c214 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/regex.cpp @@ -0,0 +1,148 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include + +void Regex::Expression::initialize(void) +{ + unsigned int tmplen = strlen(_expression); + + bool extflag = (_flags & E_EXTENDED); + + for (unsigned int i = 0; i < tmplen; ++i) + { + switch (_expression[i]) + { + case '\\': + ++i; + + if (!extflag && i < tmplen) + if (_expression[i] == '(') + ++_subcounter; + + break; + + case '(': + if (extflag) + ++_subcounter; + + default: + break; + } + } + + _errorstate = regcomp(&_comp_regex, _expression, _flags); +} + +std::string Regex::Expression::regerror_as_string(void) +{ + unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1; + + char * msg = new char[count]; + + regerror(_errorstate, &_comp_regex, msg, count); + + std::string tmp(msg, count); + + delete[] msg; + + return tmp; +} + +void Regex::Match::initialize(void) +{ + if (_expression.valid()) + { + _subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid + _submatches = new regmatch_t[_subcounter]; + _have_match = (regexec(_expression.repr(), _basestring.c_str(), + _subcounter, _submatches, _flags) == 0); + } +} + +std::string Regex::Match::replace(std::string rep, unsigned int index) +{ + ReplaceMap tmp; + tmp.insert(ReplacePair(index,rep)); + return replace(tmp); +} + +std::string Regex::Match::replace(Regex::ReplaceMap & map) +{ + if (!_have_match) + return _basestring; + + std::string buffer = _basestring; + + try + { + if (_submatches[0].rm_so != 0 && (map.find(0) != map.end())) + return _basestring.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second); + + for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++) + { + //// s f RRR s f RRR s f RRRR s f + //// XXXYYY(ZZZ)AAA(BBB)CCCEEE(FFFF)GGGG + + bool globalsubs = false; + + if (map.find(n) == map.end()) + { + if (map.find(UINT_MAX) == map.end()) + continue; + + globalsubs = true; + } + + buffer = buffer.replace(_submatches[n].rm_so, + _submatches[n].rm_eo - _submatches[n].rm_so, + map.find((globalsubs ? UINT_MAX : n))->second); + } + } + catch (std::out_of_range e) + { + return ""; + } + + return buffer; +} diff --git a/src/mod/endpoints/mod_khomp/commons/regex.hpp b/src/mod/endpoints/mod_khomp/commons/regex.hpp new file mode 100644 index 0000000000..daf20147a8 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/regex.hpp @@ -0,0 +1,252 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifndef _REGEX_HPP_ +#define _REGEX_HPP_ + +struct Regex +{ + enum + { + E_EXTENDED = REG_EXTENDED, + E_IGNORE_CASE = REG_ICASE, + E_NO_SUB_MATCH = REG_NOSUB, + E_EXPLICIT_NEWLINE = REG_NEWLINE, + }; + + enum + { + M_NO_BEGIN_OF_LINE = REG_NOTBOL, + M_NO_END_OF_LINE = REG_NOTEOL, + }; + + enum + { + /* mark replace for full match (submatch "0"). */ + REP_BASE = 0u, + /* mark global string for replace. */ + REP_ALL = UINT_MAX, + }; + + typedef std::pair < unsigned int, std::string > ReplacePair; + typedef std::map < unsigned int, std::string > ReplaceMap; + + struct Expression : public NonCopyable + { + Expression(const char * expression, unsigned int flags = 0) + : _expression(expression), _alloced(false), + _subcounter(0), _errorstate(INT_MAX), _flags(flags) + { + initialize(); + } + + Expression(std::string & expression, unsigned int flags = 0) + : _expression(strdup(expression.c_str())), _alloced(true), + _subcounter(0), _errorstate(INT_MAX), _flags(flags) + { + initialize(); + } + + ~Expression() + { + if (_errorstate != INT_MAX) + regfree(&_comp_regex); + + if (_alloced) + { + delete _expression; + _expression = 0; + } + } + + bool valid(void) { return (_errorstate == 0); } + + unsigned int subcount(void) { return _subcounter; } + const regex_t * repr(void) { return &_comp_regex; } + + std::string error(void) + { + switch (_errorstate) + { + case 0: return ""; + case INT_MAX: return "uninitialized"; + default: return regerror_as_string(); + } + } + + private: + void initialize(void); + std::string regerror_as_string(void); + + protected: + const char * _expression; + bool _alloced; + + unsigned int _subcounter; + + int _errorstate; + regex_t _comp_regex; + + unsigned int _flags; + }; + + struct Match: NEW_REFCOUNTER(Match) + { + Match(const char * basestring, Expression & expression, unsigned int flags = 0) + : _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0), + _have_match(false), _flags(flags) + { + initialize(); + } + + Match(std::string & basestring, Expression & expression, unsigned int flags = 0) + : _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0), + _have_match(false), _flags(flags) + { + initialize(); + } + + Match(const Match & o) + : INC_REFCOUNTER(o, Match), + _basestring(o._basestring), _expression(o._expression), + _subcounter(o._subcounter), _submatches(o._submatches), + _have_match(o._have_match), _flags(o._flags) + { + } + + void unreference() + { + delete[] _submatches; + } + + bool matched(void) + { + return _have_match; + } + + bool matched(unsigned int number) + { + if (_have_match && number < _subcounter) + return (_submatches[number].rm_so != -1); + + return false; + } + + std::string submatch(int number) + { + if (!matched(number)) + return ""; + + return _basestring.substr(_submatches[number].rm_so, + _submatches[number].rm_eo - _submatches[number].rm_so); + } + + /** + * \brief gets a map with all matches + * \return std::map with all matches + * \note index 0 in map, is the complete string + * \author Eduardo Nunes Pereira + * + * If fails the empty map is returned + */ + std::map obtain_match_map() + { + int match_counter = 0; + std::map tmp_map; + while(matched(match_counter)) + { + tmp_map.insert(std::make_pair(match_counter,submatch(match_counter))); + match_counter++; + } + + return tmp_map; + } + + /** + * \brief replaces strings matched by parentesis + * \param each item of the vector is a parentesis replaced + * \return string replaced + * \note The overload method match only one string in parentesis. + * \author Eduardo Nunes Pereira + * + * If fails the empty string is returned. + */ + std::string replace(ReplaceMap &); + std::string replace(std::string, unsigned int index = REP_BASE); + + std::string operator[](int number) + { + return submatch(number); + } + + // NOTE: there is already a way to get subcount defined on EXPRESSION class! + + private: + void initialize(void); + + protected: + std::string _basestring; + Expression & _expression; + + unsigned int _subcounter; + regmatch_t * _submatches; + + bool _have_match; + unsigned int _flags; + }; +}; + +#endif /* _REGEX_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp b/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp new file mode 100644 index 0000000000..428bd29221 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/ringbuffer.cpp @@ -0,0 +1,575 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +/********** BUFFER FUNCTIONS **********/ + +/* writes everything or nothing */ +bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool skip_overwrite) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int reader = cache.reader.complete; + const unsigned int writer = cache.writer.complete; + + const unsigned int dest = cache.writer.complete - 1; + + const bool reader_less = cache.reader.complete < cache.writer.complete; + + if (amount >= _size) + return false; + + bool ret = true; + + /* should we go around the buffer for writing? */ + if (((writer + amount) > _size) && (reader_less || !skip_overwrite)) + { + /* Documentation of the formula used in the 'if' below. + * + * [0|1|2|3|4|5|6|7] => size=8 + * | | + * reader | + * writer + * + * => writer has places [5,6,7,0,1] to write (5 places). + * + * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 + * + * > writer goes 1 up, amount goes 1 down. + * > reader goes 1 up, amount goes 1 up. + * > size goes 1 down, amount goes 1 down. + * + */ + + if ((_size - (writer - reader + 1)) <= amount) + { + if (skip_overwrite) + return false; + + do + { + Buffer_pointer extra(cache.reader); + extra.complete = (extra.complete + amount) % _size; + + if (update(cache.reader, extra)) + break; + } + while (true); + + ret = false; + } + + unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); + + /* two partial writes (one at the end, another at the beginning) */ + memcpy((void *) &(buffer[dest]), (const void *) (value), _block * wr1); + memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2); + } + else + { + if (!reader_less && ((reader - writer) <= amount)) + { + if (skip_overwrite) + return false; + + do + { + Buffer_pointer extra(cache.reader); + extra.complete = (extra.complete + amount) % _size; + + if (update(cache.reader, extra)) + break; + } + while (true); + + ret = false; + } + +// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) &(buffer[dest]), (const void *) value, _block * amount); + } + + _pointers.writer.complete = ((dest + amount) % _size) + 1; + _pointers.writer.partial = 1; + +// fprintf(stderr, "%p> write end: %d [block=%d]\n", this, writer, _block); + + return ret; +} + +/* returns the number of itens that have been read */ +unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int writer = _pointers.writer.complete; + const unsigned int reader = _pointers.reader.complete; + + const bool writer_less = writer < reader; + + unsigned int total = 0; + + /* should we go around the buffer for reading? */ + if (writer_less && (reader + amount >= _size)) + { + total = std::min(_size - (reader - writer + 1), amount); + + if ((total == 0) || (atomic_mode && (total < amount))) + return 0; + + unsigned int rd1 = _size - reader; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); + } + else + { + total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); + + if ((total == 0) || (atomic_mode && (total < amount))) + return 0; + +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[reader]), _block * total); + } + + do + { + /* jump the reader forward */ + Buffer_pointer index((cache.reader.complete + total) % _size); + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block); + + return total; +} + +/********** TWO-PHASE BUFFER FUNCTIONS ***********/ + +/* returns the number of itens that have been read */ +unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode) +{ + Buffer_table cache = _pointers; + + /* avoid using different values */ + const unsigned int reader = cache.reader.complete; + const unsigned int writer = cache.writer.complete; + + const bool writer_less = writer < reader; + + unsigned int total = 0; + + /* should we go around the buffer for reading? */ + if (writer_less && (reader + amount >= _size)) + { + total = std::min(_size - (reader - writer + 1), amount); + + if ((total == 0) || (atomic_mode && (total < amount))) + return 0; + + unsigned int rd1 = _size - reader; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[reader]), _block * rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2); + } + else + { + total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); + + if ((total == 0) || (atomic_mode && (total < amount))) + return 0; + +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[reader]), _block * total); + } + +// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial); + + return total; +} + +bool Ringbuffer_traits::traits_consume_commit(unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int writer = cache.writer.complete; + const unsigned int reader = cache.reader.complete; + + const bool writer_less = writer < reader; + + unsigned int total = 0; + + /* should we go around the buffer for reading? */ + if (writer_less && (reader + amount >= _size)) + { + total = std::min(_size - (reader - writer + 1), amount); + + if (total < amount) + return false; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + } + else + { + total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); + + if (total < amount) + return false; + +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + } + + do + { + /* jump the reader forward */ + Buffer_pointer index(cache.reader); + index.complete = (index.complete + total) % _size; + + if (update(cache.reader, index)) + break; + } + while (true); + +// fprintf(stderr, "%p> read end: %d [%d]\n", this, _reader, _reader_partial); + + return true; +} + +/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/ + +/* writes everything or nothing */ +bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial; + const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial; + + const unsigned int size = _size * _block; + const unsigned int dest = writer - 1; + +// fprintf(stderr, "%p> provide partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size); + + const bool reader_less = reader < writer; + + /* should we go around the buffer for writing? */ + if (reader_less && ((writer + amount) > size)) + { + /* Documentation of the formula used in the 'if' below. + * + * [0|1|2|3|4|5|6|7] => size=8 + * | | + * reader | + * writer + * + * => writer has places [5,6,7,0,1] to write (5 places). + * + * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 + * + * > writer goes 1 up, amount goes 1 down. + * > reader goes 1 up, amount goes 1 up. + * > size goes 1 down, amount goes 1 down. + * + */ + + if ((size - (writer - reader + 1)) <= amount) + return false; + + unsigned int wr1 = size - writer + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> p partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, size, reader, writer); + + /* two partial writes (one at the end, another at the beginning) */ + memcpy((void *) &(buffer[dest]), (const void *) (value), wr1); + memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2); + } + else + { + if (!reader_less && ((reader - writer) <= amount)) + return false; + +// fprintf(stderr, "%p> p full write: %d/%d [r=%d/w=%d]\n", this, amount, size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) &(buffer[dest]), (const void *) value, amount); + } + + unsigned int new_writer = ((dest + amount) % size) + 1; + + /* update "full length position" */ + _pointers.writer.complete = (unsigned int)floor((double) new_writer / (double)_block)+1; + _pointers.writer.partial = (unsigned short)(new_writer % _block); + +// fprintf(stderr, "%p> p write end: %d [block=%d]\n", this, new_writer, _block); + + return true; +} + +/* returns the number of bytes that have been read */ +unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int writer = ((cache.writer.complete - 1) * _block) + cache.writer.partial; + const unsigned int reader = (cache.reader.complete * _block) + cache.reader.partial; + + const unsigned int size = _size * _block; + +// fprintf(stderr, "%p> consume partial: %d/%d [%d/%d]\n", this, reader, writer, amount, size); + + const bool writer_less = writer < reader; + + unsigned int total = 0; + + /* should we go around the buffer for reading? */ + if (writer_less && (reader + amount >= size)) + { + total = std::min(size - (reader - writer + 1), amount); + + if (total == 0) + return 0; + + unsigned int rd1 = size - reader; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> p partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + memcpy((void *) (value), (const void *) &(buffer[reader]), rd1); + memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2); + } + else + { + total = std::min((writer_less ? amount : writer - (reader + 1)), amount); + + if (total == 0) + return 0; + +// fprintf(stderr, "%p> p full read: %d/%d [r=%d/w=%d]\n", this, total, size, reader, writer); + + /* we are talking about buffers here, man! */ + memcpy((void *) value, (const void *) &(buffer[reader]), total); + } + + do + { + unsigned int new_reader = (((cache.reader.complete * _block) + cache.reader.partial) + total) % size; + + /* jump the reader forward */ + Buffer_pointer index((unsigned int)floor((double)new_reader / (double)_block), + (unsigned short)(new_reader % _block)); + + if (update(cache.reader, index)) + { +// fprintf(stderr, "%p> p read end: %d [block=%d]\n", this, new_reader, _block); + break; + } + } + while (true); + + return total; +} + + + +/********** IO FUNCTIONS **********/ + +/* returns the number of items written to from buffer to stream */ +unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int reader = cache.reader.complete; + const unsigned int writer = cache.writer.complete; + + const bool writer_less = writer < reader; + + unsigned int total = 0; + + /* should we go around the buffer for reading? */ + if (writer_less && (reader + amount >= _size)) + { + total = std::min(_size - (reader - writer + 1), amount); + + if (total == 0) + return 0; + + unsigned int rd1 = _size - reader; + unsigned int rd2 = total - rd1; + +// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer); + + /* two partial consumes (one at the end, another at the beginning) */ + fd.write((const char *) &(buffer[reader]), _block * rd1); + fd.write((const char *) (buffer), _block * rd2); + } + else + { + total = std::min((!writer_less ? writer - (reader + 1) : amount), amount); + + if (total == 0) + return 0; + +// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer); + + /* we are talking about buffers here, man! */ + fd.write((const char *) &(buffer[reader]), _block * total); + } + + do + { + /* jump the reader forward */ + Buffer_pointer index(cache.reader); + index.complete = (index.complete + total) % _size; + + if (update(cache.reader, index)) + break; + } + while (true); + + return total; +} + +/* returns number of items read from stream to buffer */ +unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount) +{ + /* avoid using different values */ + Buffer_table cache = _pointers; + + const unsigned int reader = cache.reader.complete; + const unsigned int writer = cache.writer.complete; + + const unsigned int dest = writer - 1; + + const bool reader_less = reader < writer; + + unsigned int real_amount = 0; + + /* should we go around the buffer for writing? */ + if (reader_less && ((writer + amount) > _size)) + { + /* Documentation of the formula used in the 'if' below. + * + * [0|1|2|3|4|5|6|7] => size=8 + * | | + * reader | + * writer + * + * => writer has places [5,6,7,0,1] to write (5 places). + * + * => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5 + * + * > writer goes 1 up, amount goes 1 down. + * > reader goes 1 up, amount goes 1 up. + * > size goes 1 down, amount goes 1 down. + * + */ + + if ((_size - (writer - reader + 1)) <= amount) + return false; + + unsigned int wr1 = _size - writer + 1; /* writer is already 1 position after */ + unsigned int wr2 = amount - wr1; + +// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer); + + unsigned int char_amount = 0; + + /* one partial write on the buffer (at the end) */ + fd.read((char *) &(buffer[dest]), _block * wr1); + char_amount += fd.gcount(); + + if (fd.gcount() == (int)(_block * wr1)) + { + /* another partial write on the buffer (at the beginning) */ + fd.read((char *) (buffer), _block * wr2); + char_amount += fd.gcount(); + } + + real_amount = char_amount / _block; + } + else + { + if (!reader_less && ((reader - writer) <= amount)) + return false; + +// fprintf(stderr, "%p> full write: %d/%d [%d/%d]\n", this, amount, _size, reader, writer); + + /* we are talking about buffers here, man! */ + fd.read((char *) &(buffer[dest]), _block * amount); + + real_amount = fd.gcount() / _block; + } + + _pointers.writer.complete = ((dest + real_amount) % _size) + 1; + _pointers.writer.partial = 1; + + return real_amount; +} diff --git a/src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp b/src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp new file mode 100644 index 0000000000..39f8ffe8fb --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/ringbuffer.hpp @@ -0,0 +1,416 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/* WARNING: This is a generic ringbuffer abstraction, which works for single-sized elements, + partial elements, single/multi-elements read/writes. It is not wise to mix some + functions (partial element write / full element write), since it was not designed + with this use in mind. + + Also, it works only for single-reader + single-writer, since it does not depends + on external mutex functions. + */ + +#include + +#include +#include + +#include +#include + +#ifndef _RINGBUFFER_HPP_ +#define _RINGBUFFER_HPP_ + +struct Buffer_pointer +{ + Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u) + : complete(_complete), partial(_partial) + {}; + + Buffer_pointer(const Buffer_pointer & o) + : complete(o.complete), partial(o.partial) + {}; + + Buffer_pointer(const volatile Buffer_pointer & o) + : complete(o.complete), partial(o.partial) + {}; + + void operator=(const volatile Buffer_pointer o) + { + complete = o.complete; + partial = o.partial; + } + + void operator=(const Buffer_pointer o) volatile + { + complete = o.complete; + partial = o.partial; + } + + bool operator==(const Buffer_pointer & o) + { + return (complete == o.complete && partial == o.partial); + } + + unsigned int complete:20; + unsigned short partial:12; +} +__attribute__((packed)); + +struct Buffer_table +{ + Buffer_table() + : reader(0,0), + writer(1,1) + {}; + + Buffer_table(const Buffer_table & o) + : reader(o.reader), writer(o.writer) + {}; + + Buffer_table(const volatile Buffer_table & o) + : reader(o.reader), writer(o.writer) + {}; + + void operator=(const volatile Buffer_table o) + { + reader = o.reader; + writer = o.writer; + } + + void operator=(const Buffer_table o) volatile + { + reader = o.reader; + writer = o.writer; + } + + bool operator==(const Buffer_table & o) + { + return (reader == o.reader && writer == o.writer); + } + + Buffer_pointer reader; + Buffer_pointer writer; +} +__attribute__((packed)); + +struct Ringbuffer_traits +{ + Ringbuffer_traits(unsigned int block, unsigned int size) + : _block(block), _size(size) + {}; + + bool traits_provide( char *, const char *, unsigned int, bool); + unsigned int traits_consume(const char *, char *, unsigned int, bool); + + unsigned int traits_consume_begins(const char *, char *, unsigned int, bool); + bool traits_consume_commit(unsigned int); + + bool traits_provide_partial( char *, const char *, unsigned int); + unsigned int traits_consume_partial(const char *, char *, unsigned int); + + unsigned int traits_get( char *, std::istream &, unsigned int); + unsigned int traits_put(const char *, std::ostream &, unsigned int); + + bool update(Buffer_pointer & cache, Buffer_pointer & update) + { + return Atomic::doCAS(&(_pointers.reader), &cache, update); + } + + protected: + const unsigned int _block; + const unsigned int _size; + + volatile Buffer_table _pointers; +}; + +template +struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable +{ + struct BufferFull {}; + struct BufferEmpty {}; + + Ringbuffer(unsigned int size) + : Ringbuffer_traits(sizeof(T), size) + { + _buffer = new T[_size]; + _malloc = true; + }; + + Ringbuffer(unsigned int size, T * buffer) + : Ringbuffer_traits(sizeof(T), size) + { + _buffer = buffer; + _malloc = false; + }; + + ~Ringbuffer() + { + if (_malloc) + delete[] _buffer; + } + + /***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/ + bool may_write(Buffer_table & cache) + { + const unsigned int r = cache.reader.complete; + const unsigned int w = cache.writer.complete; + + return (((r - w) != 1) && (!(r == 0 && w == _size))); + } + + bool may_read(Buffer_table & cache) + { + if ((cache.writer.complete - cache.reader.complete) == 1) + return false; + + return true; + } + + unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index) + { + unsigned int dest = cache.complete - 1, + temp = cache.complete + 1; + + if (temp > _size) index.complete = 1; + else index.complete = temp; + + index.partial = 1; + + return dest; + }; + + void reader_next(Buffer_pointer & cache, Buffer_pointer & index) + { + unsigned int temp = cache.complete + 1; + + if (temp == _size) index.complete = 0; + else index.complete = temp; + + index.partial = 0; + } + + /***** BUFFER FUNCTIONS *****/ + + bool provide(const T & value) + { + Buffer_table cache = _pointers; + Buffer_pointer index = _pointers.writer; + + if (!may_write(cache)) + return false; + +// fprintf(stderr, "%p> provide %d/%d!\n", this, reader, writer); + + unsigned int dest = writer_next(cache.writer, index); + + _buffer[dest] = value; + + _pointers.writer = index; + +// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial); + + return true; + } + + bool consume(T & value) + { + Buffer_table cache = _pointers; + Buffer_pointer index = _pointers.reader; + + if (!may_read(cache)) + return false; + +// fprintf(stderr, "%p> consume %d/%d!\n", this, reader, writer); + + value = _buffer[index.complete]; + + do + { + reader_next(cache.reader, index); + + if (update(cache.reader, index)) + break; + + cache.reader = index; + } + while (true); + +// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial); + + return true; + } + + /* writes everything or nothing */ + inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true) + { + return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite); + } + + /* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */ + inline unsigned int consume(T * value, unsigned int amount, bool atomic_mode = false) + { + return traits_consume((const char *)_buffer, (char *) value, amount, atomic_mode); + } + + /***** TWO-PHASE BUFFER FUNCTIONS *****/ + + /* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */ + inline unsigned int consume_begins(T * value, unsigned int amount, bool atomic_mode = false) + { + return traits_consume_begins((const char *)_buffer, (char *) value, amount, atomic_mode); + } + + /* returns true if we could commit that much of buffer (use only after consume_begins). * + * note: you may commit less bytes that have been read to keep some data inside the buffer */ + inline bool consume_commit(unsigned int amount) + { + return traits_consume_commit(amount); + } + + /***** TWO-PHASE SINGLE-ELEMENT BUFFER FUNCTIONS *****/ + + T & provider_start(void) + { + Buffer_table cache = _pointers; + + if (!may_write(cache)) + throw BufferFull(); + + unsigned writer = _pointers.writer.complete - 1; + +// fprintf(stderr, "%p> provider start %d/%d!\n", this, reader, writer); + + return _buffer[writer]; + } + + void provider_commit(void) + { + unsigned int temp = _pointers.writer.complete + 1; + +// fprintf(stderr, "%p> provider commit %d!\n", this, temp); + + if (temp > _size) + temp = 1; + + _pointers.writer.complete = temp; + _pointers.writer.partial = 1; + +// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial); + } + + T & consumer_start(void) + { + Buffer_table cache = _pointers; + + if (!may_read(cache)) + throw BufferEmpty(); + + unsigned int reader = _pointers.reader.complete; + +// fprintf(stderr, "%p> consumer start %d/%d!\n", this, reader, writer); + + return _buffer[reader]; + } + + void consumer_commit(void) + { + Buffer_pointer cache = _pointers.reader; + Buffer_pointer index(cache); + + do + { + reader_next(cache, index); + + if (update(cache, index)) + break; + + cache = index; + } + while (true); + +// fprintf(stderr, "%p> consumer commit %d!\n", this, temp); + +// fprintf(stderr, "%p> read: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial); + } + + /* writes everything or nothing, but works on bytes (may write incomplete elements) */ + /* WARNING: do not mix this with full element provider */ + inline bool provider_partial(const char *buffer, unsigned int amount) + { + return traits_provide_partial((char *)_buffer, buffer, amount); + } + + /* returns the number of bytes that have been read (may read incomplete elements) */ + /* WARNING: do not mix this with full element consumer */ + inline unsigned int consumer_partial(char *buffer, unsigned int amount) + { + return traits_consume_partial((const char *)_buffer, buffer, amount); + } + + /***** IO FUNCTIONS *****/ + + /* returns the number of items written to from buffer to stream */ + inline unsigned int put(std::ostream &fd, unsigned int amount) + { + return traits_put((char *)_buffer, fd, amount); + } + + /* returns number of items read from stream to buffer */ + inline unsigned int get(std::istream &fd, unsigned int amount) + { + return traits_get((const char *)_buffer, fd, amount); + } + + void clear() + { + _pointers.reader.complete = 0; + _pointers.reader.partial = 0; + _pointers.writer.complete = 1; + _pointers.writer.partial = 1; + } + + protected: + T * _buffer; + bool _malloc; +}; + +#endif /* _RINGBUFFER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/saved_condition.cpp b/src/mod/endpoints/mod_khomp/commons/saved_condition.cpp new file mode 100644 index 0000000000..4c9f80f47f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/saved_condition.cpp @@ -0,0 +1,46 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include + +#include COMMONS_INCLUDE(saved_condition.cpp) + diff --git a/src/mod/endpoints/mod_khomp/commons/saved_condition.hpp b/src/mod/endpoints/mod_khomp/commons/saved_condition.hpp new file mode 100644 index 0000000000..dcfd22423d --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/saved_condition.hpp @@ -0,0 +1,61 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _SAVED_CONDITION_COMMON_HPP_ +#define _SAVED_CONDITION_COMMON_HPP_ + +#include + +//#include + +struct SavedConditionCommon +{ + SavedConditionCommon() : _signaled(false) {} + + protected: + bool _signaled; +}; + + +#include COMMONS_INCLUDE(saved_condition.hpp) + +#endif /* _SAVED_CONDITION_COMMON_HPP_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/scoped_lock.hpp b/src/mod/endpoints/mod_khomp/commons/scoped_lock.hpp new file mode 100644 index 0000000000..a85627f3cd --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/scoped_lock.hpp @@ -0,0 +1,95 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +struct ScopedLockBasic +{ + ScopedLockBasic(void) + : _locked(true) {}; + + ScopedLockBasic(bool locked) + : _locked(locked) {}; + + virtual ~ScopedLockBasic() {}; + + protected: + bool _locked; +}; + + +struct ScopedLock : public ScopedLockBasic +{ + struct LockFailed {}; + + ScopedLock(SimpleLock & mutex) + : ScopedLockBasic(false), _mutex(mutex) + { + switch (_mutex.lock()) + { + case SimpleLock::ISINUSE: + case SimpleLock::FAILURE: + throw LockFailed(); + default: + break; + } + + _locked = true; + } + + ~ScopedLock() + { + unlock(); + } + + void unlock() + { + if (_locked) + { + _locked = false; + _mutex.unlock(); + } + } + + protected: + SimpleLock & _mutex; +}; + diff --git a/src/mod/endpoints/mod_khomp/commons/simple_lock.hpp b/src/mod/endpoints/mod_khomp/commons/simple_lock.hpp new file mode 100644 index 0000000000..4f6619f456 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/simple_lock.hpp @@ -0,0 +1,104 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _SIMPLE_LOCK_COMMON_HPP_ +#define _SIMPLE_LOCK_COMMON_HPP_ + +#include + +#include +#include + +#include + +/* This struct uses static polymorphism, and derived classes should implement * + * the "lock/trylock/unlock()" methods for correct code compilation. * + * The base class also features reference counting, so derived classes should * + * implement the "unreference()" method for releasing resources. */ + +template < typename Implementor > +struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > ) +{ + friend class ReferenceCounter < SimpleLockCommon < Implementor > >; + + typedef enum + { + ISINUSE = 0, // operation not succeded (no error) + SUCCESS = 1, // operation succeded (no error) + FAILURE = 2, // mutex or state is somehow invalid (error! run for your life!) + } + Result; + + SimpleLockCommon() + {}; + + SimpleLockCommon(const SimpleLockCommon & o) + : INC_REFCOUNTER(o, SimpleLockCommon) + {}; + + virtual ~SimpleLockCommon() + {}; + + inline Result lock() + { + return static_cast(this)->lock(); + } + + inline Result trylock() + { + return static_cast(this)->trylock(); + } + + inline void unlock() + { + static_cast(this)->unlock(); + } + + protected: + void unreference(void) + { + static_cast(this)->unreference(); + } +}; + +#include COMMONS_INCLUDE(simple_lock.hpp) + +#endif /* _SIMPLE_LOCK_COMMON_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/strings.cpp b/src/mod/endpoints/mod_khomp/commons/strings.cpp new file mode 100644 index 0000000000..5e1cbc7004 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/strings.cpp @@ -0,0 +1,247 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +void Strings::Merger::add(std::string s) +{ + _list.push_back(s); +}; + +std::string Strings::Merger::merge(const std::string & sep) +{ + list_type::iterator i = _list.begin(); + + std::string res; + + if (i != _list.end()) + { + res += (*i); + ++i; + }; + + while (i != _list.end()) + { + res += sep; + res += (*i); + ++i; + } + + return res; +}; + +std::string Strings::Merger::merge(const char *sep) +{ + std::string ssep(sep); + return merge(ssep); +} + +unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & tokens, + const std::string & delims, long int max_tokens, bool keep_empty) +{ + std::string::size_type base = 0; + + std::string::size_type init = str.find_first_not_of(delims, 0); + std::string::size_type fini = str.find_first_of(delims, init); + + long int cur_token = 1; + + while (std::string::npos != init) + { + if (keep_empty && base < init) + { + std::string::size_type cur_empty = init - base; + + while (cur_empty && cur_token < max_tokens) + { + tokens.push_back(""); + + ++cur_token; + --cur_empty; + } + } + + if (std::string::npos != fini && cur_token < max_tokens) + { + base = fini + 1; + + tokens.push_back(str.substr(init, fini - init)); + ++cur_token; + } + else + { + base = str.size(); // find_first_of(delims, init); + + tokens.push_back(str.substr(init, str.size() - init)); + break; + } + + init = str.find_first_not_of(delims, fini); + fini = str.find_first_of(delims, init); + } + + if (keep_empty && base != str.size()) + { + std::string::size_type cur_empty = str.size() - base + 1; + + while (cur_empty && cur_token < max_tokens) + { + tokens.push_back(""); + + ++cur_token; + --cur_empty; + } + + if (cur_empty) + { + std::string::size_type pos = base + cur_empty - 1; + tokens.push_back(str.substr(pos, str.size() - pos)); + ++cur_token; + } + } + + return (cur_token - 1); +} + +bool Strings::toboolean(std::string str) +{ + std::string tmp(str); + + Strings::lower(tmp); + + if ((tmp == "true") || (tmp == "yes")) return true; + if ((tmp == "false") || (tmp == "no")) return false; + + throw invalid_value(str); +} + +long Strings::tolong(std::string str, int base) +{ + char *str_end = 0; + + unsigned long value = strtol(str.c_str(), &str_end, base); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +} + +unsigned long Strings::toulong(std::string str, int base) +{ + char *str_end = 0; + + unsigned long value = strtoul(str.c_str(), &str_end, base); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +} + +unsigned long long Strings::toulonglong(std::string str, int base) +{ +#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32) + throw not_implemented(); +#else + char *str_end = 0; + + unsigned long long value = strtoull(str.c_str(), &str_end, base); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +#endif +} + +double Strings::todouble(std::string str) +{ + char *str_end = 0; + + double value = strtod(str.c_str(), &str_end); + + if (str_end && *str_end == 0) + return value; + + throw invalid_value(str); +} + +std::string Strings::fromboolean(bool value) +{ + if (value) return "true"; + else return "false"; +} + +std::string Strings::lower(std::string str) +{ + std::string res; + + for (std::string::iterator i = str.begin(); i != str.end(); i++) + res += tolower((*i)); + + return res; +} + +std::string Strings::hexadecimal(std::string value) +{ + std::string result; + + for (std::string::iterator i = value.begin(); i != value.end(); i++) + { + if (i != value.begin()) + result += " "; + + result += STG(FMT("%2x") % (unsigned int)(*i)); + } + + return result; +} + +std::string Strings::trim(const std::string& str, const std::string& trim_chars) +{ + std::string result(str); + + result.erase( result.find_last_not_of( trim_chars ) + 1 ); + result.erase( 0, result.find_first_not_of( trim_chars ) ); + + return result; +} diff --git a/src/mod/endpoints/mod_khomp/commons/strings.hpp b/src/mod/endpoints/mod_khomp/commons/strings.hpp new file mode 100644 index 0000000000..056b9335c6 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/strings.hpp @@ -0,0 +1,106 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include +#include +#include + +#include + +#include + +/* Generic string funcions */ + +#ifndef _STRINGS_HPP_ +#define _STRINGS_HPP_ + +struct Strings +{ + typedef std::list list_type; + typedef std::vector vector_type; + + struct Merger + { + void add(std::string); + + std::string merge(const std::string &); + std::string merge(const char *); + + bool empty() { return _list.empty(); }; + + protected: + list_type _list; + }; + + public: + struct invalid_value + { + invalid_value(const char * value): _value(value) {}; + invalid_value(std::string value): _value(value) {}; + + std::string & value() { return _value; } + + protected: + std::string _value; + }; + + struct not_implemented {}; + + static unsigned int tokenize(const std::string &, vector_type &, const std::string & delims = ",;:", + long int max_toxens = LONG_MAX, bool keep_empty = true); + + static bool toboolean(std::string); + static std::string fromboolean(bool); + + static long tolong(std::string, int base = 10); + static unsigned long toulong(std::string, int base = 10); + static unsigned long long toulonglong(std::string, int base = 10); + static double todouble(std::string); + + static std::string lower(std::string); + static std::string hexadecimal(std::string); + + static std::string trim(const std::string&, const std::string& trim_chars = " \f\n\r\t\v"); +}; + +#endif // _STRINGS_HPP_ // diff --git a/src/mod/endpoints/mod_khomp/commons/tagged_union.hpp b/src/mod/endpoints/mod_khomp/commons/tagged_union.hpp new file mode 100644 index 0000000000..1616268c5f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/tagged_union.hpp @@ -0,0 +1,307 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _TAGGED_UNION_HPP_ +#define _TAGGED_UNION_HPP_ + +#include + +#include +#include + +namespace Tagged +{ + struct EmptyUnion + { + friend class Value; + + EmptyUnion() + : _adjusted(false) {}; + + // copy constructor + EmptyUnion(const EmptyUnion & o) + : _adjusted(o._adjusted) {}; + + // copy assignment operator + EmptyUnion & operator=(const EmptyUnion & o) + { + _adjusted = o._adjusted; + return *this; + }; + + ~EmptyUnion() { _adjusted = false; }; + + bool operator==(const EmptyUnion & o) + { + return true; + }; + + public: + void clear(void) { _adjusted = false; }; + protected: + void setup(void) { _adjusted = true; }; + + protected: + bool value_set(void) { return false; }; + bool value_get(void) { return false; }; + + bool value_check(void) { return false; }; + + template < typename S > + bool value_visit(S & visitor, typename S::ReturnType & ret) + { + return false; + }; + + template < typename S > + bool value_visit_void(S & visitor) + { + return false; + }; + + bool adjusted() { return _adjusted; }; + + private: + bool _adjusted; + }; + + template < typename V, typename E = EmptyUnion > + struct Union: public E + { + friend class Value; + + // default constructor + Union() + : _value(0) {}; + + // constructor with initializer + template < typename U > + Union( U value ) + : _value(0) + { + set(value); + }; + + // copy constructor + Union(const Union & o) + : E(static_cast(o)), + _value( (o._value ? new const V(*(o._value)) : 0) ) + {}; + + // copy assignment operator + Union & operator=(const Union & o) + { + if (_value) + { + delete _value; + _value = 0; + } + + if (o._value) + { + _value = new const V(*(o._value)); + } + + E::operator=(static_cast(o)); + + return *this; + }; + + // destructor + ~Union() + { + if (_value) + { + delete _value; + _value = 0; + } + }; + + // equal sign operator + template < typename U > + void operator=(U value) + { + set(value); + } + + template < typename U > + bool check(void) + { + return value_check(static_cast(0)); + }; + + template < typename U > + const U & get(void) + { + const U * res = 0; + + if (!value_get(&res) || !res) + throw std::runtime_error("type mismatch"); + + return *res; + }; + + template < typename U > + void set(U val) + { + if (E::adjusted()) + clear(); + + if (!value_set(val)) + throw std::runtime_error("unable to set value of invalid type"); + }; + + template < typename S > + typename S::ReturnType visit(S visitor) + { + typename S::ReturnType ret; + + if (!value_visit(visitor, ret)) + throw std::runtime_error("unable to visit empty value"); + + return ret; + }; + + template < typename S > + void visit_void(S visitor) + { + if (!value_visit_void(visitor)) + throw std::runtime_error("unable to visit empty value"); + }; + + void clear() + { + if (_value) + { + delete _value; + _value = 0; + } + + E::clear(); + }; + + // compare (equal) operator + bool operator==(const Union & o) + { + bool are_equal = false; + + if (!_value && !(o._value)) + are_equal = true; + + if (_value && o._value) + are_equal = (*_value == *(o._value)); + + if (are_equal) + return E::operator==(static_cast(o)); + + return false; + }; + + // compare types + bool sameType(const Union & o) + { + if ((!(_value) && !(o._value)) || (_value && o._value)) + return E::operator==(static_cast(o)); + + return false; + }; + + protected: + using E::value_set; + using E::value_get; + + using E::value_check; + using E::value_visit; + using E::value_visit_void; + + bool value_set(V val) + { + _value = new const V(val); + E::setup(); + + return true; + }; + + bool value_get(const V ** val) + { + if (!_value) + return false; + + *val = _value; + return true; + } + + bool value_check(const V * const junk) + { + (void)junk; + return (_value != 0); + }; + + template < typename S > + bool value_visit(S & visitor, typename S::ReturnType & ret) + { + if (_value) + { + ret = visitor(*const_cast(_value)); + return true; + }; + + return E::value_visit(visitor, ret); + }; + + template < typename S > + bool value_visit_void(S & visitor) + { + if (_value) + { + visitor(*const_cast(_value)); + return true; + }; + + return E::value_visit_void(visitor); + }; + + private: + const V * _value; + }; +}; + +#endif /* _TAGGED_UNION_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/thread.hpp b/src/mod/endpoints/mod_khomp/commons/thread.hpp new file mode 100644 index 0000000000..e00d7c875a --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/thread.hpp @@ -0,0 +1,103 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _THREAD_COMMON_HPP_ +#define _THREAD_COMMON_HPP_ + +#include + +#include +//#include + +struct ThreadCommon +{ + protected: + template + struct DecomposeFuncPtr; + + template + struct DecomposeFuncPtr + { + typedef ReturnType Return; + }; + + template + struct DecomposeFuncPtr + { + typedef void Return; + }; + + template + struct DecomposeFuncPtr + { + typedef ReturnType Return; + }; + + template< typename FunctionType > + struct DecomposeFunction + { + typedef typename Select < IsClass< FunctionType >::Result, int, + typename DecomposeFuncPtr< FunctionType >::Return >::Result + Return; + }; + + public: + struct ThreadDataCommon + { + ThreadDataCommon() {} + + virtual ~ThreadDataCommon() {} + + virtual int run() = 0; + + ThreadCommon * _thread; + + void * _self; + void * _attribute; + }; + + ThreadCommon() {} +}; + + +#include COMMONS_INCLUDE(thread.hpp) + +#endif /* _THREAD_COMMON_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/timer.cpp b/src/mod/endpoints/mod_khomp/commons/timer.cpp new file mode 100644 index 0000000000..36e32f521a --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/timer.cpp @@ -0,0 +1,352 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +TimerTraits::TimerTraits() +: _thread((Thread*)0), _purify(false), _last_tick(0), _age_count(0), _shutdown(false) +{}; + +bool TimerTraits::start (void) +{ + _shutdown = false; + + _condition.reset(); + _finalized.reset(); + + if (!_thread) + { + _thread = new Thread(TimerTraits::loop_thread(this)); + _purify = true; + } + +#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32) + // set priority ... +#else + pthread_attr_t attrs; + sched_param param; + + if (pthread_attr_init(&attrs) < 0) + return false; + + if (pthread_attr_setschedpolicy(&attrs, SCHED_RR) < 0) + return false; + + if (pthread_attr_getschedparam(&attrs, ¶m) < 0) + return false; + + param.sched_priority = sched_get_priority_max(SCHED_RR); + + if (pthread_attr_setschedparam(&attrs, ¶m) < 0) + return false; + + // set priority... + +// if (pthread_create(&_thread, &attrs, TimerTraits::loop_thread, NULL) < 0) +// return false; + + _thread->start(); +#endif + + return true; +} + +bool TimerTraits::stop (void) +{ + _shutdown = true; + + _condition.signal(); + + _finalized.wait(10000); /* 10 seconds max wait */ + + if (_thread && _purify) + { + delete _thread; + + _thread = (Thread *)0; + _purify = false; + } + + return true; +} + +//----------------------------------------- + +int TimerTraits::loop_thread::operator()(void) +{ + try + { + _timer->loop(); + } + catch( ... ) + { + /* something wrong happened! */ + } + + _timer->_finalized.signal(); + + return 0; +} + +void TimerTraits::execute(ControlSet::iterator init, const TimerTraits::Control & ctrl) +{ + volatile CallbackFuncType func = (volatile CallbackFuncType) ctrl._func; + volatile CallbackDataType data = (volatile CallbackDataType) ctrl._data; + + _timer_set.erase(init); + + _mutex.unlock(); + + func(data); +} + +void TimerTraits::loop (void) +{ + while (true) + { + if (_shutdown) break; + + _mutex.lock(); + + ControlSet::iterator init = _timer_set.begin(); + + if (init == _timer_set.end()) + { + _mutex.unlock(); + _condition.wait(); + } + else + { + const Control & ctrl = *init; + + unsigned int ts_now = TimerTraits::tick(); + + if (_age_count == ctrl._age) + { + if (ts_now < ctrl._msecs) + { + /* age is right, but it is not time to expire yet... */ + volatile unsigned int wait_time = ctrl._msecs - ts_now; + _mutex.unlock(); + _condition.wait(wait_time); /* expire - now */ + } + else + { + /* age is right, and we should expire! */ + execute(init, ctrl); /* called locked, return unlocked */ + } + } + else if (_age_count < ctrl._age) + { + /* age is not there yet (need some time to overlap)... */ + volatile unsigned int wait_time = (UINT_MAX - ts_now) + ctrl._msecs; + _mutex.unlock(); + _condition.wait(wait_time); /* MAX - now + expire */ + } + else + { + /* age has passed, we should have expired before! */ + execute(init, ctrl); /* called locked, return unlocked */ + } + } + } + + _finalized.signal(); +} + +unsigned int TimerTraits::tick() +{ +#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32) + unsigned int tick = GetTickCount(); +#else + struct timespec ticks; + + // error condition, make the user notice this.. + if (clock_gettime(CLOCK_MONOTONIC, &ticks) < 0) + return 0; + + unsigned int tick = ( ticks.tv_sec * 1000 ) + ( ticks.tv_nsec / 1000000 ); +#endif + + if (_last_tick > tick) + ++_age_count; + + _last_tick = tick; + + return tick; +} + +//----------------------------------------- + +TimerTraits::Index TimerTraits::traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value) +{ + unsigned int ms_tick = TimerTraits::tick(); + + unsigned int ms_left = UINT_MAX - ms_tick; + unsigned int ms_real = msecs; + + unsigned int age_num = _age_count; + + if (ms_left < msecs) + { + ms_real -= ms_left; + ++age_num; + } + else + { + ms_real += ms_tick; + } + + ControlSet::iterator it = _timer_set.insert(Control(age_num,ms_real,func,data,value)); + + if (_timer_set.size() == 1 || _timer_set.begin() == it) + { + _condition.signal(); + }; + + return Index(age_num, ms_real, msecs, func, data, value); +} + +TimerTraits::Index TimerTraits::traits_add (unsigned int msecs, const void * func, const void * data, unsigned int value) +{ + _mutex.lock(); + + Index idx = traits_add_unlocked(msecs, func, data, value); + + _mutex.unlock(); + + return idx; +} + +bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force) +{ + bool ret = false; + + _mutex.lock(); + + if (idx.valid) + { + if (traits_del_unlocked(idx) || force) + { + idx = traits_add_unlocked(idx.delta, idx.func, idx.data, idx.value); + ret = true; + } + } + + _mutex.unlock(); + + return ret; +} + +bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx) +{ + bool ret = false; + + if (idx.valid) + { + ControlSet::iterator i = _timer_set.lower_bound(Control(idx.era, idx.msec)); + ControlSet::iterator j = _timer_set.upper_bound(Control(idx.era, idx.msec)); + + for (; i != j; i++) + { + const Control & ctrl = (*i); + + if ((idx.value && !(ctrl._value & idx.value))) + continue; + + if (((idx.func && ctrl._func == idx.func) || !idx.func) && ((idx.data && ctrl._data == idx.data) || !idx.data)) + { + if (_timer_set.begin() == i) + _condition.signal(); + + _timer_set.erase(i); + + ret = true; + break; + } + } + + idx.valid = false; + } + + return ret; +} + +bool TimerTraits::traits_del (TimerTraits::Index & idx) +{ + _mutex.lock(); + + bool ret = traits_del_unlocked(idx); + + _mutex.unlock(); + + return ret; +} + +bool TimerTraits::traits_del (const void * func, const void * data, unsigned int value) +{ + bool ret = false; + + _mutex.lock(); + + for (ControlSet::iterator i = _timer_set.begin(); i != _timer_set.end(); i++) + { + const Control & ctrl = (*i); + + if ((value && !(ctrl._value & value))) + continue; + + if (((func && ctrl._func == func) || !func) && ((data && ctrl._data == data) || !data)) + { + if (_timer_set.begin() == i) + _condition.signal(); + + _timer_set.erase(i); + + ret = true; + break; + } + } + + _mutex.unlock(); + + return ret; +} diff --git a/src/mod/endpoints/mod_khomp/commons/timer.hpp b/src/mod/endpoints/mod_khomp/commons/timer.hpp new file mode 100644 index 0000000000..382efa1645 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/timer.hpp @@ -0,0 +1,224 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32) +#include +#else +#include +#endif + +#include + +#include +#include +#include +#include + +#ifndef _TIMER_HPP_ +#define _TIMER_HPP_ + +struct TimerTraits +{ + typedef bool (* CallbackFuncType)(const void * volatile); + typedef const void * CallbackDataType; + + TimerTraits(); + + virtual ~TimerTraits() {}; + + protected: + + /* pre-declaration, used below */ + struct ControlCompare; + + struct Control + { + Control(unsigned int age, unsigned int msecs, const void * func = 0, const void * data = 0, unsigned int value = 0) + : _age(age), _msecs(msecs), _func(func), _data(data), _value(value) {} + + unsigned int _age; + + unsigned int _msecs; + + const void * _func; + const void * _data; + + unsigned int _value; + }; + + struct ControlCompare + { + bool operator()(const Control & c1, const Control & c2) const + { + return (c1._age < c2._age ? true : c1._msecs < c2._msecs); + } + }; + + typedef std::multiset < Control, ControlCompare > ControlSet; + + public: + struct Index + { + Index(): era(0), msec(0), valid(false) {}; + + Index(unsigned int _era, unsigned int _msec, unsigned int _delta, const void * _func, const void * _data, unsigned int _value) + : era(_era), msec(_msec), delta(_delta), func(_func), data(_data), value(_value), valid(true) {}; + + unsigned int era; + unsigned int msec; + + unsigned int delta; + + const void * func; + const void * data; + + unsigned int value; + + bool valid; + + void reset(void) { era = 0; msec = 0; valid = false; }; + }; + + /* timer add/remove functions */ + Index traits_add (unsigned int msecs, const void * func, const void * data = 0, unsigned int value = 0); + + bool traits_restart (Index & idx, bool force); + + bool traits_del (Index & idx); + bool traits_del (const void * func, const void * data = 0, unsigned int value = 0); + + /* timer start/stop functions */ + bool start(void); + bool stop(void); + + protected: + Index traits_add_unlocked (unsigned int msecs, const void * func, const void * data, unsigned int value); + + bool traits_del_unlocked (Index & idx); + + protected: + void execute(ControlSet::iterator, const Control &); + + void loop(void); + + struct loop_thread + { + loop_thread(TimerTraits *timer) : _timer(timer) {}; + + int operator()(void); + + protected: + TimerTraits * _timer; + }; + + unsigned int tick(); + + /* variables */ + + SavedCondition _condition; + + SimpleLock _mutex; + Thread * _thread; + bool _purify; + + ControlSet _timer_set; + + unsigned int _last_tick; + unsigned int _age_count; + + SavedCondition _finalized; + bool _shutdown; +}; + +template < typename F, typename D > +struct TimerTemplate: NEW_REFCOUNTER(TimerTemplate< F, D >) +{ + typedef TimerTraits::Index Index; + typedef TimerTraits::Control Control; + + TimerTemplate() + : _timer(new TimerTraits()) + {}; + + TimerTemplate(const TimerTemplate< F, D > & o) + : INC_REFCOUNTER(o, TimerTemplate< F, D >), + _timer(o._timer) + {}; + + void unreference(void) + { + if (_timer) + delete _timer; + }; + + bool start() { return _timer->start(); } + bool stop() { return _timer->stop(); } + + inline Index add(unsigned int msecs, F * func, D data = 0, unsigned int value = 0) + { + return _timer->traits_add(msecs, (const void *)func, (void *)(data), value); + } + + inline bool restart(Index & idx, bool force = false) + { + return _timer->traits_restart(idx, force); + } + + inline bool del(Index & idx) + { + return _timer->traits_del(idx); + } + + inline bool del(F * func, D data, unsigned int value = 0) + { + return _timer->traits_del((const void *)func, (void *)(data), value); + } + + inline bool del(unsigned int value) + { + return _timer->traits_del((const void *)0, (void *)0, value); + } + + protected: + TimerTraits * _timer; +}; + +#endif /* _TIMER_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/types.hpp b/src/mod/endpoints/mod_khomp/commons/types.hpp new file mode 100644 index 0000000000..adbd8abe36 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/types.hpp @@ -0,0 +1,81 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef _TYPES_HPP_ +#define _TYPES_HPP_ + +/*** Used for conditional compilation based on K3L version ***/ + +#define K3L_AT_LEAST(major,minor,build) \ + (((k3lApiMajorVersion == major) && ((k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build)) || \ + ((k3lApiMajorVersion == major) && (k3lApiMinorVersion > minor))) || \ + (k3lApiMajorVersion > major)) + +#define K3L_EXACT(major,minor,build) \ + ((k3lApiMajorVersion == major) && (k3lApiMinorVersion == minor) && (k3lApiBuildVersion >= build)) + +/*** Used for checking information on classes and stuff.. ***/ + +template< typename T > +class IsClass +{ + protected: + template< typename X > static char ( &A( void(X::*)() ) )[1]; + template< typename X > static char ( &A( X ) )[2]; + public: + static bool const Result = sizeof( A< T >(0) ) == 1; +}; + +/*** Used for template metaprogramming ***/ + +template < bool Value, typename Then, typename Else > +struct Select +{ + typedef Then Result; +}; + +template < typename Then, typename Else > +struct Select < false, Then, Else > +{ + typedef Else Result; +}; + +#endif /* _TYPES_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/commons/variant.hpp b/src/mod/endpoints/mod_khomp/commons/variant.hpp new file mode 100644 index 0000000000..410a770a6e --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/variant.hpp @@ -0,0 +1,127 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include + +#include + +#ifndef _VARIANT_H_ +#define _VARIANT_H_ + +/* this is internal, should not be used by the user */ +struct NoArgumentDefined {}; + +template < typename UserReturnType, typename UserArgumentType = NoArgumentDefined > +struct VariantBaseType +{ + typedef UserReturnType ReturnType; + typedef UserArgumentType ArgumentType; + + virtual ~VariantBaseType() {}; + + virtual int which() = 0; + + virtual ReturnType visit(void) { return ReturnType(); }; + virtual ReturnType visit(ArgumentType) { return ReturnType(); }; +}; + +template < typename BaseType = VariantBaseType < void > > +struct Variant: NEW_REFCOUNTER(Variant < BaseType >) +{ + typedef typename BaseType::ReturnType ReturnType; + typedef typename BaseType::ArgumentType ArgumentType; + + struct InvalidType {}; + + Variant(BaseType * value, bool is_owner = false) + : _value(value), _is_owner(is_owner) {}; + + Variant(const Variant & v) + : INC_REFCOUNTER(v, Variant < BaseType >), + _value(v._value), _is_owner(v._is_owner) {}; + + virtual ~Variant() {}; + + void unreference() + { + if (_is_owner && _value) + { + delete _value; + _value = 0; + } + }; + + template < typename ValueType > + ValueType & get(void) + { + try + { + ValueType & ret = dynamic_cast < ValueType & > (*_value); + return ret; + } + catch (std::bad_cast & e) + { + throw InvalidType(); + } + }; + + int which() + { + return _value->which(); + } + + ReturnType visit(void) + { + return _value->visit(); + } + + ReturnType visit(ArgumentType arg) + { + return _value->visit(arg); + } + + protected: + BaseType * _value; + bool _is_owner; +}; + +#endif /* _VARIANT_H_ */ + diff --git a/src/mod/endpoints/mod_khomp/commons/verbose.cpp b/src/mod/endpoints/mod_khomp/commons/verbose.cpp new file mode 100644 index 0000000000..182d159ca1 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/verbose.cpp @@ -0,0 +1,3188 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include + +#define PRESENTATION_CHECK_RETURN(fmt, txtexact, txthuman) \ + { \ + switch(fmt) \ + { \ + case EXACT: return txtexact; \ + case HUMAN: return txthuman; \ + } \ + return txtexact; \ + } + +/********************************************/ + +std::string Verbose::channelStatus(int32 dev, int32 obj, int32 cs, Verbose::Presentation fmt) +{ + try + { + K3L_CHANNEL_CONFIG & config = _api.channel_config(dev, obj); + return Verbose::channelStatus(config.Signaling, cs, fmt); + } + catch (...) + { + return presentation(fmt, "", "Unknown"); + } +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::event(int32 obj, K3L_EVENT *ev, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::event(int32 obj, K3L_EVENT *ev, Verbose::Presentation fmt) +#endif +{ + try + { + K3L_CHANNEL_CONFIG & config = _api.channel_config(ev->DeviceId, obj); +#if K3L_AT_LEAST(2,0,0) + return Verbose::event(config.Signaling, obj, ev, r2_country, fmt); +#else + return Verbose::event(config.Signaling, obj, ev, fmt); +#endif + } + catch (...) + { +#if K3L_AT_LEAST(2,0,0) + return Verbose::event(ksigInactive, obj, ev, r2_country, fmt); +#else + return Verbose::event(ksigInactive, obj, ev, fmt); +#endif + } +} + +/********************************************/ + +std::string Verbose::echoLocation(KEchoLocation ec, Verbose::Presentation fmt) +{ + switch (ec) + { +#if K3L_AT_LEAST(1,5,4) + case kelNetwork: return presentation(fmt, "kelNetwork", "Network"); +#else + case kelE1: return presentation(fmt, "kelE1", "Network"); +#endif + case kelCtBus: return presentation(fmt, "kelCtBus", "CT-Bus"); + }; + + return presentation(fmt, "", "Unknown"); +}; + +std::string Verbose::echoCancellerConfig(KEchoCancellerConfig ec, Verbose::Presentation fmt) +{ + switch (ec) + { + case keccNotPresent: return presentation(fmt, "keccNotPresent", "Not Present"); + case keccOneSingleBank: return presentation(fmt, "keccOneSingleBank", "One, Single Bank"); + case keccOneDoubleBank: return presentation(fmt, "keccOneDoubleBank", "One, Double Bank"); + case keccTwoSingleBank: return presentation(fmt, "keccTwoSingleBank", "Two, Single Bank"); + case keccTwoDoubleBank: return presentation(fmt, "keccTwoDoubleBank", "Two, Double Bank"); + case keccFail: return presentation(fmt, "keccFail", "Failure"); + }; + + return presentation(fmt, "", "Unknown"); +}; + +// TODO: internal_deviceType / internal_deviceModel + +std::string Verbose::deviceName(KDeviceType dt, int32 model, Verbose::Presentation fmt) +{ + try + { + std::string value; + + value += internal_deviceType(dt); + value += "-"; + value += internal_deviceModel(dt, model); + + return value; + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[type/model='%d/%d']") % (int)dt % (int)model), + STG(FMT("Unknown device type/model (%d/%d)") % (int)dt % (int)model)); + } +} + +std::string Verbose::deviceType(KDeviceType dt, Verbose::Presentation fmt) +{ + try + { + return internal_deviceType(dt); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[type='%d']") % (int)dt), + STG(FMT("Unknown device type (%d)") % (int)dt)); + } +} + +std::string Verbose::internal_deviceType(KDeviceType dt) +{ + switch (dt) + { + case kdtE1: return "K2E1"; + +#if K3L_AT_LEAST(1,6,0) + case kdtFXO: return "KFXO"; +#else + case kdtFX: return "KFXO"; +#endif + + case kdtConf: return "KCONF"; + case kdtPR: return "KPR"; + case kdtE1GW: return "KE1GW"; + +#if K3L_AT_LEAST(1,6,0) + case kdtFXOVoIP: return "KFXVoIP"; +#else + case kdtFXVoIP: return "KFXVoIP"; +#endif + +#if K3L_AT_LEAST(1,5,0) + case kdtE1IP: return "K2E1"; +#endif +#if K3L_AT_LEAST(1,5,1) + case kdtE1Spx: return "K2E1"; + case kdtGWIP: return "KGWIP"; +#endif + +#if K3L_AT_LEAST(1,6,0) + case kdtFXS: return "KFXS"; + case kdtFXSSpx: return "KFXS"; + case kdtGSM: return "KGSM"; + case kdtGSMSpx: return "KGSM"; +#endif + +#if K3L_AT_LEAST(2,1,0) + case kdtGSMUSB: return "KGSMUSB"; + case kdtGSMUSBSpx: return "KGSMUSB"; + + case kdtE1FXSSpx: return "KE1FXS"; + case kdtDevTypeCount: return "DevTypeCount"; +#endif + +#if K3L_EXACT(2,1,0) + case kdtReserved1: return "Reserved1"; +#endif + +#if K3L_AT_LEAST(2,2,0) + case kdtE1AdHoc: return "KE1AdHoc"; +#endif + } + + throw internal_not_found(); +} + +std::string Verbose::deviceModel(KDeviceType dt, int32 model, Verbose::Presentation fmt) +{ + try + { + return internal_deviceModel(dt, model); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[model='%d']") % (int)model), + STG(FMT("Unknown device model (%d)") % (int)model)); + } +} + +std::string Verbose::internal_deviceModel(KDeviceType dt, int32 model) +{ + switch (dt) + { + case kdtE1: + switch ((KE1DeviceModel)model) + { + case kdmE1600: return "600"; + case kdmE1600E: return "600E"; +#if K3L_AT_LEAST(2,0,0) + case kdmE1600EX: return "600EX"; +#endif + } + throw internal_not_found(); + +#if K3L_AT_LEAST(1,6,0) + case kdtFXO: + switch ((KFXODeviceModel)model) +#else + case kdtFX: + switch ((KFXDeviceModel)model) +#endif + { +#if K3L_AT_LEAST(1,6,0) + case kdmFXO80: return "80"; + case kdmFXOHI: return "HI"; + case kdmFXO160HI: return "160HI"; +#if K3L_AT_LEAST(2,1,0) + case kdmFXO240HI: return "240HI"; +#endif +#else + case kdmFXO80: return "80"; +#endif + } + + throw internal_not_found(); + + case kdtConf: + switch ((KConfDeviceModel)model) + { + case kdmConf240: return "240"; + case kdmConf120: return "120"; +#if K3L_AT_LEAST(2,0,0) + case kdmConf240EX: return "240EX"; + case kdmConf120EX: return "120EX"; +#endif + } + + throw internal_not_found(); + + case kdtPR: + switch ((KPRDeviceModel)model) + { +#if K3L_AT_LEAST(1,6,0) + case kdmPR300v1: return "300v1"; + case kdmPR300SpxBased: return "300S"; +#if K3L_AT_LEAST(2,0,0) + case kdmPR300EX: return "300EX"; +#endif + case kdmPR300: return "300"; + } +#endif + throw internal_not_found(); + +#if K3L_AT_LEAST(1,4,0) + case kdtE1GW: + switch ((KE1GWDeviceModel)model) + { +#if K3L_AT_LEAST(1,6,0) + case kdmE1GW640: return "640"; +#if K3L_AT_LEAST(2,0,0) + case kdmE1GW640EX: return "640EX"; +#endif +#else + case kdmE1600V: return "600V"; + case kdmE1600EV: return "600EV"; +#endif + } + + throw internal_not_found(); +#endif + +#if K3L_AT_LEAST(1,6,0) + case kdtFXOVoIP: + switch ((KFXOVoIPDeviceModel)model) + { + case kdmFXGW180: return "180"; + } + + throw internal_not_found(); + +#elif K3L_AT_LEAST(1,4,0) + case kdtFXVoIP: + switch ((KFXVoIPDeviceModel)model) + { + case kdmFXO80V: return "80V"; + } + + throw internal_not_found(); +#endif + +#if K3L_AT_LEAST(1,5,0) + case kdtE1IP: + switch ((KE1IPDeviceModel)model) + { +#if K3L_AT_LEAST(1,6,0) + case kdmE1IP: return "E1IP"; +#if K3L_AT_LEAST(2,0,0) + case kdmE1IPEX: return "E1IPEX"; +#endif +#else + case kdmE1600EG: return "600EG"; +#endif + } + + throw internal_not_found(); +#endif + +#if K3L_AT_LEAST(1,5,1) + case kdtE1Spx: + switch ((KE1SpxDeviceModel)model) + { + case kdmE1Spx: return "SPX"; + case kdm2E1Based: return "SPX-2E1"; +#if K3L_AT_LEAST(2,0,0) + case kdmE1SpxEX: return "SPXEX"; +#endif + } + throw internal_not_found(); + + case kdtGWIP: + switch ((KGWIPDeviceModel)model) + { +#if K3L_AT_LEAST(1,6,0) + case kdmGWIP: return "GWIP"; +#if K3L_AT_LEAST(2,0,0) + case kdmGWIPEX: return "GWIPEX"; +#endif +#else + case kdmGW600G: return "600G"; + case kdmGW600EG: return "600EG"; +#endif + } + + throw internal_not_found(); +#endif + +#if K3L_AT_LEAST(1,6,0) + case kdtFXS: + switch ((KFXSDeviceModel)model) + { + case kdmFXS300: return "300"; +#if K3L_AT_LEAST(2,0,0) + case kdmFXS300EX: return "300EX"; +#endif + } + + throw internal_not_found(); + + case kdtFXSSpx: + switch ((KFXSSpxDeviceModel)model) + { + case kdmFXSSpx300: return "SPX"; + case kdmFXSSpx2E1Based: return "SPX-2E1"; +#if K3L_AT_LEAST(2,0,0) + case kdmFXSSpx300EX: return "SPXEX"; +#endif + } + + throw internal_not_found(); + + case kdtGSM: + switch ((KGSMDeviceModel)model) + { + case kdmGSM: return "40"; +#if K3L_AT_LEAST(2,0,0) + case kdmGSMEX: return "40EX"; +#endif + } + + throw internal_not_found(); + + case kdtGSMSpx: + switch ((KGSMSpxDeviceModel)model) + { + case kdmGSMSpx: return "SPX"; +#if K3L_AT_LEAST(2,0,0) + case kdmGSMSpxEX: return "SPXEX"; +#endif + } + + throw internal_not_found(); + +#if K3L_AT_LEAST(2,1,0) + case kdtGSMUSB: + switch ((KGSMUSBDeviceModel)model) + { + case kdmGSMUSB: return "20"; + } + + throw internal_not_found(); + + case kdtGSMUSBSpx: + switch ((KGSMUSBSpxDeviceModel)model) + { + case kdmGSMUSBSpx: return "SPX"; + } + + throw internal_not_found(); + + case kdtE1FXSSpx: + switch ((KGSMSpxDeviceModel)model) + { + case kdmE1FXSSpx: return "SPX"; + case kdmE1FXSSpxEX: return "SPXEX"; + } + + throw internal_not_found(); +#if K3L_AT_LEAST(2,2,0) + case kdtE1AdHoc: + switch((KE1AdHocModel)model) + { + case kdmE1AdHoc100: return "E1AdHoc100"; + case kdmE1AdHoc100E: return "E1AdHoc100E"; + case kdmE1AdHoc240: return "E1AdHoc240"; + case kdmE1AdHoc240E: return "E1AdHoc240E"; + case kdmE1AdHoc400: return "E1AdHoc240"; + case kdmE1AdHoc400E: return "E1AdHoc240E"; + } + throw internal_not_found(); +#endif + +#if K3L_EXACT(2,1,0) + case kdtReserved1: +#endif + case kdtDevTypeCount: + throw internal_not_found(); + +#endif +#endif + } + + throw internal_not_found(); +} + +std::string Verbose::signaling(KSignaling sig, Verbose::Presentation fmt) +{ + switch (sig) + { + case ksigInactive: return presentation(fmt, "ksigInactive", "Inactive"); + case ksigAnalog: return presentation(fmt, "ksigAnalog", "FXO (analog)"); + case ksigContinuousEM: return presentation(fmt, "ksigContinuousEM", "E+M Continuous"); + case ksigPulsedEM: return presentation(fmt, "ksigPulsedEM", "E+M PUlsed"); + case ksigOpenCAS: return presentation(fmt, "ksigOpenCAS", "Open CAS"); + case ksigOpenR2: return presentation(fmt, "ksigOpenR2", "Open R2"); + case ksigR2Digital: return presentation(fmt, "ksigR2Digital", "R2/MFC"); + case ksigUserR2Digital: return presentation(fmt, "ksigUserR2Digital", "R2/Other"); +#if K3L_AT_LEAST(1,4,0) + case ksigSIP: return presentation(fmt, "ksigSIP", "SIP"); +#endif + +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: return presentation(fmt, "ksigOpenCCS", "Open CCS"); + case ksigPRI_EndPoint: return presentation(fmt, "ksigPRI_EndPoint", "ISDN Endpoint"); + case ksigPRI_Network: return presentation(fmt, "ksigPRI_Network", "ISDN Network"); + case ksigPRI_Passive: return presentation(fmt, "ksigPRI_Passive", "ISDN Passive"); +#endif +#if K3L_AT_LEAST(1,5,3) + case ksigLineSide: return presentation(fmt, "ksigLineSide", "Line Side"); +#endif +#if K3L_AT_LEAST(1,6,0) + case ksigAnalogTerminal: return presentation(fmt, "ksigAnalogTerminal", "FXS (analog)"); + case ksigGSM: return presentation(fmt, "ksigGSM", "GSM"); + case ksigCAS_EL7: return presentation(fmt, "ksigCAS_EL7", "CAS EL7"); + case ksigE1LC: return presentation(fmt, "ksigE1LC", "E1 LC"); +#endif +#if K3L_AT_LEAST(2,1,0) + case ksigISUP: return presentation(fmt, "ksigISUP", "ISUP"); +#endif +#if K3L_EXACT(2,1,0) + case ksigFax: return presentation(fmt, "ksigFax", "Fax"); +#endif +#if K3L_AT_LEAST(2,2,0) + case ksigISUPPassive: return presentation(fmt, "ksigISUPPassive", "ISUP Passive"); +#endif + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KSignaling='%d']") % (int)sig), + STG(FMT("Unknown signaling (%d)") % (int)sig)); +} + +std::string Verbose::systemObject(KSystemObject so, Verbose::Presentation fmt) +{ + switch (so) + { + case ksoLink: return presentation(fmt, "ksoLink", "Link"); + case ksoLinkMon: return presentation(fmt, "ksoLinkMon", "Link Monitor"); + case ksoChannel: return presentation(fmt, "ksoChannel", "Channel"); +#if K3L_AT_LEAST(2,1,0) + case ksoGsmChannel:return presentation(fmt, "ksoGsmChannel","GsmChannel"); +#endif + case ksoH100: return presentation(fmt, "ksoH100", "H.100"); + case ksoFirmware: return presentation(fmt, "ksoFirmware", "Firmware"); + case ksoDevice: return presentation(fmt, "ksoDevice", "Device"); + case ksoAPI: return presentation(fmt, "ksoAPI", "Software Layer"); + } + + return presentation(fmt, + STG(FMT("[KSystemObject='%d']") % (int)so), + STG(FMT("Unknown object (%d)") % (int)so)); +} + +std::string Verbose::mixerTone(KMixerTone mt, Verbose::Presentation fmt) +{ + switch (mt) + { + case kmtSilence: return presentation(fmt, "kmtSilence", "Silence"); + case kmtDial: return presentation(fmt, "kmtDial", "Dialtone begin"); + case kmtEndOf425: return presentation(fmt, "kmtEndOf425", "Dialtone end"); + case kmtBusy: return presentation(fmt, "kmtBusy", "Busy"); + case kmtFax: return presentation(fmt, "kmtFax", "Fax"); + case kmtVoice: return presentation(fmt, "kmtVoice", "Voice"); +#if K3L_AT_LEAST(1,5,0) + case kmtCollect: return presentation(fmt, "kmtCollect", "Collect Call"); +#endif +#if K3L_AT_LEAST(1,5,1) + case kmtEndOfDtmf: return presentation(fmt, "kmtEndOfDtmf", "DTMF end"); +#endif + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KMixerTone='%d']") % (int)mt), + STG(FMT("Unknonwn tone (%d)") % (int)mt)); +} + +std::string Verbose::mixerSource(KMixerSource ms, Verbose::Presentation fmt) +{ + switch (ms) + { + case kmsChannel: return presentation(fmt, "kmsChannel", "Channel"); + case kmsPlay: return presentation(fmt, "kmsPlay", "Player"); + case kmsGenerator: return presentation(fmt, "kmsGenerator", "Generator"); + case kmsCTbus: return presentation(fmt, "kmsCTbus", "CT-bus"); +#if (K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(1,6,0)) + case kmsVoIP: return presentation(fmt, "kmsVoIP", "VoIP"); +#endif +#if K3L_AT_LEAST(1,6,0) + case kmsNoDelayChannel: return presentation(fmt, "kmsNoDelayChannel", "No delay channel"); +#endif + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KMixerSource='%d']") % (int)ms), + STG(FMT("Unknonwn source (%d)") % (int)ms)); +} + +std::string Verbose::channelFeatures(int32 flags, Verbose::Presentation fmt) +{ + if (0x00 != flags) + { + Strings::Merger strs; + + if (kcfDtmfSuppression & flags) strs.add(presentation(fmt, "DtmfSuppression", "DTMF Suppression")); + if (kcfCallProgress & flags) strs.add(presentation(fmt, "CallProgress", "Call Progress")); + if (kcfPulseDetection & flags) strs.add(presentation(fmt, "PulseDetection", "Pulse Detection")); + if (kcfAudioNotification & flags) strs.add(presentation(fmt, "AudioNotification", "Audio Notification")); + if (kcfEchoCanceller & flags) strs.add(presentation(fmt, "EchoCanceller", "Echo Canceller")); + if (kcfAutoGainControl & flags) strs.add(presentation(fmt, "AutoGainControl", "Input AGC")); + if (kcfHighImpEvents & flags) strs.add(presentation(fmt, "HighImpEvents", "High Impedance Events")); +#if K3L_AT_LEAST(1,6,0) + if (kcfCallAnswerInfo & flags) strs.add(presentation(fmt, "CallAnswerInfo", "Call Answer Info")); +#if !K3L_AT_LEAST(2,2,0) + if (kcfOutputVolume & flags) strs.add(presentation(fmt, "OutputVolume", "Output Volume")); +#endif + if (kcfPlayerAGC & flags) strs.add(presentation(fmt, "PlayerAGC", "Player AGC")); +#endif + + return presentation(fmt, + STG(FMT("kcf{%s}") % strs.merge(",")), + STG(FMT("%s") % strs.merge(", "))); + }; + + PRESENTATION_CHECK_RETURN(fmt, "", "No features"); +} + +std::string Verbose::seizeFail(KSeizeFail sf, Verbose::Presentation fmt) +{ + switch (sf) + { + case ksfChannelLocked: return presentation(fmt, "ksfChannelLocked", "Channel Locked"); + case ksfChannelBusy: return presentation(fmt, "ksfChannelBusy", "Channel Busy"); + case ksfIncomingChannel: return presentation(fmt, "ksfIncomingChannel", "Incoming Channel"); + case ksfDoubleSeizure: return presentation(fmt, "ksfDoubleSeizure", "Double Seizure"); + case ksfCongestion: return presentation(fmt, "ksfCongestion", "Congestion"); + case ksfNoDialTone: return presentation(fmt, "ksfNoDialTone", "No Dial Tone"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KSeizeFail='%d']") % (int)sf), + STG(FMT("Unknown seize fail (%d)") % (int)sf)); +} + +#if K3L_AT_LEAST(1,5,0) +std::string Verbose::internal_sipFailures(KSIP_Failures code, Verbose::Presentation fmt) +{ + switch (code) + { +#if K3L_AT_LEAST(1,6,0) + case kveResponse_200_OK_Success: return presentation(fmt, "kveResponse_200_OK_Success", "200 OK"); +#endif + case kveRedirection_300_MultipleChoices: return presentation(fmt, "kveRedirection_300_MultipleChoices", "300 Multiple Choices"); + case kveRedirection_301_MovedPermanently: return presentation(fmt, "kveRedirection_301_MovedPermanently", "301 Moved Permanently"); + case kveRedirection_302_MovedTemporarily: return presentation(fmt, "kveRedirection_302_MovedTemporarily", "302 Moved Temporarily"); + case kveRedirection_305_UseProxy: return presentation(fmt, "kveRedirection_305_UseProxy", "305 Use Proxy"); + case kveRedirection_380_AlternativeService: return presentation(fmt, "kveRedirection_380_AlternativeService", "380 Alternate Service"); + case kveFailure_400_BadRequest: return presentation(fmt, "kveFailure_400_BadRequest", "400 Bad Request"); + case kveFailure_401_Unauthorized: return presentation(fmt, "kveFailure_401_Unauthorized", "401 Unauthorized"); + case kveFailure_402_PaymentRequired: return presentation(fmt, "kveFailure_402_PaymentRequired", "402 Payment Required"); + case kveFailure_403_Forbidden: return presentation(fmt, "kveFailure_403_Forbidden", "403 Forbidden"); + case kveFailure_404_NotFound: return presentation(fmt, "kveFailure_404_NotFound", "404 Not Found"); + case kveFailure_405_MethodNotAllowed: return presentation(fmt, "kveFailure_405_MethodNotAllowed", "405 Method Not Allowed"); + case kveFailure_406_NotAcceptable: return presentation(fmt, "kveFailure_406_NotAcceptable", "406 Not Acceptable"); + case kveFailure_407_ProxyAuthenticationRequired: return presentation(fmt, "kveFailure_407_ProxyAuthenticationRequired", "407 Proxy Authentication Required"); + case kveFailure_408_RequestTimeout: return presentation(fmt, "kveFailure_408_RequestTimeout", "408 Request Timeout"); + case kveFailure_410_Gone: return presentation(fmt, "kveFailure_410_Gone", "410 Gone"); + case kveFailure_413_RequestEntityTooLarge: return presentation(fmt, "kveFailure_413_RequestEntityTooLarge", "413 Request Entity Too Large"); + case kveFailure_414_RequestURI_TooLong: return presentation(fmt, "kveFailure_414_RequestURI_TooLong", "414 Request URI Too Long"); + case kveFailure_415_UnsupportedMediaType: return presentation(fmt, "kveFailure_415_UnsupportedMediaType", "415 Unsupported Media Type"); + case kveFailure_416_UnsupportedURI_Scheme: return presentation(fmt, "kveFailure_416_UnsupportedURI_Scheme", "416 Unsupported URI Scheme"); + case kveFailure_420_BadExtension: return presentation(fmt, "kveFailure_420_BadExtension", "420 Bad Extension"); + case kveFailure_421_ExtensionRequired: return presentation(fmt, "kveFailure_421_ExtensionRequired", "421 Extension Required"); + case kveFailure_423_IntervalTooBrief: return presentation(fmt, "kveFailure_423_IntervalTooBrief", "423 Internal Too Brief"); + case kveFailure_480_TemporarilyUnavailable: return presentation(fmt, "kveFailure_480_TemporarilyUnavailable", "480 Temporarily Unavailable"); + case kveFailure_481_CallDoesNotExist: return presentation(fmt, "kveFailure_481_CallDoesNotExist", "481 Call Does Not Exist"); + case kveFailure_482_LoopDetected: return presentation(fmt, "kveFailure_482_LoopDetected", "482 Loop Detected"); + case kveFailure_483_TooManyHops: return presentation(fmt, "kveFailure_483_TooManyHops", "483 Too Many Hops"); + case kveFailure_484_AddressIncomplete: return presentation(fmt, "kveFailure_484_AddressIncomplete", "484 Address Incomplete"); + case kveFailure_485_Ambiguous: return presentation(fmt, "kveFailure_485_Ambiguous", "485 Ambiguous"); + case kveFailure_486_BusyHere: return presentation(fmt, "kveFailure_486_BusyHere", "486 Busy Here"); + case kveFailure_487_RequestTerminated: return presentation(fmt, "kveFailure_487_RequestTerminated", "487 Request Terminated"); + case kveFailure_488_NotAcceptableHere: return presentation(fmt, "kveFailure_488_NotAcceptableHere", "488 Not Acceptable Here"); + case kveFailure_491_RequestPending: return presentation(fmt, "kveFailure_491_RequestPending", "491 Request Pending"); + case kveFailure_493_Undecipherable: return presentation(fmt, "kveFailure_493_Undecipherable", "493 Undecipherable"); + case kveServer_500_InternalError: return presentation(fmt, "kveServer_500_InternalError", "500 Internal Error"); + case kveServer_501_NotImplemented: return presentation(fmt, "kveServer_501_NotImplemented", "501 Not Implemented"); + case kveServer_502_BadGateway: return presentation(fmt, "kveServer_502_BadGateway", "502 Bad Gateway"); + case kveServer_503_ServiceUnavailable: return presentation(fmt, "kveServer_503_ServiceUnavailable", "503 Service Unavailable"); + case kveServer_504_TimeOut: return presentation(fmt, "kveServer_504_TimeOut", "504 Timed Out"); + case kveServer_505_VersionNotSupported: return presentation(fmt, "kveServer_505_VersionNotSupported", "505 Version Not Supported"); + case kveServer_513_MessageTooLarge: return presentation(fmt, "kveServer_513_MessageTooLarge", "513 Message Too Large"); + case kveGlobalFailure_600_BusyEverywhere: return presentation(fmt, "kveGlobalFailure_600_BusyEverywhere", "600 Busy Everywhere"); + case kveGlobalFailure_603_Decline: return presentation(fmt, "kveGlobalFailure_603_Decline", "603 Decline"); + case kveGlobalFailure_604_DoesNotExistAnywhere: return presentation(fmt, "kveGlobalFailure_604_DoesNotExistAnywhere", "604 Does Not Exist Anywhere"); + case kveGlobalFailure_606_NotAcceptable: return presentation(fmt, "kveGlobalFailure_606_NotAcceptable", "606 Not Acceptable"); + } + + throw internal_not_found(); +} + +std::string Verbose::sipFailures(KSIP_Failures code, Verbose::Presentation fmt) +{ + try + { + return internal_sipFailures(code, fmt); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KSIP_Failures='%d']") % (int)code), + STG(FMT("Unknown SIP failure (%d)") % (int)code)); + } +} + +#endif + +#if K3L_AT_LEAST(1,5,1) +std::string Verbose::internal_isdnCause(KQ931Cause code, Verbose::Presentation fmt) +{ + switch (code) + { + case kq931cNone: return presentation(fmt, "kq931cNone", "None"); + case kq931cUnallocatedNumber: return presentation(fmt, "kq931cUnallocatedNumber", "Unallocated number"); + case kq931cNoRouteToTransitNet: return presentation(fmt, "kq931cNoRouteToTransitNet", "No route to transmit to network"); + case kq931cNoRouteToDest: return presentation(fmt, "kq931cNoRouteToDest", "No route to destination"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cSendSpecialInfoTone: return presentation(fmt, "kq931cSendSpecialInfoTone", "Send special information tone"); + case kq931cMisdialedTrunkPrefix: return presentation(fmt, "kq931cMisdialedTrunkPrefix", "Misdialed trunk prefix"); +#endif + case kq931cChannelUnacceptable: return presentation(fmt, "kq931cChannelUnacceptable", "Channel unacceptable"); + case kq931cCallAwarded: return presentation(fmt, "kq931cCallAwarded", "Call awarded"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cPreemption: return presentation(fmt, "kq931cPreemption", "Preemption"); + case kq931cPreemptionCircuitReuse: return presentation(fmt, "kq931cPreemptionCircuitReuse", "Preemption circuit reuse"); + case kq931cQoR_PortedNumber: return presentation(fmt, "kq931cQoR_PortedNumber", "QoR ported number"); +#endif + case kq931cNormalCallClear: return presentation(fmt, "kq931cNormalCallClear", "Normal call clear"); + case kq931cUserBusy: return presentation(fmt, "kq931cUserBusy", "User busy"); + case kq931cNoUserResponding: return presentation(fmt, "kq931cNoUserResponding", "No user responding"); + case kq931cNoAnswerFromUser: return presentation(fmt, "kq931cNoAnswerFromUser", "No answer from user"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cSubscriberAbsent: return presentation(fmt, "kq931cSubscriberAbsent", "Subscriber absent"); +#endif + case kq931cCallRejected: return presentation(fmt, "kq931cCallRejected", "Call rejected"); + case kq931cNumberChanged: return presentation(fmt, "kq931cNumberChanged", "Number changed"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cRedirectionToNewDest: return presentation(fmt, "kq931cRedirectionToNewDest", "Redirection to new destination"); + case kq931cCallRejectedFeatureDest: return presentation(fmt, "kq931cCallRejectedFeatureDest", "Call rejected feature destination"); + case kq931cExchangeRoutingError: return presentation(fmt, "kq931cExchangeRoutingError", "Exchange routing error"); +#endif + case kq931cNonSelectedUserClear: return presentation(fmt, "kq931cNonSelectedUserClear", "Non selected user clear"); + case kq931cDestinationOutOfOrder: return presentation(fmt, "kq931cDestinationOutOfOrder", "Destination out of order"); + case kq931cInvalidNumberFormat: return presentation(fmt, "kq931cInvalidNumberFormat", "Invalid number format"); + case kq931cFacilityRejected: return presentation(fmt, "kq931cFacilityRejected", "Facility rejected"); + case kq931cRespStatusEnquiry: return presentation(fmt, "kq931cRespStatusEnquiry", "Response status enquiry"); + case kq931cNormalUnspecified: return presentation(fmt, "kq931cNormalUnspecified", "Normal unespecified"); + case kq931cNoCircuitChannelAvail: return presentation(fmt, "kq931cNoCircuitChannelAvail", "No circuit channel available"); + case kq931cNetworkOutOfOrder: return presentation(fmt, "kq931cNetworkOutOfOrder", "Network out of order"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cPermanentFrameConnOutOfService: return presentation(fmt, "kq931cPermanentFrameConnOutOfService", "Permanent frame connection out of service"); + case kq931cPermanentFrameConnOperational: return presentation(fmt, "kq931cPermanentFrameConnOperational", "Permanent frame connection operational"); +#endif + case kq931cTemporaryFailure: return presentation(fmt, "kq931cTemporaryFailure", "Temporary failure"); + case kq931cSwitchCongestion: return presentation(fmt, "kq931cSwitchCongestion", "Switch congestion"); + case kq931cAccessInfoDiscarded: return presentation(fmt, "kq931cAccessInfoDiscarded", "Access information discarded"); + case kq931cRequestedChannelUnav: return presentation(fmt, "kq931cRequestedChannelUnav", "Requested channel unavailable"); + case kq931cPrecedenceCallBlocked: return presentation(fmt, "kq931cPrecedenceCallBlocked", "Precedence call blocked"); + case kq931cResourceUnavailable: return presentation(fmt, "kq931cResourceUnavailable", "Request resource unavailable"); + case kq931cQosUnavailable: return presentation(fmt, "kq931cQosUnavailable", "QoS unavailable"); + case kq931cReqFacilityNotSubsc: return presentation(fmt, "kq931cReqFacilityNotSubsc", "Request facility not subscribed"); + case kq931cOutCallsBarredWithinCUG: return presentation(fmt, "kq931cOutCallsBarredWithinCUG", "Out calls barred within UG"); + case kq931cInCallsBarredWithinCUG: return presentation(fmt, "kq931cInCallsBarredWithinCUG", "In calls barred within UG"); + case kq931cBearerCapabNotAuthor: return presentation(fmt, "kq931cBearerCapabNotAuthor", "Bearer capability not authorized"); + case kq931cBearerCapabNotAvail: return presentation(fmt, "kq931cBearerCapabNotAvail", "Bearer capability not available"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cInconsistency: return presentation(fmt, "kq931cInconsistency", "Inconsistency"); +#endif + case kq931cServiceNotAvailable: return presentation(fmt, "kq931cServiceNotAvailable", "Service not available"); + case kq931cBcNotImplemented: return presentation(fmt, "kq931cBcNotImplemented", "Bearer capability not implemented"); + case kq931cChannelTypeNotImplem: return presentation(fmt, "kq931cChannelTypeNotImplem", "Channel type not implemented"); + case kq931cReqFacilityNotImplem: return presentation(fmt, "kq931cReqFacilityNotImplem", "Request facility not implemented"); + case kq931cOnlyRestrictedBcAvail: return presentation(fmt, "kq931cOnlyRestrictedBcAvail", "Only restricted bearer capability available"); + case kq931cServiceNotImplemented: return presentation(fmt, "kq931cServiceNotImplemented", "Service not implemented"); + case kq931cInvalidCrv: return presentation(fmt, "kq931cInvalidCrv", "Invalid call reference value"); + case kq931cChannelDoesNotExist: return presentation(fmt, "kq931cChannelDoesNotExist", "Channel does not exist"); + case kq931cCallIdDoesNotExist: return presentation(fmt, "kq931cCallIdDoesNotExist", "Call identification does not exist"); + case kq931cCallIdInUse: return presentation(fmt, "kq931cCallIdInUse", "Call identification in use"); + case kq931cNoCallSuspended: return presentation(fmt, "kq931cNoCallSuspended", "No call suspended"); + case kq931cCallIdCleared: return presentation(fmt, "kq931cCallIdCleared", "Call identification cleared"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cUserNotMemberofCUG: return presentation(fmt, "kq931cUserNotMemberofCUG", "User not member of UG"); +#endif + case kq931cIncompatibleDestination: return presentation(fmt, "kq931cIncompatibleDestination", "Incompatible destination"); + case kq931cInvalidTransitNetSel: return presentation(fmt, "kq931cInvalidTransitNetSel", "Invalid transit network selected"); + case kq931cInvalidMessage: return presentation(fmt, "kq931cInvalidMessage", "Invalid message"); + case kq931cMissingMandatoryIe: return presentation(fmt, "kq931cMissingMandatoryIe", "Missing mandatory information element"); + case kq931cMsgTypeNotImplemented: return presentation(fmt, "kq931cMsgTypeNotImplemented", "Message type not implemented"); + case kq931cMsgIncompatWithState: return presentation(fmt, "kq931cMsgIncompatWithState", "Message incompatible with state"); + case kq931cIeNotImplemented: return presentation(fmt, "kq931cIeNotImplemented", "Information element not implemented"); + case kq931cInvalidIe: return presentation(fmt, "kq931cInvalidIe", "Invalid information element"); + case kq931cMsgIncompatWithState2: return presentation(fmt, "kq931cMsgIncompatWithState2", "Message incompatible with state (2)"); + case kq931cRecoveryOnTimerExpiry: return presentation(fmt, "kq931cRecoveryOnTimerExpiry", "Recovery on timer expiry"); + case kq931cProtocolError: return presentation(fmt, "kq931cProtocolError", "Protocol error"); +#if 1 /* this changed during K3L 1.6.0 development cycle... */ + case kq931cMessageWithUnrecognizedParam: return presentation(fmt, "kq931cMessageWithUnrecognizedParam", "Message with unrecognized parameters"); + case kq931cProtocolErrorUnspecified: return presentation(fmt, "kq931cProtocolErrorUnspecified", "Protocol error unspecified"); +#endif + case kq931cInterworking: return presentation(fmt, "kq931cInterworking", "Interworking"); + case kq931cCallConnected: return presentation(fmt, "kq931cCallConnected", "Call connected"); + case kq931cCallTimedOut: return presentation(fmt, "kq931cCallTimedOut", "Call timeout"); + case kq931cCallNotFound: return presentation(fmt, "kq931cCallNotFound", "Call not found"); + case kq931cCantReleaseCall: return presentation(fmt, "kq931cCantReleaseCall", "Cannot realese call"); + case kq931cNetworkFailure: return presentation(fmt, "kq931cNetworkFailure", "Network failure"); + case kq931cNetworkRestart: return presentation(fmt, "kq931cNetworkRestart", "Network restart"); + } + + throw internal_not_found(); +} + +std::string Verbose::isdnCause(KQ931Cause code, Verbose::Presentation fmt) +{ + try + { + return internal_isdnCause(code); + } + catch (internal_not_found & e) + { + return STG(FMT("[KQ931Cause='%d']") % (int)code); + } +} +#endif + +#if K3L_AT_LEAST(1,5,2) +std::string Verbose::isdnDebug(int32 flags, Verbose::Presentation fmt) +{ + if (0x00 != flags) + { + Strings::Merger strs; + + if (flags & kidfQ931) strs.add("Q931"); + if (flags & kidfLAPD) strs.add("LAPD"); + if (flags & kidfSystem) strs.add("System"); + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("kidf{%s}") % strs.merge(",")), + strs.merge(", ")); + } + + return presentation(fmt, "", "No debug active"); +} +#endif + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::internal_signGroupB(KSignGroupB group, R2CountryType country, Verbose::Presentation fmt) +#else +std::string Verbose::internal_signGroupB(KSignGroupB group, Verbose::Presentation fmt) +#endif +{ +#if K3L_AT_LEAST(2,0,0) + switch (country) + { + case R2_COUNTRY_ARG: + switch ((KSignGroupB_Argentina)group) + { + case kgbArNumberChanged: return presentation(fmt, "kgbArNumberChanged", "Number Changed"); + case kgbArBusy: return presentation(fmt, "kgbArBusy", "Busy"); + case kgbArCongestion: return presentation(fmt, "kgbArCongestion", "Congestion"); + case kgbArInvalidNumber: return presentation(fmt, "kgbArInvalidNumber", "Invalid Number"); + case kgbArLineFreeCharged: return presentation(fmt, "kgbArLineFreeCharged", "Line Free Charged"); + case kgbArLineFreeNotCharged: return presentation(fmt, "kgbArLineFreeNotCharged", "Line Free Not Charged"); + case kgbArLineOutOfOrder: return presentation(fmt, "kgbArLineOutOfOrder", "Line Out Of Order"); + case kgbArNone: return presentation(fmt, "kgbArNone", "None"); + } + break; + + case R2_COUNTRY_BRA: + switch ((KSignGroupB_Brazil)group) + { + case kgbBrLineFreeCharged: return presentation(fmt, "kgbBrLineFreeCharged", "Line Free Charged"); + case kgbBrLineFreeNotCharged: return presentation(fmt, "kgbBrLineFreeNotCharged", "Line Free Not Charged"); + case kgbBrLineFreeChargedLPR: return presentation(fmt, "kgbBrLineFreeChargedLPR", "Line Free Charged PLR"); + case kgbBrBusy: return presentation(fmt, "kgbBrBusy", "Busy"); + case kgbBrNumberChanged: return presentation(fmt, "kgbBrNumberChanged", "Number Changed"); + case kgbBrCongestion: return presentation(fmt, "kgbBrCongestion", "Congestion"); + case kgbBrInvalidNumber: return presentation(fmt, "kgbBrInvalidNumber", "Invalid Number"); + case kgbBrLineOutOfOrder: return presentation(fmt, "kgbBrLineOutOfOrder", "Line Out Of Order"); + case kgbBrNone: return presentation(fmt, "kgbBrNone", "None"); + } + break; + + case R2_COUNTRY_CHI: + switch ((KSignGroupB_Chile)group) + { + case kgbClNumberChanged: return presentation(fmt, "kgbClNumberChanged", "Number Changed"); + case kgbClBusy: return presentation(fmt, "kgbClBusy", "Busy"); + case kgbClCongestion: return presentation(fmt, "kgbClCongestion", "Congestion"); + case kgbClInvalidNumber: return presentation(fmt, "kgbClInvalidNumber", "Invalid Number"); + case kgbClLineFreeCharged: return presentation(fmt, "kgbClLineFreeCharged", "Line Free Charged"); + case kgbClLineFreeNotCharged: return presentation(fmt, "kgbClLineFreeNotCharged", "Line Free Not Charged"); + case kgbClLineOutOfOrder: return presentation(fmt, "kgbClLineOutOfOrder", "Line Out Of Order"); + case kgbClNone: return presentation(fmt, "kgbClNone", "None"); + } + break; + + case R2_COUNTRY_MEX: + switch ((KSignGroupB_Mexico)group) + { + case kgbMxLineFreeCharged: return presentation(fmt, "kgbMxLineFreeCharged", "Line Free Charged"); + case kgbMxBusy: return presentation(fmt, "kgbMxBusy", "Busy"); + case kgbMxLineFreeNotCharged: return presentation(fmt, "kgbMxLineFreeNotCharged", "Line Free Not Charged"); + case kgbMxNone: return presentation(fmt, "kgbMxNone", "None"); + } + break; + + case R2_COUNTRY_URY: + switch ((KSignGroupB_Uruguay)group) + { + case kgbUyNumberChanged: return presentation(fmt, "kgbUyNumberChanged", "Number Changed"); + case kgbUyBusy: return presentation(fmt, "kgbUyBusy", "Busy"); + case kgbUyCongestion: return presentation(fmt, "kgbUyCongestion", "Congestion"); + case kgbUyInvalidNumber: return presentation(fmt, "kgbUyInvalidNumber", "Invalid Number"); + case kgbUyLineFreeCharged: return presentation(fmt, "kgbUyLineFreeCharged", "Line Free Charged"); + case kgbUyLineFreeNotCharged: return presentation(fmt, "kgbUyLineFreeNotCharged", "Line Free Not Charged"); + case kgbUyLineOutOfOrder: return presentation(fmt, "kgbUyLineOutOfOrder", "Line Out Of Order"); + case kgbUyNone: return presentation(fmt, "kgbUyNone", "None"); + } + break; + + case R2_COUNTRY_VEN: + switch ((KSignGroupB_Venezuela)group) + { + case kgbVeLineFreeChargedLPR: return presentation(fmt, "kgbVeLineFreeChargedLPR", "Line Free Charged PLR"); + case kgbVeNumberChanged: return presentation(fmt, "kgbVeNumberChanged", "Number Changed"); + case kgbVeBusy: return presentation(fmt, "kgbVeBusy", "Busy"); + case kgbVeCongestion: return presentation(fmt, "kgbVeCongestion", "Congestion"); + case kgbVeInformationTone: return presentation(fmt, "kgbVeInformationTone", "Information Tone"); + case kgbVeLineFreeCharged: return presentation(fmt, "kgbVeLineFreeCharged", "Line Free Charged"); + case kgbVeLineFreeNotCharged: return presentation(fmt, "kgbVeLineFreeNotCharged", "Line Free Not Charged"); + case kgbVeLineBlocked: return presentation(fmt, "kgbVeLineBlocked", "Line Blocked"); + case kgbVeIntercepted: return presentation(fmt, "kgbVeIntercepted", "Intercepted"); + case kgbVeDataTrans: return presentation(fmt, "kgbVeDataTrans", "Data Transfer"); + case kgbVeNone: return presentation(fmt, "kgbVeNone", "None"); + } + break; + } +#else + switch ((KSignGroupB)group) + { + case kgbLineFreeCharged: return presentation(fmt, "kgbLineFreeCharged", "Line Free Charged"); + case kgbLineFreeNotCharged: return presentation(fmt, "kgbLineFreeNotCharged", "Line Free Not Charged"); + case kgbLineFreeChargedLPR: return presentation(fmt, "kgbLineFreeChargedLPR", "Line Free Charged PLR"); + case kgbBusy: return presentation(fmt, "kgbBusy", "Busy"); + case kgbNumberChanged: return presentation(fmt, "kgbNumberChanged", "Number Changed"); + case kgbCongestion: return presentation(fmt, "kgbCongestion", "Congestion"); + case kgbInvalidNumber: return presentation(fmt, "kgbInvalidNumber", "Invalid Number"); + case kgbLineOutOfOrder: return presentation(fmt, "kgbLineOutOfOrder", "Line Out Of Order"); + case kgbNone: return presentation(fmt, "kgbNone", "None"); + } +#endif + + throw internal_not_found(); +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::signGroupB(KSignGroupB group, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::signGroupB(KSignGroupB group, Verbose::Presentation fmt) +#endif +{ + try + { +#if K3L_AT_LEAST(2,0,0) + return internal_signGroupB(group, r2_country, fmt); +#else + return internal_signGroupB(group, fmt); +#endif + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KSignGroupB='%d']") % (int)group), + STG(FMT("Unknown group B (%d)") % (int)group)); + } +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::internal_signGroupII(KSignGroupII group, R2CountryType country, Verbose::Presentation fmt) +#else +std::string Verbose::internal_signGroupII(KSignGroupII group, Verbose::Presentation fmt) +#endif +{ +#if K3L_AT_LEAST(2,0,0) + switch (country) + { + case R2_COUNTRY_ARG: + switch ((KSignGroupII_Argentina)group) + { + case kg2ArOrdinary: return presentation(fmt, "kg2ArOrdinary", "Ordinary"); + case kg2ArPriority: return presentation(fmt, "kg2ArPriority", "Priority"); + case kg2ArMaintenance: return presentation(fmt, "kg2ArMaintenance", "Maintenance"); + case kg2ArLocalPayPhone: return presentation(fmt, "kg2ArLocalPayPhone", "Local pay phone"); + case kg2ArTrunkOperator: return presentation(fmt, "kg2ArTrunkOperator", "Trunk operator"); + case kg2ArDataTrans: return presentation(fmt, "kg2ArDataTrans", "Data transfer"); + case kg2ArCPTP: return presentation(fmt, "kg2ArCPTP", "CPTP"); + case kg2ArSpecialLine: return presentation(fmt, "kg2ArSpecialLine", "Special line"); + case kg2ArMobileUser: return presentation(fmt, "kg2ArMobileUser", "Mobile user"); + case kg2ArPrivateRedLine: return presentation(fmt, "kg2ArPrivateRedLine", "Private red line"); + case kg2ArSpecialPayPhoneLine: return presentation(fmt, "kg2ArSpecialPayPhoneLine", "Special pay phone line"); + } + break; + + case R2_COUNTRY_BRA: + switch ((KSignGroupII_Brazil)group) + { + case kg2BrOrdinary: return presentation(fmt, "kg2BrOrdinary", "Ordinary"); + case kg2BrPriority: return presentation(fmt, "kg2BrPriority", "Priority"); + case kg2BrMaintenance: return presentation(fmt, "kg2BrMaintenance", "Maintenance"); + case kg2BrLocalPayPhone: return presentation(fmt, "kg2BrLocalPayPhone", "Local pay phone"); + case kg2BrTrunkOperator: return presentation(fmt, "kg2BrTrunkOperator", "Trunk operator"); + case kg2BrDataTrans: return presentation(fmt, "kg2BrDataTrans", "Data transfer"); + case kg2BrNonLocalPayPhone: return presentation(fmt, "kg2BrNonLocalPayPhone", "Non local pay phone"); + case kg2BrCollectCall: return presentation(fmt, "kg2BrCollectCall", "Collect call"); + case kg2BrOrdinaryInter: return presentation(fmt, "kg2BrOrdinaryInter", "Ordinary international"); + case kg2BrTransfered: return presentation(fmt, "kg2BrTransfered", "Transfered"); + } + break; + + case R2_COUNTRY_CHI: + switch ((KSignGroupII_Chile)group) + { + case kg2ClOrdinary: return presentation(fmt, "kg2ClOrdinary", "Ordinary"); + case kg2ClPriority: return presentation(fmt, "kg2ClPriority", "Priority"); + case kg2ClMaintenance: return presentation(fmt, "kg2ClMaintenance", "Maintenance"); + case kg2ClTrunkOperator: return presentation(fmt, "kg2ClTrunkOperator", "Trunk operator"); + case kg2ClDataTrans: return presentation(fmt, "kg2ClDataTrans", "Data transfer"); + case kg2ClUnidentifiedSubscriber: return presentation(fmt, "kg2ClUnidentifiedSubscriber", "Unidentified subscriber"); + } + break; + + case R2_COUNTRY_MEX: + switch ((KSignGroupII_Mexico)group) + { + case kg2MxTrunkOperator: return presentation(fmt, "kg2MxTrunkOperator", "Trunk operator"); + case kg2MxOrdinary: return presentation(fmt, "kg2MxOrdinary", "Ordinary"); + case kg2MxMaintenance: return presentation(fmt, "kg2MxMaintenance", "Maintenance"); + } + break; + + case R2_COUNTRY_URY: + switch ((KSignGroupII_Uruguay)group) + { + case kg2UyOrdinary: return presentation(fmt, "kg2UyOrdinary", "Ordinary"); + case kg2UyPriority: return presentation(fmt, "kg2UyPriority", "Priority"); + case kg2UyMaintenance: return presentation(fmt, "kg2UyMaintenance", "Maintenance"); + case kg2UyLocalPayPhone: return presentation(fmt, "kg2UyLocalPayPhone", "Local pay phone"); + case kg2UyTrunkOperator: return presentation(fmt, "kg2UyTrunkOperator", "Trunk operator"); + case kg2UyDataTrans: return presentation(fmt, "kg2UyDataTrans", "Data transfer"); + case kg2UyInternSubscriber: return presentation(fmt, "kg2UyInternSubscriber", "International subscriber"); + } + break; + + case R2_COUNTRY_VEN: + switch ((KSignGroupII_Venezuela)group) + { + case kg2VeOrdinary: return presentation(fmt, "kg2VeOrdinary", "Ordinary"); + case kg2VePriority: return presentation(fmt, "kg2VePriority", "Priority"); + case kg2VeMaintenance: return presentation(fmt, "kg2VeMaintenance", "Maintenance"); + case kg2VeLocalPayPhone: return presentation(fmt, "kg2VeLocalPayPhone", "Local pay phone"); + case kg2VeTrunkOperator: return presentation(fmt, "kg2VeTrunkOperator", "Trunk operator"); + case kg2VeDataTrans: return presentation(fmt, "kg2VeDataTrans", "Data transfer"); + case kg2VeNoTransferFacility: return presentation(fmt, "kg2VeNoTransferFacility", "No transfer facility"); + } + break; + } +#else + switch ((KSignGroupII)group) + { + case kg2Ordinary: return presentation(fmt, "kg2Ordinary", "Ordinary"); + case kg2Priority: return presentation(fmt, "kg2Priority", "Priority"); + case kg2Maintenance: return presentation(fmt, "kg2Maintenance", "Maintenance"); + case kg2LocalPayPhone: return presentation(fmt, "kg2LocalPayPhone", "Local pay phone"); + case kg2TrunkOperator: return presentation(fmt, "kg2TrunkOperator", "Trunk operator"); + case kg2DataTrans: return presentation(fmt, "kg2DataTrans", "Data transfer"); + case kg2NonLocalPayPhone: return presentation(fmt, "kg2NonLocalPayPhone", "Non local pay phone"); + case kg2CollectCall: return presentation(fmt, "kg2CollectCall", "Collect call"); + case kg2OrdinaryInter: return presentation(fmt, "kg2OrdinaryInter", "Ordinary international"); + case kg2Transfered: return presentation(fmt, "kg2Transfered", "Transfered"); + } +#endif + + throw internal_not_found(); +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::signGroupII(KSignGroupII group, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::signGroupII(KSignGroupII group, Verbose::Presentation fmt) +#endif +{ + try + { +#if K3L_AT_LEAST(2,0,0) + return internal_signGroupII(group, r2_country); +#else + return internal_signGroupII(group); +#endif + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KSignGroupII='%d']") % (int)group), + STG(FMT("Unknown group II (%d)") % (int)group)); + } +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::callFail(KSignaling sig, R2CountryType country, int32 info, Verbose::Presentation fmt) +#else +std::string Verbose::callFail(KSignaling sig, int32 info, Verbose::Presentation fmt) +#endif +{ + try + { + switch (sig) + { + case ksigInactive: + throw internal_not_found(); + + case ksigAnalog: + if (('a' <= ((char)info) && 'z' >= ((char)info)) || ('A' <= ((char)info) && 'Z' >= ((char)info))) + return STG(FMT("%c") % (char)info); + else + throw internal_not_found(); + +#if K3L_AT_LEAST(1,5,4) + case ksigLineSide: +#endif +#if K3L_EXACT(2,1,0) + case ksigISUP: + case ksigFax: +#endif +#if K3L_AT_LEAST(1,6,0) + case ksigCAS_EL7: + case ksigE1LC: + return "NOT IMPLEMENTED"; + + case ksigAnalogTerminal: +#endif + case ksigContinuousEM: + case ksigPulsedEM: + + case ksigR2Digital: + case ksigOpenR2: +#if K3L_AT_LEAST(2,0,0) + return internal_signGroupB((KSignGroupB)info, country); +#else + return internal_signGroupB((KSignGroupB)info); +#endif + + case ksigOpenCAS: + case ksigUserR2Digital: +#if K3L_AT_LEAST(2,0,0) + return internal_signGroupB((KSignGroupB)info, R2_COUNTRY_BRA); +#else + return internal_signGroupB((KSignGroupB)info); +#endif + +#if K3L_AT_LEAST(1,5,0) + case ksigSIP: + return internal_sipFailures((KSIP_Failures)info); +#endif + +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: + case ksigPRI_EndPoint: + case ksigPRI_Network: + case ksigPRI_Passive: +#if K3L_AT_LEAST(2,2,0) + case ksigISUP: + case ksigISUPPassive: +#endif + return internal_isdnCause((KQ931Cause)info); +#endif + +#if K3L_AT_LEAST(1,6,0) + case ksigGSM: + return internal_gsmCallCause((KGsmCallCause)info); +#endif + } + } + catch (internal_not_found & e) + { + /* this exception is used for breaking the control flow */ + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[%s, callFail='%d']") % signaling(sig, fmt) % (int)info), + STG(FMT("Unknown call fail code for '%s' (%d)") % signaling(sig, fmt) % (int)info)); +} + +std::string Verbose::channelFail(KSignaling sig, int32 code, Verbose::Presentation fmt) +{ + try + { + switch (sig) + { + case ksigInactive: + case ksigAnalog: + case ksigSIP: +#if K3L_EXACT(2,1,0) + case ksigISUP: + case ksigFax: +#endif + throw internal_not_found(); + +#if K3L_AT_LEAST(1,6,0) + case ksigGSM: + return internal_gsmMobileCause((KGsmMobileCause)code); + + case ksigAnalogTerminal: + case ksigCAS_EL7: + case ksigE1LC: +#endif + + case ksigContinuousEM: + case ksigPulsedEM: + + case ksigLineSide: + + case ksigOpenCAS: + case ksigOpenR2: + case ksigR2Digital: + case ksigUserR2Digital: + switch ((KChannelFail)code) + { + case kfcRemoteFail: return presentation(fmt, "kfcRemoteFail", "Remote failure"); + case kfcLocalFail: return presentation(fmt, "kfcLocalFail", "Local failure"); + case kfcRemoteLock: return presentation(fmt, "kfcRemoteLock", "Remote lock"); + case kfcLineSignalFail: return presentation(fmt, "kfcLineSignalFail", "Line signal failure"); + case kfcAcousticSignalFail: return presentation(fmt, "kfcAcousticSignalFail", "Acoustic signal failure"); + } + + throw internal_not_found(); + +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: + case ksigPRI_EndPoint: + case ksigPRI_Network: + case ksigPRI_Passive: +#if K3L_AT_LEAST(2,2,0) + case ksigISUP: + case ksigISUPPassive: +#endif + return internal_isdnCause((KQ931Cause)code); +#endif + } + } + catch (internal_not_found & e) + { + /* this exception is used for breaking the control flow */ + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[%s, channelFail='%d']") % signaling(sig, fmt) % (int)code), + STG(FMT("Unknown channel fail code for '%s' (%d)") % signaling(sig, fmt) % (int)code)); +} + +std::string Verbose::internalFail(KInternalFail inf, Verbose::Presentation fmt) +{ + switch (inf) + { + case kifInterruptCtrl: return presentation(fmt, "kifInterruptCtrl", "Interrupt control"); + case kifCommunicationFail: return presentation(fmt, "kifCommunicationFail", "Communication failure"); + case kifProtocolFail: return presentation(fmt, "kifProtocolFail", "Protocol failure"); + case kifInternalBuffer: return presentation(fmt, "kifInternalBuffer", "Internal buffer"); + case kifMonitorBuffer: return presentation(fmt, "kifMonitorBuffer", "Monitor buffer"); + case kifInitialization: return presentation(fmt, "kifInitialization", "Initialization"); + case kifInterfaceFail: return presentation(fmt, "kifInterfaceFail", "Interface failure"); + case kifClientCommFail: return presentation(fmt, "kifClientCommFail", "Client communication failure"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KInternalFail='%d']") % (int)inf), + STG(FMT("Unknown internal failure (%d)") % (int)inf)); +} + +std::string Verbose::linkErrorCounter(KLinkErrorCounter ec, Verbose::Presentation fmt) +{ + switch (ec) + { + case klecChangesToLock: return presentation(fmt, "klecChangesToLock", "Changes to lock"); + case klecLostOfSignal: return presentation(fmt, "klecLostOfSignal", "Lost of signal"); + case klecAlarmNotification: return presentation(fmt, "klecAlarmNotification", "Alarm notification"); + case klecLostOfFrame: return presentation(fmt, "klecLostOfFrame", "Lost of frame"); + case klecLostOfMultiframe: return presentation(fmt, "klecLostOfMultiframe", "Lost of multiframe"); + case klecRemoteAlarm: return presentation(fmt, "klecRemoteAlarm", "Remote alarm"); + case klecUnknowAlarm: return presentation(fmt, "klecUnknowAlarm", "Slip alarm"); + case klecPRBS: return presentation(fmt, "klecPRBS", "PRBS"); + case klecWrogrBits: return presentation(fmt, "klecWrongBits", "Wrong bits"); + case klecJitterVariation: return presentation(fmt, "klecJitterVariation", "Jitter variation"); + case klecFramesWithoutSync: return presentation(fmt, "klecFramesWithoutSync", "Frames without sync"); + case klecMultiframeSignal: return presentation(fmt, "klecMultiframeSignal", "Multiframe Signal"); + case klecFrameError: return presentation(fmt, "klecFrameError", "Frame error"); + case klecBipolarViolation: return presentation(fmt, "klecBipolarViolation", "Bipolar violation"); + case klecCRC4: return presentation(fmt, "klecCRC4", "CRC4 error"); + case klecCount: return ""; /* this should never be verbosed */ + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KLinkErrorCounter='%d']") % (int)ec), + STG(FMT("Unknown link error counter (%d)") % (int)ec)); +} + +std::string Verbose::callStatus(KCallStatus code, Verbose::Presentation fmt) +{ + switch (code) + { + case kcsFree: return presentation(fmt, "kcsFree", "Free"); + case kcsIncoming: return presentation(fmt, "kcsIncoming", "Incoming"); + case kcsOutgoing: return presentation(fmt, "kcsOutgoing", "Outgoing"); + case kcsFail: return presentation(fmt, "kcsFail", "Failure"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KCallStatus='%d']") % (int)code), + STG(FMT("Unknown call status (%d)") % (int)code)); +} + +std::string Verbose::linkStatus(KSignaling sig, int32 code, Verbose::Presentation fmt) +{ + switch (sig) + { + case ksigInactive: + return presentation(fmt, "[ksigInactive]", "Inactive trunk"); + + case ksigAnalog: + return presentation(fmt, "[ksigAnalog]", "Analog trunk"); + +#if K3L_AT_LEAST(1,4,1) + case ksigSIP: + return presentation(fmt, "[ksigSIP]", "SIP trunk"); +#endif + +#if K3L_AT_LEAST(1,6,0) + case ksigGSM: + return presentation(fmt, "[ksigGSM]", "GSM trunk"); +#endif + +#if K3L_EXACT(2,1,0) + case ksigFax: + return presentation(fmt, "[ksigFax]", "FAX"); +#endif + case ksigContinuousEM: + case ksigPulsedEM: + + case ksigOpenCAS: + case ksigOpenR2: + case ksigR2Digital: + case ksigUserR2Digital: + +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: + case ksigPRI_EndPoint: + case ksigPRI_Network: + case ksigPRI_Passive: +#endif +#if K3L_AT_LEAST(1,5,3) + case ksigLineSide: +#endif +#if K3L_AT_LEAST(1,6,0) + case ksigAnalogTerminal: + case ksigCAS_EL7: + case ksigE1LC: +#endif +#if K3L_AT_LEAST(2,2,0) + case ksigISUP: + case ksigISUPPassive: +#endif + if (kesOk == code) + { + return presentation(fmt, "kesOk", "Up"); + } + else + { + Strings::Merger strs; + + if (kesSignalLost & code) strs.add(presentation(fmt, "SignalLost", "Signal lost")); + if (kesNetworkAlarm & code) strs.add(presentation(fmt, "NetworkAlarm", "Network alarm")); + if (kesFrameSyncLost & code) strs.add(presentation(fmt, "FrameSyncLost", "Frame sync lost")); + if (kesMultiframeSyncLost & code) strs.add(presentation(fmt, "MultiframeSyncLost", "Multiframe sync lost")); + if (kesRemoteAlarm & code) strs.add(presentation(fmt, "RemoteAlarm", "Remote alarm")); + if (kesHighErrorRate & code) strs.add(presentation(fmt, "HighErrorRate", "High error rate")); + if (kesUnknownAlarm & code) strs.add(presentation(fmt, "UnknownAlarm", "Slip alarm")); + if (kesE1Error & code) strs.add(presentation(fmt, "E1Error", "E1 error")); + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("kes{%s}") % strs.merge(",")), + strs.merge(", ")); + } + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[%s, linkStatus='%d']") % signaling(sig) % (int)code), + STG(FMT("Unknown link status for '%s' (%d)") % signaling(sig) % (int)code)); +} + +std::string Verbose::channelStatus(KSignaling sig, int32 flags, Verbose::Presentation fmt) +{ + try + { + switch (sig) + { + case ksigInactive: + return presentation(fmt, "[ksigInactive]", "Inactive channel"); + +#if K3L_AT_LEAST(1,4,1) + case ksigSIP: + return presentation(fmt, "[ksigSIP]", "SIP channel"); +#endif +#if K3L_EXACT(2,1,0) + case ksigISUP: + return presentation(fmt, "[ksigISUP]", "ISUP trunk"); + case ksigFax: + return presentation(fmt, "[ksigFax]", "FAX"); +#endif + + case ksigAnalog: +#if K3L_AT_LEAST(1,6,0) + switch ((KFXOChannelStatus)flags) +#else + switch ((KFXChannelStatus)flags) +#endif + { + case kfcsDisabled: return presentation(fmt, "kfcsDisabled", "Disabled"); + case kfcsEnabled: return presentation(fmt, "kfcsEnabled", "Enabled"); + } + + throw internal_not_found(); + +#if K3L_AT_LEAST(1,6,0) + case ksigAnalogTerminal: + switch ((KFXSChannelStatus)flags) + { + case kfxsOnHook: return presentation(fmt, "kfxsOnHook", "On Hook"); + case kfxsOffHook: return presentation(fmt, "kfxsOffHook", "Off Hook"); + case kfxsRinging: return presentation(fmt, "kfxsRinging", "Ringing"); + case kfxsFail: return presentation(fmt, "kfxsFail", "Failure"); + } + + throw internal_not_found(); + + case ksigGSM: + switch ((KGsmChannelStatus)flags) + { + case kgsmIdle: return presentation(fmt, "kgsmIdle", "Idle"); + case kgsmCallInProgress: return presentation(fmt, "kgsmCallInProgress", "Call in progress"); + case kgsmSMSInProgress: return presentation(fmt, "kgsmSMSInProgress", "SMS in progress"); + case kgsmModemError: return presentation(fmt, "kgsmModemError", "Modem error"); + case kgsmSIMCardError: return presentation(fmt, "kgsmSIMCardError", "SIM card error"); + case kgsmNetworkError: return presentation(fmt, "kgsmNetworkError", "Network error"); + case kgsmNotReady: return presentation(fmt, "kgsmNotReady", "Initializing"); + } + + throw internal_not_found(); +#endif + + /* deprecated, but still.. */ + case ksigPulsedEM: + case ksigContinuousEM: + + case ksigOpenCAS: + case ksigOpenR2: + case ksigR2Digital: + case ksigUserR2Digital: + +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: + case ksigPRI_EndPoint: + case ksigPRI_Network: + case ksigPRI_Passive: +#endif +#if K3L_AT_LEAST(1,5,3) + case ksigLineSide: +#endif +#if K3L_AT_LEAST(1,6,0) + case ksigCAS_EL7: + case ksigE1LC: +#endif +#if K3L_AT_LEAST(2,2,0) + case ksigISUP: + case ksigISUPPassive: +#endif + { + if (flags == kecsFree) + { + return presentation(fmt, "kecsFree", "Free"); + } + else + { + Strings::Merger strs; + + if (flags & kecsBusy) + strs.add("Busy"); + + switch (flags & 0x06) + { + case kecsOutgoing: + strs.add("Outgoing"); + break; + case kecsIncoming: + strs.add("Incoming"); + break; + case kecsLocked: + strs.add("Locked"); + default: + break; + } + + int32 value = (flags & 0xf0); + + if (kecsOutgoingLock & value) + strs.add(presentation(fmt, "OutgoingLock", "Outgoing Lock")); + + if (kecsLocalFail & value) + strs.add(presentation(fmt, "LocalFail", "Local Failure")); + + if (kecsIncomingLock & value) + strs.add(presentation(fmt, "IncomingLock", "Incoming Lock")); + + if (kecsRemoteLock & value) + strs.add(presentation(fmt, "RemoteLock", "Remote Lock")); + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("kecs{%s}") % strs.merge(",")), + strs.merge(", ")); + } + + throw internal_not_found(); + } + } + } + catch (internal_not_found & e) + { + /* we use this exception to break the control flow */ + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[%s, channelStatus='%d']") % signaling(sig) % flags), + STG(FMT("Unknown channel status for '%s' (%d)") % signaling(sig) % flags)); +} + +std::string Verbose::status(KLibraryStatus code, Verbose::Presentation fmt) +{ + switch (code) + { + case ksSuccess: return presentation(fmt, "ksSuccess", "Success"); + case ksFail: return presentation(fmt, "ksFail", "Failure"); + case ksTimeOut: return presentation(fmt, "ksTimeOut", "Time Out"); + case ksBusy: return presentation(fmt, "ksBusy", "Busy"); + case ksLocked: return presentation(fmt, "ksLocked", "Locked"); + case ksInvalidParams: return presentation(fmt, "ksInvalidParams", "Invalid Parameters"); + case ksEndOfFile: return presentation(fmt, "ksEndOfFile", "End of File"); + case ksInvalidState: return presentation(fmt, "ksInvalidState", "Invalid State"); + case ksServerCommFail: return presentation(fmt, "ksServerCommFail", "Communication Failure"); + case ksOverflow: return presentation(fmt, "ksOverflow", "Overflow"); + case ksUnderrun: return presentation(fmt, "ksUnderrun", "Underrun"); + +#if K3L_AT_LEAST(1,4,0) + case ksNotFound: return presentation(fmt, "ksNotFound", "Not Found"); + case ksNotAvailable: return presentation(fmt, "ksNotAvaiable", "Not Available"); +#endif + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KLibraryStatus='%d']") % (int)code), + STG(FMT("Unknown library status (%d)") % (int)code)); +} + +std::string Verbose::h100configIndex(KH100ConfigIndex code, Verbose::Presentation fmt) +{ + switch (code) + { + case khciDeviceMode: return presentation(fmt, "khciDeviceMode", "Device Mode"); + case khciMasterGenClock: return presentation(fmt, "khciMasterGenClock", "Master Generated Clock"); + case khciCTNetRefEnable: return presentation(fmt, "khciCTNetRefEnable", "CTBus Network Reference Enable"); + case khciSCbusEnable: return presentation(fmt, "khciSCbusEnable", "SCBus Enable"); + case khciHMVipEnable: return presentation(fmt, "khciHMVipEnable", "HMVip Enable"); + case khciMVip90Enable: return presentation(fmt, "khciMVip90Enable", "MVip90 Enable"); + case khciCTbusDataEnable: return presentation(fmt, "khciCTbusDataEnable", "CTBus Data Enable"); + case khciCTbusFreq03_00: return presentation(fmt, "khciCTbusFreq03_00", "CTBus Frequency 03 00"); // TODO: find better name + case khciCTbusFreq07_04: return presentation(fmt, "khciCTbusFreq07_04", "CTBus Frequency 07 04"); // TODO: find better name + case khciCTbusFreq11_08: return presentation(fmt, "khciCTbusFreq11_08", "CTBus Frequency 11 08"); // TODO: find better name + case khciCTbusFreq15_12: return presentation(fmt, "khciCTbusFreq15_12", "CTBus Frequency 15 12"); // TODO: find better name + case khciMax: return presentation(fmt, "khciMax", "Max"); // TODO: find better name + case khciMasterDevId: return presentation(fmt, "khciMasterDevId", "Master Device Number"); + case khciSecMasterDevId: return presentation(fmt, "khciSecMasterDevId", "Secondary Master Device Number"); + case khciCtNetrefDevId: return presentation(fmt, "khciCtNetrefDevId", "CTBus Network Reference Device Number"); +#if K3L_AT_LEAST(1,6,0) + case khciMaxH100ConfigIndex: return ""; /* do not verbose this value */ +#endif + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KH100ConfigIndex='%d']") % (int)code), + STG(FMT("Unknown H.100 config index (%d)") % (int)code)); +} + +#if K3L_AT_LEAST(1,6,0) +std::string Verbose::callStartInfo(KCallStartInfo code, Verbose::Presentation fmt) +{ + switch (code) + { + case kcsiHumanAnswer: return presentation(fmt, "kcsiHumanAnswer", "Human Answer"); + case kcsiAnsweringMachine: return presentation(fmt, "kcsiAnsweringMachine", "Answering Machine"); + case kcsiCellPhoneMessageBox: return presentation(fmt, "kcsiCellPhoneMessageBox", "Cell Phone Message Box"); + case kcsiCarrierMessage: return presentation(fmt, "kcsiCarrierMessage", "Carrier Message"); + case kcsiUnknown: return presentation(fmt, "kcsiUnknown", "Unknown"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KCallStartInfo='%d']") % (int)code), + STG(FMT("Unknown call answer info (%d)") % (int)code)); +} + +std::string Verbose::gsmCallCause(KGsmCallCause code, Verbose::Presentation fmt) +{ + try + { + return internal_gsmCallCause(code, fmt); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KGsmCallCause='%d']") % (int)code), + STG(FMT("Unknown GSM call cause (%d)") % (int)code)); + } +} + +std::string Verbose::internal_gsmCallCause(KGsmCallCause code, Verbose::Presentation fmt) +{ + switch (code) + { + case kgccNone: return presentation(fmt, "kgccNone", "None"); + case kgccUnallocatedNumber: return presentation(fmt, "kgccUnallocatedNumber", "Unallocated number"); + case kgccNoRouteToDest: return presentation(fmt, "kgccNoRouteToDest", "No route to destination"); + case kgccChannelUnacceptable: return presentation(fmt, "kgccChannelUnacceptable", "Channel unacceptable"); + case kgccOperatorDeterminedBarring: return presentation(fmt, "kgccOperatorDeterminedBarring", "Operator determined barring"); + case kgccNormalCallClear: return presentation(fmt, "kgccNormalCallClear", "Normal call clear"); + case kgccUserBusy: return presentation(fmt, "kgccUserBusy", "User busy"); + case kgccNoUserResponding: return presentation(fmt, "kgccNoUserResponding", "No user responding"); + case kgccNoAnswerFromUser: return presentation(fmt, "kgccNoAnswerFromUser", "No answer from user"); + case kgccCallRejected: return presentation(fmt, "kgccCallRejected", "Call rejected"); + case kgccNumberChanged: return presentation(fmt, "kgccNumberChanged", "Number changed"); + case kgccNonSelectedUserClear: return presentation(fmt, "kgccNonSelectedUserClear", "Non Selected user clear"); + case kgccDestinationOutOfOrder: return presentation(fmt, "kgccDestinationOutOfOrder", "Destination out of order"); + case kgccInvalidNumberFormat: return presentation(fmt, "kgccInvalidNumberFormat", "Invalid number format"); + case kgccFacilityRejected: return presentation(fmt, "kgccFacilityRejected", "Facility rejected"); + case kgccRespStatusEnquiry: return presentation(fmt, "kgccRespStatusEnquiry", "Response status enquiry"); + case kgccNormalUnspecified: return presentation(fmt, "kgccNormalUnspecified", "Normal, unspecified"); + case kgccNoCircuitChannelAvail: return presentation(fmt, "kgccNoCircuitChannelAvail", "No circuit channel available"); + case kgccNetworkOutOfOrder: return presentation(fmt, "kgccNetworkOutOfOrder", "Network out of order"); + case kgccTemporaryFailure: return presentation(fmt, "kgccTemporaryFailure", "Temporary failure"); + case kgccSwitchCongestion: return presentation(fmt, "kgccSwitchCongestion", "Switch congestion"); + case kgccAccessInfoDiscarded: return presentation(fmt, "kgccAccessInfoDiscarded", "Access information discarded"); + case kgccRequestedChannelUnav: return presentation(fmt, "kgccRequestedChannelUnav", "Requested channel unavailable"); + case kgccResourceUnavailable: return presentation(fmt, "kgccResourceUnavailable", "Resource unavailable"); + case kgccQosUnavailable: return presentation(fmt, "kgccQosUnavailable", "QoS unavailable"); + case kgccReqFacilityNotSubsc: return presentation(fmt, "kgccReqFacilityNotSubsc", "Request facility not subscribed"); + case kgccCallBarredWitchCUG: return presentation(fmt, "kgccCallBarredWitchCUG", "Call barred with UG"); + case kgccBearerCapabNotAuthor: return presentation(fmt, "kgccBearerCapabNotAuthor", "Bearer capability not authorized"); + case kgccBearerCapabNotAvail: return presentation(fmt, "kgccBearerCapabNotAvail", "Bearer capability not available"); + case kgccServiceNotAvailable: return presentation(fmt, "kgccServiceNotAvailable", "Service not available"); + case kgccBcNotImplemented: return presentation(fmt, "kgccBcNotImplemented", "Bearer capability not implemented"); + case kgccReqFacilityNotImplem: return presentation(fmt, "kgccReqFacilityNotImplem", "Request facility not implemented"); + case kgccOnlyRestrictedBcAvail: return presentation(fmt, "kgccOnlyRestrictedBcAvail", "Only restricted bearer capability available"); + case kgccServiceNotImplemented: return presentation(fmt, "kgccServiceNotImplemented", "Service not implemented"); + case kgccInvalidCrv: return presentation(fmt, "kgccInvalidCrv", "Invalid call reference value"); + case kgccUserNotMemberOfCUG: return presentation(fmt, "kgccUserNotMemberOfCUG", "User not member of UG"); + case kgccIncompatibleDestination: return presentation(fmt, "kgccIncompatibleDestination", "Incompatible destination"); + case kgccInvalidTransitNetSel: return presentation(fmt, "kgccInvalidTransitNetSel", "Invalid transit network selected"); + case kgccInvalidMessage: return presentation(fmt, "kgccInvalidMessage", "Invalid message"); + case kgccMissingMandatoryIe: return presentation(fmt, "kgccMissingMandatoryIe", "Missing mandatory information element"); + case kgccMsgTypeNotImplemented: return presentation(fmt, "kgccMsgTypeNotImplemented", "Message type not implemented"); + case kgccMsgIncompatWithState: return presentation(fmt, "kgccMsgIncompatWithState", "Message incompatible with state"); + case kgccIeNotImplemented: return presentation(fmt, "kgccIeNotImplemented", "Information element not implemented"); + case kgccInvalidIe: return presentation(fmt, "kgccInvalidIe", "Invalid information element"); + case kgccMsgIncompatWithState2: return presentation(fmt, "kgccMsgIncompatWithState2", "Message incompatible with state (2)"); + case kgccRecoveryOnTimerExpiry: return presentation(fmt, "kgccRecoveryOnTimerExpiry", "Recovery on timer expiry"); + case kgccProtocolError: return presentation(fmt, "kgccProtocolError", "Protocol error"); + case kgccInterworking: return presentation(fmt, "kgccInterworking", "Interworking"); + } + + throw internal_not_found(); +} + +std::string Verbose::gsmMobileCause(KGsmMobileCause code, Verbose::Presentation fmt) +{ + try + { + return internal_gsmMobileCause(code, fmt); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KGsmMobileCause='%d']") % (int)code), + STG(FMT("Unknown GSM mobile cause (%d)") % (int)code)); + } +} + +std::string Verbose::internal_gsmMobileCause(KGsmMobileCause code, Verbose::Presentation fmt) +{ + switch (code) + { + case kgmcPhoneFailure: return presentation(fmt, "kgmcPhoneFailure", "Phone failure"); + case kgmcNoConnectionToPhone: return presentation(fmt, "kgmcNoConnectionToPhone", "No connection to phone"); + case kgmcPhoneAdaptorLinkReserved: return presentation(fmt, "kgmcPhoneAdaptorLinkReserved", "Phone adaptor link reserved"); +#if 0 /* this changed during K3L 1.6.0 development cycle... */ + case kgmcCoperationNotAllowed: return presentation(fmt, "kgmcCoperationNotAllowed", ""); + case kgmcCoperationNotSupported: return presentation(fmt, "kgmcCoperationNotSupported", ""); +#else + case kgmcOperationNotAllowed: return presentation(fmt, "kgmcOperationNotAllowed", "Operation not allowed"); + case kgmcOperationNotSupported: return presentation(fmt, "kgmcOperationNotSupported", "Operation not supported"); +#endif + case kgmcPH_SIMPINRequired: return presentation(fmt, "kgmcPH_SIMPINRequired", "Phone SIM PIN required"); + case kgmcPH_FSIMPINRequired: return presentation(fmt, "kgmcPH_FSIMPINRequired", "Phone FSIM PIN required"); + case kgmcPH_FSIMPUKRequired: return presentation(fmt, "kgmcPH_FSIMPUKRequired", "Phone FSIM PUK required"); + case kgmcSIMNotInserted: return presentation(fmt, "kgmcSIMNotInserted", "SIM not inserted"); + case kgmcSIMPINRequired: return presentation(fmt, "kgmcSIMPINRequired", "SIM PIN required"); + case kgmcSIMPUKRequired: return presentation(fmt, "kgmcSIMPUKRequired", "SIM PUK required"); + case kgmcSIMFailure: return presentation(fmt, "kgmcSIMFailure", "SIM failure"); + case kgmcSIMBusy: return presentation(fmt, "kgmcSIMBusy", "SIM busy"); + case kgmcSIMWrong: return presentation(fmt, "kgmcSIMWrong", "SIM wrong"); + case kgmcIncorrectPassword: return presentation(fmt, "kgmcIncorrectPassword", "Incorrect password"); + case kgmcSIMPIN2Required: return presentation(fmt, "kgmcSIMPIN2Required", "SIM PIN2 required"); + case kgmcSIMPUK2Required: return presentation(fmt, "kgmcSIMPUK2Required", "SIM PUK2 required"); + case kgmcMemoryFull: return presentation(fmt, "kgmcMemoryFull", "Memory full"); + case kgmcInvalidIndex: return presentation(fmt, "kgmcInvalidIndex", "Invalid index"); + case kgmcNotFound: return presentation(fmt, "kgmcNotFound", "Not found"); + case kgmcMemoryFailure: return presentation(fmt, "kgmcMemoryFailure", "Memory failure"); + case kgmcTextStringTooLong: return presentation(fmt, "kgmcTextStringTooLong", "Text string too long"); + case kgmcInvalidCharInTextString: return presentation(fmt, "kgmcInvalidCharInTextString", "Invalid character in text string"); + case kgmcDialStringTooLong: return presentation(fmt, "kgmcDialStringTooLong", "Dial string too long"); + case kgmcInvalidCharInDialString: return presentation(fmt, "kgmcInvalidCharInDialString", "Invalid character in dial string"); + case kgmcNoNetworkService: return presentation(fmt, "kgmcNoNetworkService", "No network service"); + case kgmcNetworkTimeout: return presentation(fmt, "kgmcNetworkTimeout", "Network timeout"); + case kgmcNetworkNotAllowed: return presentation(fmt, "kgmcNetworkNotAllowed", "Network not allowed"); + case kgmcCommandAborted: return presentation(fmt, "kgmcCommandAborted", "Command aborted"); + case kgmcNumParamInsteadTextParam: return presentation(fmt, "kgmcNumParamInsteadTextParam", "Number parameter instead of text parameter"); + case kgmcTextParamInsteadNumParam: return presentation(fmt, "kgmcTextParamInsteadNumParam", "Text parameter instead of number parameter"); + case kgmcNumericParamOutOfBounds: return presentation(fmt, "kgmcNumericParamOutOfBounds", "Numeric parameter out of bounds"); + case kgmcTextStringTooShort: return presentation(fmt, "kgmcTextStringTooShort", "Text string too short"); + case kgmcNetworkPINRequired: return presentation(fmt, "kgmcNetworkPINRequired", "Network PIN required"); + case kgmcNetworkPUKRequired: return presentation(fmt, "kgmcNetworkPUKRequired", "Network PUK required"); + case kgmcNetworkSubsetPINRequired: return presentation(fmt, "kgmcNetworkSubsetPINRequired", "Network subset PIN required"); + case kgmcNetworkSubnetPUKRequired: return presentation(fmt, "kgmcNetworkSubnetPUKRequired", "Network subset PUK required"); + case kgmcServiceProviderPINRequired: return presentation(fmt, "kgmcServiceProviderPINRequired", "Network service provider PIN required"); + case kgmcServiceProviderPUKRequired: return presentation(fmt, "kgmcServiceProviderPUKRequired", "Network service provider PUK required"); + case kgmcCorporatePINRequired: return presentation(fmt, "kgmcCorporatePINRequired", "Corporate PIN required"); + case kgmcCorporatePUKRequired: return presentation(fmt, "kgmcCorporatePUKRequired", "Corporate PUK required"); + case kgmcSIMServiceOptNotSupported: return presentation(fmt, "kgmcSIMServiceOptNotSupported", "SIM Service option not supported"); + case kgmcUnknown: return presentation(fmt, "kgmcUnknown", "Unknown"); + case kgmcIllegalMS_N3: return presentation(fmt, "kgmcIllegalMS_N3", "Illegal MS #3"); + case kgmcIllegalME_N6: return presentation(fmt, "kgmcIllegalME_N6", "Illegal MS #6"); + case kgmcGPRSServicesNotAllowed_N7: return presentation(fmt, "kgmcGPRSServicesNotAllowed_N7", "GPRS service not allowed #7"); + case kgmcPLMNNotAllowed_No11: return presentation(fmt, "kgmcPLMNNotAllowed_No11", "PLMN not allowed #11"); + case kgmcLocationAreaNotAllowed_N12: return presentation(fmt, "kgmcLocationAreaNotAllowed_N12", "Location area not allowed #12"); + case kgmcRoamingNotAllowed_N13: return presentation(fmt, "kgmcRoamingNotAllowed_N13", "Roaming not allowed #13"); + case kgmcServiceOptNotSupported_N32: return presentation(fmt, "kgmcServiceOptNotSupported_N32", "Service option not supported #32"); + case kgmcReqServOptNotSubscribed_N33: return presentation(fmt, "kgmcReqServOptNotSubscribed_N33", "Registration service option not subscribed #33"); + case kgmcServOptTempOutOfOrder_N34: return presentation(fmt, "kgmcServOptTempOutOfOrder_N34", "Service option temporary out of order #34"); + case kgmcLongContextActivation: return presentation(fmt, "kgmcLongContextActivation", "Long context activation"); + case kgmcUnspecifiedGPRSError: return presentation(fmt, "kgmcUnspecifiedGPRSError", "Unspecified GPRS error"); + case kgmcPDPAuthenticationFailure: return presentation(fmt, "kgmcPDPAuthenticationFailure", "PDP authentication failure"); + case kgmcInvalidMobileClass: return presentation(fmt, "kgmcInvalidMobileClass", "Invalid mobile class"); + case kgmcGPRSDisconnectionTmrActive: return presentation(fmt, "kgmcGPRSDisconnectionTmrActive", "GPRS disconnection TMR active"); + case kgmcTooManyActiveCalls: return presentation(fmt, "kgmcTooManyActiveCalls", "Too many active calls"); + case kgmcCallRejected: return presentation(fmt, "kgmcCallRejected", "Call rejected"); + case kgmcUnansweredCallPending: return presentation(fmt, "kgmcUnansweredCallPending", "Unanswered call pending"); + case kgmcUnknownCallingError: return presentation(fmt, "kgmcUnknownCallingError", "Unknown calling error"); + case kgmcNoPhoneNumRecognized: return presentation(fmt, "kgmcNoPhoneNumRecognized", "No phone number recognized"); + case kgmcCallStateNotIdle: return presentation(fmt, "kgmcCallStateNotIdle", "Call state not idle"); + case kgmcCallInProgress: return presentation(fmt, "kgmcCallInProgress", "Call in progress"); + case kgmcDialStateError: return presentation(fmt, "kgmcDialStateError", "Dial state error"); + case kgmcUnlockCodeRequired: return presentation(fmt, "kgmcUnlockCodeRequired", "Unlock code required"); + case kgmcNetworkBusy: return presentation(fmt, "kgmcNetworkBusy", "Network busy"); + case kgmcInvalidPhoneNumber: return presentation(fmt, "kgmcInvalidPhoneNumber", "Invalid phone number"); + case kgmcNumberEntryAlreadyStarted: return presentation(fmt, "kgmcNumberEntryAlreadyStarted", "Number entry already started"); + case kgmcCancelledByUser: return presentation(fmt, "kgmcCancelledByUser", "Cancelled by user"); + case kgmcNumEntryCouldNotBeStarted: return presentation(fmt, "kgmcNumEntryCouldNotBeStarted", "Number entry could not be started"); + case kgmcDataLost: return presentation(fmt, "kgmcDataLost", "Data lost"); + case kgmcInvalidBessageBodyLength: return presentation(fmt, "kgmcInvalidBessageBodyLength", "Invalid message body length"); + case kgmcInactiveSocket: return presentation(fmt, "kgmcInactiveSocket", "Inactive socket"); + case kgmcSocketAlreadyOpen: return presentation(fmt, "kgmcSocketAlreadyOpen", "Socket already open"); +#if K3L_AT_LEAST(2,1,0) + case kgmcSuccess: return presentation(fmt, "kgmcSuccess", "Success"); +#endif + } + + throw internal_not_found(); +} + +std::string Verbose::gsmSmsCause(KGsmSmsCause code, Verbose::Presentation fmt) +{ + try + { + return internal_gsmSmsCause(code, fmt); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KGsmSmsCause='%d']") % (int)code), + STG(FMT("Unknown GSM SMS cause (%d)") % (int)code)); + } +} + +std::string Verbose::internal_gsmSmsCause(KGsmSmsCause code, Verbose::Presentation fmt) +{ + switch (code) + { +#if K3L_AT_LEAST(2,1,0) + case kgscNone: return presentation(fmt, "kgscNone", "None"); +#endif + case kgscUnassigned: return presentation(fmt, "kgscUnassigned", "Unassigned number"); + case kgscOperatorDeterminedBarring: return presentation(fmt, "kgscOperatorDeterminedBarring", "Operator determined barring"); + case kgscCallBarred: return presentation(fmt, "kgscCallBarred", "Call barred"); + case kgscSMSTransferRejected: return presentation(fmt, "kgscSMSTransferRejected", "SMS transfer rejected"); + case kgscDestinationOutOfService: return presentation(fmt, "kgscDestinationOutOfService", "Destination out of service"); + case kgscUnidentifiedSubscriber: return presentation(fmt, "kgscUnidentifiedSubscriber", "Unidentified subscriber"); + case kgscFacilityRejected: return presentation(fmt, "kgscFacilityRejected", "Facility rejected"); + case kgscUnknownSubscriber: return presentation(fmt, "kgscUnknownSubscriber", "Unknown subscriber"); + case kgscNetworkOutOfOrder: return presentation(fmt, "kgscNetworkOutOfOrder", "Network out of order"); + case kgscTemporaryFailure: return presentation(fmt, "kgscTemporaryFailure", "Temporary failure"); + case kgscCongestion: return presentation(fmt, "kgscCongestion", "Congestion"); + case kgscResourcesUnavailable: return presentation(fmt, "kgscResourcesUnavailable", "Resources unavailable"); + case kgscFacilityNotSubscribed: return presentation(fmt, "kgscFacilityNotSubscribed", "Facility not subscribed"); + case kgscFacilityNotImplemented: return presentation(fmt, "kgscFacilityNotImplemented", "Facility not implemented"); + case kgscInvalidSMSTransferRefValue: return presentation(fmt, "kgscInvalidSMSTransferRefValue", "Invalid SMS transfer reference value"); + case kgscInvalidMessage: return presentation(fmt, "kgscInvalidMessage", "Invalid message"); + case kgscInvalidMandatoryInformation: return presentation(fmt, "kgscInvalidMandatoryInformation", "Invalid mandatory information"); + case kgscMessageTypeNonExistent: return presentation(fmt, "kgscMessageTypeNonExistent", "Message type non existent"); + case kgscMsgNotCompatWithSMProtState: return presentation(fmt, "kgscMsgNotCompatWithSMProtState", "Message not compatible with SMS protection state"); + case kgscInformationElementNonExiste: return presentation(fmt, "kgscInformationElementNonExiste", "Information element non existent"); + case kgscProtocolError: return presentation(fmt, "kgscProtocolError", "Protocol error"); + case kgscInterworking: return presentation(fmt, "kgscInterworking", "Interworking"); + case kgscTelematicInterworkingNotSup: return presentation(fmt, "kgscTelematicInterworkingNotSup", "Telematic interworking not supported"); + case kgscSMSTypeZeroNotSupported: return presentation(fmt, "kgscSMSTypeZeroNotSupported", "SMS type zero not supported"); + case kgscCannotReplaceSMS: return presentation(fmt, "kgscCannotReplaceSMS", "Cannot replace SMS"); + case kgscUnspecifiedTPPIDError: return presentation(fmt, "kgscUnspecifiedTPPIDError", "Unspecified TPPID error"); + case kgscAlphabetNotSupported: return presentation(fmt, "kgscAlphabetNotSupported", "Alphabet not supported"); + case kgscMessageClassNotSupported: return presentation(fmt, "kgscMessageClassNotSupported", "Message class not supported"); + case kgscUnspecifiedTPDCSError: return presentation(fmt, "kgscUnspecifiedTPDCSError", "Unspecified TPDCS error"); + case kgscCommandCannotBeActioned: return presentation(fmt, "kgscCommandCannotBeActioned", "Command cannot be actioned"); + case kgscCommandUnsupported: return presentation(fmt, "kgscCommandUnsupported", "Command unsupported"); + case kgscUnspecifiedTPCommandError: return presentation(fmt, "kgscUnspecifiedTPCommandError", "Unspecified TP command error"); + case kgscTPDUNotSupported: return presentation(fmt, "kgscTPDUNotSupported", "TPDU not supported"); + case kgscSCBusy: return presentation(fmt, "kgscSCBusy", "SC busy"); + case kgscNoSCSubscription: return presentation(fmt, "kgscNoSCSubscription", "No SC subscription"); + case kgscSCSystemFailure: return presentation(fmt, "kgscSCSystemFailure", "SC system failure"); + case kgscInvalidSMEAddress: return presentation(fmt, "kgscInvalidSMEAddress", "Invalid SME address"); + case kgscDestinationSMEBarred: return presentation(fmt, "kgscDestinationSMEBarred", "Destination SME barred"); + case kgscSMRejectedDuplicateSM: return presentation(fmt, "kgscSMRejectedDuplicateSM", "SM rejected duplicate SM"); + case kgscTPVPFNotSupported: return presentation(fmt, "kgscTPVPFNotSupported", "TPVPF not supported"); + case kgscTPVPNotSupported: return presentation(fmt, "kgscTPVPNotSupported", "TPVP not supported"); + case kgscSIMSMSStorageFull: return presentation(fmt, "kgscSIMSMSStorageFull", "SIM SMS storage full"); + case kgscNoSMSStorageCapabilityInSIM: return presentation(fmt, "kgscNoSMSStorageCapabilityInSIM", "No SMS storage capability in SIM"); + case kgscErrorInMS: return presentation(fmt, "kgscErrorInMS", "Error in SMS"); + case kgscMemoryCapacityExceeded: return presentation(fmt, "kgscMemoryCapacityExceeded", "Memory capatity exceeded"); + case kgscSIMDataDownloadError: return presentation(fmt, "kgscSIMDataDownloadError", "SIM data download error"); + case kgscUnspecifiedError: return presentation(fmt, "kgscUnspecifiedError", "Unspecified error"); + case kgscPhoneFailure: return presentation(fmt, "kgscPhoneFailure", "Phone failure"); + case kgscSmsServiceReserved: return presentation(fmt, "kgscSmsServiceReserved", "SMS service reserved"); + case kgscOperationNotAllowed: return presentation(fmt, "kgscOperationNotAllowed", "Operation not allowed"); + case kgscOperationNotSupported: return presentation(fmt, "kgscOperationNotSupported", "Operation not supported"); + case kgscInvalidPDUModeParameter: return presentation(fmt, "kgscInvalidPDUModeParameter", "Invalid PDU mode parameter"); + case kgscInvalidTextModeParameter: return presentation(fmt, "kgscInvalidTextModeParameter", "Invalid text mode parameter"); + case kgscSIMNotInserted: return presentation(fmt, "kgscSIMNotInserted", "SIM not inserted"); + case kgscSIMPINNecessary: return presentation(fmt, "kgscSIMPINNecessary", "SIM PIN necessary"); + case kgscPH_SIMPINNecessary: return presentation(fmt, "kgscPH_SIMPINNecessary", "Phone SIM PIN necessary"); + case kgscSIMFailure: return presentation(fmt, "kgscSIMFailure", "SIM failure"); + case kgscSIMBusy: return presentation(fmt, "kgscSIMBusy", "SIM busy"); + case kgscSIMWrong: return presentation(fmt, "kgscSIMWrong", "SIM wrong"); + case kgscMemoryFailure: return presentation(fmt, "kgscMemoryFailure", "Memory failure"); + case kgscInvalidMemoryIndex: return presentation(fmt, "kgscInvalidMemoryIndex", "Invalid memory index"); + case kgscMemoryFull: return presentation(fmt, "kgscMemoryFull", "Memory full"); + case kgscSMSCAddressUnknown: return presentation(fmt, "kgscSMSCAddressUnknown", "SMSC address unknown"); + case kgscNoNetworkService: return presentation(fmt, "kgscNoNetworkService", "No network service"); + case kgscNetworkTimeout: return presentation(fmt, "kgscNetworkTimeout", "Network timeout"); + case kgscUnknownError: return presentation(fmt, "kgscUnknownError", "Unknown error"); + case kgscNetworkBusy: return presentation(fmt, "kgscNetworkBusy", "Network busy"); + case kgscInvalidDestinationAddress: return presentation(fmt, "kgscInvalidDestinationAddress", "Invalid destination address"); + case kgscInvalidMessageBodyLength: return presentation(fmt, "kgscInvalidMessageBodyLength", "Invalid message body length"); + case kgscPhoneIsNotInService: return presentation(fmt, "kgscPhoneIsNotInService", "Phone is not in service"); + case kgscInvalidPreferredMemStorage: return presentation(fmt, "kgscInvalidPreferredMemStorage", "Invalid preferred memory storage"); + case kgscUserTerminated: return presentation(fmt, "kgscUserTerminated", "User terminated"); + } + + throw internal_not_found(); +} + +std::string Verbose::q931ProgressIndication(KQ931ProgressIndication code, Verbose::Presentation fmt) +{ + try + { + return internal_q931ProgressIndication(code); + } + catch (internal_not_found & e) + { + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KQ931ProgressIndication='%d']") % (int)code), + STG(FMT("Unknown Q931 progress indication (%d)") % (int)code)); + } +} + +std::string Verbose::internal_q931ProgressIndication(KQ931ProgressIndication code, Verbose::Presentation fmt) +{ + switch (code) + { + case kq931pTonesMaybeAvailable: return presentation(fmt, "kq931pTonesMaybeAvailable", "Tones may be available"); + case kq931pDestinationIsNonIsdn: return presentation(fmt, "kq931pDestinationIsNonIsdn", "Destination is not ISDN"); + case kq931pOriginationIsNonIsdn: return presentation(fmt, "kq931pOriginationIsNonIsdn", "Origination is not ISDN"); + case kq931pCallReturnedToIsdn: return presentation(fmt, "kq931pCallReturnedToIsdn", "Call returned to ISDN"); + case kq931pTonesAvailable: return presentation(fmt, "kq931pTonesAvailable", "Tones available"); + } + + throw internal_not_found(); +} + +#endif /* K3L_AT_LEAST(1,6,0) */ + + + + +#if K3L_AT_LEAST(2,1,0) +std::string Verbose::faxResult(KFaxResult code, Verbose::Presentation fmt) +{ + switch (code) + { + case kfaxrEndOfTransmission: return presentation(fmt, "kfaxrEndOfTransmission", "EndOfTransmission"); + case kfaxrStoppedByCommand: return presentation(fmt, "kfaxrStoppedByCommand", "StoppedByCommand"); + case kfaxrProtocolTimeout: return presentation(fmt, "kfaxrProtocolTimeout", "ProtocolTimeout"); + case kfaxrProtocolError: return presentation(fmt, "kfaxrProtocolError", "ProtocolError"); + case kfaxrRemoteDisconnection: return presentation(fmt, "kfaxrRemoteDisconnection", "RemoteDisconnection"); + case kfaxrFileError: return presentation(fmt, "kfaxrFileError", "FileError"); + case kfaxrUnknown: return presentation(fmt, "kfaxrUnknown", "Unknown"); + case kfaxrEndOfReception: return presentation(fmt, "kfaxrEndOfReception", "EndOfReception"); + case kfaxrCompatibilityError: return presentation(fmt, "kfaxrCompatibilityError", "CompatibilityError"); + case kfaxrQualityError: return presentation(fmt, "kfaxrQualityError", "QualityError"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KFaxResult='%d']") % (int)code), + STG(FMT("Unknown fax result (%d)") % (int)code)); +} + +std::string Verbose::faxFileErrorCause(KFaxFileErrorCause code, Verbose::Presentation fmt) +{ + switch (code) + { + case kfaxfecTransmissionStopped: return presentation(fmt, "kfaxfecTransmissionStopped", "TransmissionStopped"); + case kfaxfecTransmissionError: return presentation(fmt, "kfaxfecTransmissionError", "TransmissionError"); + case kfaxfecListCleared: return presentation(fmt, "kfaxfecListCleared", "ListCleared"); + case kfaxfecCouldNotOpen: return presentation(fmt, "kfaxfecCouldNotOpen", "CouldNotOpen"); + case kfaxfecInvalidHeader: return presentation(fmt, "kfaxfecInvalidHeader", "InvalidHeader"); + case kfaxfecDataNotFound: return presentation(fmt, "kfaxfecDataNotFound", "DataNotFound"); + case kfaxfecInvalidHeight: return presentation(fmt, "kfaxfecInvalidHeight", "InvalidHeight"); + case kfaxfecUnsupportedWidth: return presentation(fmt, "kfaxfecUnsupportedWidth", "UnsupportedWidth"); + case kfaxfecUnsupportedCompression: return presentation(fmt, "kfaxfecUnsupportedCompression", "UnsupportedCompression"); + case kfaxfecUnsupportedRowsPerStrip: return presentation(fmt, "kfaxfecUnsupportedRowsPerStrip", "UnsupportedRowsPerStrip"); + case kfaxfecUnknown: return presentation(fmt, "kfaxfecUnknown", "Unknown"); + } + + PRESENTATION_CHECK_RETURN(fmt, + STG(FMT("[KFaxFileErrorCause='%d']") % (int)code), + STG(FMT("Unknown fax file error cause (%d)") % (int)code)); +} + +#endif + + +/********/ + +std::string Verbose::commandName(int32 code) +{ + switch ((kcommand)code) + { + case K_CM_SEIZE: return "CM_SEIZE"; + case K_CM_SYNC_SEIZE: return "CM_SYNC_SEIZE"; + case K_CM_DIAL_DTMF: return "CM_DIAL_DTMF"; +#if K3L_AT_LEAST(1,6,0) + case K_CM_SIP_REGISTER: return "CM_SIP_REGISTER"; +#endif + case K_CM_DISCONNECT: return "CM_DISCONNECT"; + case K_CM_CONNECT: return "CM_CONNECT"; + case K_CM_PRE_CONNECT: return "CM_PRE_CONNECT"; + case K_CM_CAS_CHANGE_LINE_STT: return "CM_CAS_CHANGE_LINE_STT"; + case K_CM_CAS_SEND_MFC: return "CM_CAS_SEND_MFC"; + case K_CM_SET_FORWARD_CHANNEL: return "CM_SET_FORWARD_CHANNEL"; + case K_CM_CAS_SET_MFC_DETECT_MODE: return "CM_CAS_SET_MFC_DETECT_MODE"; + case K_CM_DROP_COLLECT_CALL: return "CM_DROP_COLLECT_CALL"; + +#if K3L_AT_LEAST(1,5,0) + case K_CM_MAKE_CALL: return "CM_MAKE_CALL"; +#endif + +#if K3L_AT_LEAST(1,4,0) + case K_CM_RINGBACK: return "CM_RINGBACK"; +#endif + +#if K3L_AT_LEAST(1,5,1) + case K_CM_USER_INFORMATION: return "CM_USER_INFORMATION"; +#endif + +#if K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(2,2,0) + case K_CM_VOIP_SEIZE: return "CM_VOIP_SEIZE"; + +#if !K3L_AT_LEAST(2,0,0) + /* internal commands */ + case K_CM_VOIP_START_DEBUG: return "CM_VOIP_START_DEBUG"; + case K_CM_VOIP_STOP_DEBUG: return "CM_VOIP_STOP_DEBUG"; + case K_CM_VOIP_DUMP_STAT: return "CM_VOIP_DUMP_STAT"; +#endif +#endif + +#if K3L_AT_LEAST(1,5,2) && !K3L_AT_LEAST(2,0,0) + /* internal command */ + case K_CM_ISDN_DEBUG: return "CM_ISDN_DEBUG"; +#endif + + case K_CM_LOCK_INCOMING: return "CM_LOCK_INCOMING"; + case K_CM_UNLOCK_INCOMING: return "CM_UNLOCK_INCOMING"; + case K_CM_LOCK_OUTGOING: return "CM_LOCK_OUTGOING"; + case K_CM_UNLOCK_OUTGOING: return "CM_UNLOCK_OUTGOING"; + + case K_CM_START_SEND_FAIL: return "CM_START_SEND_FAIL"; + case K_CM_STOP_SEND_FAIL: return "CM_STOP_SEND_FAIL"; + +#if K3L_AT_LEAST(1,5,3) + case K_CM_END_OF_NUMBER: return "CM_END_OF_NUMBER"; +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_CM_SS_TRANSFER: return "CM_SS_TRANSFER"; + case K_CM_GET_SMS: return "CM_GET_SMS"; + case K_CM_PREPARE_SMS: return "CM_PREPARE_SMS"; + case K_CM_SEND_SMS: return "CM_SEND_SMS"; +#endif +#if K3L_HAS_MPTY_SUPPORT + case K_CM_HOLD_SWITCH: return "CM_HOLD_SWITCH"; + case K_CM_MPTY_CONF: return "CM_MPTY_CONF"; + case K_CM_MPTY_SPLIT: return "CM_MPTY_SPLIT"; +#endif + + case K_CM_ENABLE_DTMF_SUPPRESSION: return "CM_ENABLE_DTMF_SUPPRESSION"; + case K_CM_DISABLE_DTMF_SUPPRESSION: return "CM_DISABLE_DTMF_SUPPRESSION"; + case K_CM_ENABLE_AUDIO_EVENTS: return "CM_ENABLE_AUDIO_EVENTS"; + case K_CM_DISABLE_AUDIO_EVENTS: return "CM_DISABLE_AUDIO_EVENTS"; + case K_CM_ENABLE_CALL_PROGRESS: return "CM_ENABLE_CALL_PROGRESS"; + case K_CM_DISABLE_CALL_PROGRESS: return "CM_DISABLE_CALL_PROGRESS"; + case K_CM_FLASH: return "CM_FLASH"; + case K_CM_ENABLE_PULSE_DETECTION: return "CM_ENABLE_PULSE_DETECTION"; + case K_CM_DISABLE_PULSE_DETECTION: return "CM_DISABLE_PULSE_DETECTION"; + case K_CM_ENABLE_ECHO_CANCELLER: return "CM_ENABLE_ECHO_CANCELLER"; + case K_CM_DISABLE_ECHO_CANCELLER: return "CM_DISABLE_ECHO_CANCELLER"; + case K_CM_ENABLE_AGC: return "CM_ENABLE_AGC"; + case K_CM_DISABLE_AGC: return "CM_DISABLE_AGC"; + case K_CM_ENABLE_HIGH_IMP_EVENTS: return "CM_ENABLE_HIGH_IMP_EVENTS"; + case K_CM_DISABLE_HIGH_IMP_EVENTS: return "CM_DISABLE_HIGH_IMP_EVENTS"; + +#if K3L_AT_LEAST(1,6,0) + case K_CM_ENABLE_CALL_ANSWER_INFO: return "CM_ENABLE_CALL_ANSWER_INFO"; + case K_CM_DISABLE_CALL_ANSWER_INFO: return "CM_DISABLE_CALL_ANSWER_INFO"; +#endif + + case K_CM_RESET_LINK: return "CM_RESET_LINK"; + +#if K3L_AT_LEAST(1,6,0) + case K_CM_CLEAR_LINK_ERROR_COUNTER: return "CM_CLEAR_LINK_ERROR_COUNTER"; +#endif + + case K_CM_SEND_DTMF: return "CM_SEND_DTMF"; + case K_CM_STOP_AUDIO: return "CM_STOP_AUDIO"; + case K_CM_HARD_RESET: return "CM_HARD_RESET"; + + case K_CM_SEND_TO_CTBUS: return "CM_SEND_TO_CTBUS"; + case K_CM_RECV_FROM_CTBUS: return "CM_RECV_FROM_CTBUS"; + case K_CM_SETUP_H100: return "CM_SETUP_H100"; + + case K_CM_MIXER: return "CM_MIXER"; + case K_CM_CLEAR_MIXER: return "CM_CLEAR_MIXER"; + case K_CM_PLAY_FROM_FILE: return "CM_PLAY_FROM_FILE"; + case K_CM_RECORD_TO_FILE: return "CM_RECORD_TO_FILE"; + case K_CM_PLAY_FROM_STREAM: return "CM_PLAY_FROM_STREAM"; + case K_CM_STOP_PLAY: return "CM_STOP_PLAY"; + case K_CM_STOP_RECORD: return "CM_STOP_RECORD"; + case K_CM_PAUSE_PLAY: return "CM_PAUSE_PLAY"; + case K_CM_PAUSE_RECORD: return "CM_PAUSE_RECORD"; + case K_CM_INCREASE_VOLUME: return "CM_INCREASE_VOLUME"; + case K_CM_DECREASE_VOLUME: return "CM_DECREASE_VOLUME"; + case K_CM_LISTEN: return "CM_LISTEN"; + case K_CM_STOP_LISTEN: return "CM_STOP_LISTEN"; + case K_CM_PREPARE_FOR_LISTEN: return "CM_PREPARE_FOR_LISTEN"; + + case K_CM_PLAY_SOUND_CARD: return "CM_PLAY_SOUND_CARD"; + case K_CM_STOP_SOUND_CARD: return "CM_STOP_SOUND_CARD"; + + case K_CM_MIXER_CTBUS: return "CM_MIXER_CTBUS"; + case K_CM_PLAY_FROM_STREAM_EX: return "CM_PLAY_FROM_STREAM_EX"; + case K_CM_ENABLE_PLAYER_AGC: return "CM_ENABLE_PLAYER_AGC"; + case K_CM_DISABLE_PLAYER_AGC: return "CM_DISABLE_PLAYER_AGC"; + case K_CM_START_STREAM_BUFFER: return "CM_START_STREAM_BUFFER"; + case K_CM_ADD_STREAM_BUFFER: return "CM_ADD_STREAM_BUFFER"; + case K_CM_STOP_STREAM_BUFFER: return "CM_STOP_STREAM_BUFFER"; + case K_CM_SEND_BEEP: return "CM_SEND_BEEP"; + case K_CM_SEND_BEEP_CONF: return "CM_SEND_BEEP_CONF"; + case K_CM_ADD_TO_CONF: return "CM_ADD_TO_CONF"; + case K_CM_REMOVE_FROM_CONF: return "CM_REMOVE_FROM_CONF"; + case K_CM_RECORD_TO_FILE_EX: return "CM_RECORD_TO_FILE_EX"; + +#if K3L_AT_LEAST(1,5,4) + case K_CM_SET_VOLUME: return "CM_SET_VOLUME"; +#endif + case K_CM_SET_LINE_CONDITION: return "CM_SET_LINE_CONDITION"; + case K_CM_SEND_LINE_CONDITION: return "CM_SEND_LINE_CONDITION"; + case K_CM_SET_CALLER_CATEGORY: return "CM_SET_CALLER_CATEGORY"; + case K_CM_DIAL_MFC: return "CM_DIAL_MFC"; + + case K_CM_INTERNAL_PLAY: return "CM_INTERNAL_PLAY"; + case K_CM_RESUME_PLAY: return "CM_RESUME_PLAY"; + case K_CM_RESUME_RECORD: return "CM_RESUME_RECORD"; + case K_CM_INTERNAL_PLAY_EX: return "CM_INTERNAL_PLAY_EX"; +#if !K3L_AT_LEAST(2,0,0) + case K_CM_PING: return "CM_PING"; +#if K3L_AT_LEAST(1,6,0) + case K_CM_LOG_REQUEST: return "CM_LOG_REQUEST"; + case K_CM_LOG_CREATE_DISPATCHER: return "CM_LOG_CREATE_DISPATCHER"; + case K_CM_LOG_DESTROY_DISPATCHER: return "CM_LOG_DESTROY_DISPATCHER"; +#endif +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_CM_START_CADENCE: return "CM_START_CADENCE"; + case K_CM_STOP_CADENCE: return "CM_STOP_CADENCE"; + case K_CM_CHECK_NEW_SMS: return "CM_CHECK_NEW_SMS"; + case K_CM_SEND_TO_MODEM: return "CM_SEND_TO_MODEM"; +#endif +#if K3L_AT_LEAST(2,1,0) + case K_CM_START_FAX_TX: return "CM_START_FAX_TX"; + case K_CM_STOP_FAX_TX: return "CM_STOP_FAX_TX"; + case K_CM_ADD_FAX_FILE: return "CM_ADD_FAX_FILE"; + case K_CM_ADD_FAX_PAGE_BREAK: return "CM_ADD_FAX_PAGE_BREAK"; + case K_CM_START_FAX_RX: return "CM_START_FAX_RX"; + case K_CM_STOP_FAX_RX: return "CM_STOP_FAX_RX"; + case K_CM_SIM_CARD_SELECT: return "CM_SIM_CARD_SELECT"; +#endif + +#if K3L_AT_LEAST(2,1,0) + case K_CM_NOTIFY_WATCHDOG: return "CM_NOTIFY_WATCHDOG"; + case K_CM_STOP_WATCHDOG: return "CM_STOP_WATCHDOG"; + case K_CM_WATCHDOG_COUNT: return "CM_WATCHDOG_COUNT"; + case K_CM_START_WATCHDOG: return "CM_START_WATCHDOG"; +#endif + + } + + return STG(FMT("[command='%d']") % code); +} + +std::string Verbose::eventName(int32 code) +{ + switch ((kevent)code) + { + case K_EV_CHANNEL_FREE: return "EV_CHANNEL_FREE"; + case K_EV_CONNECT: return "EV_CONNECT"; + case K_EV_DISCONNECT: return "EV_DISCONNECT"; + case K_EV_CALL_SUCCESS: return "EV_CALL_SUCCESS"; + case K_EV_CALL_FAIL: return "EV_CALL_FAIL"; + case K_EV_NO_ANSWER: return "EV_NO_ANSWER"; + case K_EV_BILLING_PULSE: return "EV_BILLING_PULSE"; + case K_EV_SEIZE_SUCCESS: return "EV_SEIZE_SUCCESS"; + case K_EV_SEIZE_FAIL: return "EV_SEIZE_FAIL"; + case K_EV_SEIZURE_START: return "EV_SEIZURE_START"; + case K_EV_CAS_LINE_STT_CHANGED: return "EV_CAS_LINE_STT_CHANGED"; + case K_EV_CAS_MFC_RECV: return "EV_CAS_MFC_RECV"; + +#if K3L_AT_LEAST(1,5,0) + case K_EV_NEW_CALL: return "EV_NEW_CALL"; +#endif + +#if K3L_AT_LEAST(1,5,1) + case K_EV_USER_INFORMATION: return "EV_USER_INFORMATION"; +#endif + +#if K3L_AT_LEAST(1,5,3) + case K_EV_DIALED_DIGIT: return "EV_DIALED_DIGIT"; +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_SIP_REGISTER_INFO: return "EV_SIP_REGISTER_INFO"; +#endif + +#if K3L_AT_LEAST(1,4,0) + case K_EV_CALL_HOLD_START: return "EV_CALL_HOLD_START"; + case K_EV_CALL_HOLD_STOP: return "EV_CALL_HOLD_STOP"; +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_SS_TRANSFER_FAIL: return "EV_SS_TRANSFER_FAIL"; + case K_EV_FLASH: return "EV_FLASH"; +#endif + + case K_EV_DTMF_DETECTED: return "EV_DTMF_DETECTED"; + case K_EV_DTMF_SEND_FINISH: return "EV_DTMF_SEND_FINISH"; + case K_EV_AUDIO_STATUS: return "EV_AUDIO_STATUS"; + case K_EV_CADENCE_RECOGNIZED: return "EV_CADENCE_RECOGNIZED"; + + case K_EV_END_OF_STREAM: return "EV_END_OF_STREAM"; + case K_EV_PULSE_DETECTED: return "EV_PULSE_DETECTED"; + +#if K3L_AT_LEAST(1,5,1) + case K_EV_POLARITY_REVERSAL: return "EV_POLARITY_REVERSAL"; +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_ISDN_PROGRESS_INDICATOR: return "EV_ISDN_PROGRESS_INDICATOR"; + case K_EV_CALL_ANSWER_INFO: return "EV_CALL_ANSWER_INFO"; + case K_EV_COLLECT_CALL: return "EV_COLLECT_CALL"; + case K_EV_SIP_DTMF_DETECTED: return "EV_SIP_DTMF_DETECTED"; + + case K_EV_RECV_FROM_MODEM: return "EV_RECV_FROM_MODEM"; + case K_EV_NEW_SMS: return "EV_NEW_SMS"; + case K_EV_SMS_INFO: return "EV_SMS_INFO"; + case K_EV_SMS_DATA: return "EV_SMS_DATA"; + case K_EV_SMS_SEND_RESULT: return "EV_SMS_SEND_RESULT"; + case K_EV_RING_DETECTED: return "EV_RING_DETECTED"; + case K_EV_PHYSICAL_LINK_DOWN: return "EV_PHYSICAL_LINK_DOWN"; + case K_EV_PHYSICAL_LINK_UP: return "EV_PHYSICAL_LINK_UP"; +#endif +#if K3L_HAS_MPTY_SUPPORT + case K_EV_CALL_MPTY_START: return "EV_CALL_MPTY_START"; + case K_EV_CALL_MPTY_STOP: return "EV_CALL_MPTY_STOP"; + case K_EV_GSM_COMMAND_STATUS: return "EV_GSM_COMMAND_STATUS"; +#endif +#if !K3L_AT_LEAST(2,0,0) + case K_EV_PONG: return "EV_PONG"; +#endif + case K_EV_CHANNEL_FAIL: return "EV_CHANNEL_FAIL"; + case K_EV_REFERENCE_FAIL: return "EV_REFERENCE_FAIL"; + case K_EV_INTERNAL_FAIL: return "EV_INTERNAL_FAIL"; + case K_EV_HARDWARE_FAIL: return "EV_HARDWARE_FAIL"; + case K_EV_LINK_STATUS: return "EV_LINK_STATUS"; + +#if K3L_AT_LEAST(1,4,0) + case K_EV_CLIENT_RECONNECT: return "EV_CLIENT_RECONNECT"; + case K_EV_VOIP_SEIZURE: return "EV_VOIP_SEIZURE"; +#endif + case K_EV_SEIZURE: return "EV_SEIZURE"; +#if K3L_AT_LEAST(2,1,0) + case K_EV_FAX_CHANNEL_FREE: return "EV_FAX_CHANNEL_FREE"; + case K_EV_FAX_FILE_SENT: return "EV_FAX_FILE_SENT"; + case K_EV_FAX_FILE_FAIL: return "EV_FAX_FILE_FAIL"; + /*case K_EV_FAX_MESSAGE_CONFIRMATION:return "EV_FAX_MESSAGE_CONFIRMATION";*/ + case K_EV_FAX_TX_TIMEOUT: return "EV_FAX_TX_TIMEOUT"; + case K_EV_FAX_PAGE_CONFIRMATION:return "EV_FAX_PAGE_CONFIRMATION"; + case K_EV_FAX_REMOTE_INFO: return "EV_FAX_REMOTE_INFO"; +#endif + +#if K3L_AT_LEAST(2,1,0) + case K_EV_WATCHDOG_COUNT: return "EV_WATCHDOG_COUNT"; +#endif + } + + return STG(FMT("[event='%d']") % code); +} + + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::command(int32 dev, K3L_COMMAND *k3lcmd, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::command(int32 dev, K3L_COMMAND *k3lcmd, Verbose::Presentation fmt) +#endif +{ +#if K3L_AT_LEAST(2,0,0) + return command(k3lcmd->Cmd, dev, k3lcmd->Object, (const char *) k3lcmd->Params, r2_country, fmt); +#else + return command(k3lcmd->Cmd, dev, k3lcmd->Object, (const char *) k3lcmd->Params, fmt); +#endif +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const char * params, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::command(int32 cmd_code, int32 dev_idx, int32 obj_idx, const char * params, Verbose::Presentation fmt) +#endif +{ + unsigned short int dev = (unsigned short int) dev_idx; + unsigned short int obj = (unsigned short int) obj_idx; + + kcommand code = (kcommand) cmd_code; + + std::string buf, extra; + + switch (code) + { + case K_CM_SEIZE: + case K_CM_SYNC_SEIZE: + //case K_CM_VOIP_SEIZE://deprecated + case K_CM_DIAL_MFC: + case K_CM_DIAL_DTMF: + + case K_CM_CONNECT: + case K_CM_PRE_CONNECT: + case K_CM_DISCONNECT: + case K_CM_DROP_COLLECT_CALL: + + case K_CM_START_SEND_FAIL: + case K_CM_STOP_SEND_FAIL: + + case K_CM_ENABLE_DTMF_SUPPRESSION: + case K_CM_DISABLE_DTMF_SUPPRESSION: + case K_CM_ENABLE_AUDIO_EVENTS: + case K_CM_DISABLE_AUDIO_EVENTS: + case K_CM_ENABLE_CALL_PROGRESS: + case K_CM_DISABLE_CALL_PROGRESS: + case K_CM_ENABLE_PULSE_DETECTION: + case K_CM_DISABLE_PULSE_DETECTION: + case K_CM_ENABLE_ECHO_CANCELLER: + case K_CM_DISABLE_ECHO_CANCELLER: + case K_CM_ENABLE_AGC: + case K_CM_DISABLE_AGC: + case K_CM_ENABLE_HIGH_IMP_EVENTS: + case K_CM_DISABLE_HIGH_IMP_EVENTS: + + case K_CM_FLASH: + case K_CM_RESET_LINK: + case K_CM_CLEAR_MIXER: + + case K_CM_LOCK_INCOMING: + case K_CM_UNLOCK_INCOMING: + case K_CM_LOCK_OUTGOING: + case K_CM_UNLOCK_OUTGOING: + + case K_CM_INCREASE_VOLUME: + case K_CM_DECREASE_VOLUME: + + case K_CM_STOP_RECORD: + case K_CM_PAUSE_RECORD: + case K_CM_RESUME_RECORD: + + case K_CM_STOP_LISTEN: + + case K_CM_PLAY_SOUND_CARD: + case K_CM_STOP_SOUND_CARD: + case K_CM_RINGBACK: +#if K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(2,0,0) + case K_CM_VOIP_START_DEBUG: + case K_CM_VOIP_STOP_DEBUG: + case K_CM_VOIP_DUMP_STAT: +#endif + +#if K3L_AT_LEAST(1,5,3) + case K_CM_END_OF_NUMBER: +#endif + +#if K3L_AT_LEAST(1,5,4) + case K_CM_SET_VOLUME: +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_CM_ENABLE_CALL_ANSWER_INFO: + case K_CM_DISABLE_CALL_ANSWER_INFO: + + case K_CM_SS_TRANSFER: + + case K_CM_CHECK_NEW_SMS: + case K_CM_GET_SMS: + case K_CM_PREPARE_SMS: + case K_CM_SEND_SMS: + + case K_CM_START_CADENCE: + case K_CM_STOP_CADENCE: + case K_CM_SEND_TO_MODEM: +#endif +#if K3L_HAS_MPTY_SUPPORT + case K_CM_HOLD_SWITCH: + case K_CM_MPTY_CONF: + case K_CM_MPTY_SPLIT: +#endif +#if K3L_AT_LEAST(2,1,0) + case K_CM_SIM_CARD_SELECT: +#endif + if (params != NULL) + { + extra += "param='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + else + { + return show(buf, commandName(code), Target(CHANNEL, dev, obj)); + } + + case K_CM_SEND_DTMF: /* ?? */ + return show(buf, commandName(code), Target(CHANNEL, dev, obj)); + + /****/ + + case K_CM_STOP_AUDIO: + extra = "stop='"; + switch ((params ? (int)(*params) : -1)) + { + case 1: extra += "tx"; + case 2: extra += "rx"; + case 3: extra += "tx+rx"; + default: extra += ""; + } + extra = "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + + /****/ + +#if K3L_AT_LEAST(1,5,2) && !K3L_AT_LEAST(2,0,0) + case K_CM_ISDN_DEBUG: + extra = "flags='"; + extra += isdnDebug((unsigned long)params); + extra += "'"; + + return show(buf, commandName(code), Target(NONE), extra); +#endif + + /****/ + +#if K3L_AT_LEAST(1,5,1) + case K_CM_USER_INFORMATION: +#endif + if (params != NULL) + { + KUserInformation * userinfo = (KUserInformation *)params; + + std::string tmp((const char*) userinfo->UserInfo, userinfo->UserInfoLength); + + extra = STG(FMT("proto='%d',length='%d',data='%s'") + % userinfo->ProtocolDescriptor % userinfo->UserInfoLength % tmp); + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + else + { + return show(buf, commandName(code), Target(CHANNEL, dev, obj)); + } + + /****/ + + + + case K_CM_CAS_CHANGE_LINE_STT: + { + const char status = (params ? *params : 0x00); + + extra += "status='"; + extra += (status & 0x01 ? "1" : "0"); + extra += (status & 0x02 ? "1" : "0"); + extra += (status & 0x04 ? "1" : "0"); + extra += (status & 0x08 ? "1" : "0"); + extra += "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + + case K_CM_CAS_SEND_MFC: + { + char mfc = (params ? *params : 0xff); + + extra = STG(FMT("mfc='%d'") % (int) mfc); + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + + case K_CM_CAS_SET_MFC_DETECT_MODE: + { + int mode = (params ? *((int *)params) : -1); + + extra = STG(FMT("mode='%d'") % mode); + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + + case K_CM_SET_FORWARD_CHANNEL: + { + int channel = (params ? *((int*) params) : -1); + + extra = STG(FMT("forward='%03d'") % channel); + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + +#if K3L_AT_LEAST(1,5,0) + case K_CM_MAKE_CALL: + extra = "options='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); +#endif + + case K_CM_MIXER: + case K_CM_MIXER_CTBUS: + { + if (params) + { + KMixerCommand *m = (KMixerCommand*)params; + + std::string src = mixerSource((KMixerSource)m->Source); + std::string idx(""); + + switch (m->Source) + { + case kmsChannel: + case kmsPlay: + case kmsCTbus: +#if (K3L_AT_LEAST(1,4,0) && !K3L_AT_LEAST(1,6,0)) + case kmsVoIP: +#endif +#if K3L_AT_LEAST(1,6,0) + case kmsNoDelayChannel: +#endif + idx = STG(FMT("%02d") % (int)m->SourceIndex); + break; + + case kmsGenerator: + idx = mixerTone((KMixerTone)m->SourceIndex); + break; + }; + + extra = STG(FMT("track='%d',src='%s',index='%s'") % (int)m->Track % src % idx); + } + else + { + extra = ""; + } + + return show(buf, commandName(code), Target(MIXER, dev, obj), extra); + }; + + case K_CM_PLAY_FROM_FILE: + extra = "file='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + + case K_CM_RECORD_TO_FILE: + extra = "file='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + + case K_CM_RECORD_TO_FILE_EX: + extra = "params='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + + case K_CM_PLAY_FROM_STREAM: + case K_CM_ADD_STREAM_BUFFER: + { + struct buffer_param + { + const void * ptr; + const int size; + } + *p = (buffer_param *) params; + + std::stringstream stream; + + extra = STG(FMT("buffer='%p',size='%d'") + % (const void *) p->ptr % (const int) p->size); + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + } + + case K_CM_PLAY_FROM_STREAM_EX: + { + struct buffer_param + { + const void * ptr; + const int size; + const char codec; + } + *p = (buffer_param *) params; + + std::string codec; + + switch (p->codec) + { + case 0: codec = "A-Law"; + case 1: codec = "PCM-08khz"; + case 2: codec = "PCM-11khz"; + default: codec = ""; + } + + std::stringstream stream; + + extra = STG(FMT("buffer='%p',size='%d',codec='%s'") + % (const void *) p->ptr % (const int) p->size % codec); + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + } + + case K_CM_STOP_PLAY: + case K_CM_PAUSE_PLAY: + case K_CM_RESUME_PLAY: + + case K_CM_START_STREAM_BUFFER: + case K_CM_STOP_STREAM_BUFFER: + + case K_CM_ENABLE_PLAYER_AGC: + case K_CM_DISABLE_PLAYER_AGC: + + case K_CM_SEND_BEEP: + case K_CM_SEND_BEEP_CONF: + + case K_CM_INTERNAL_PLAY: + case K_CM_INTERNAL_PLAY_EX: + return show(buf, commandName(code), Target(PLAYER, dev, obj)); + + case K_CM_ADD_TO_CONF: + extra += "conference='"; + extra += (params ? (int) (*params) : -1); + extra += "'"; + + return show(buf, commandName(code), Target(MIXER, dev, obj), extra); + + case CM_REMOVE_FROM_CONF: + return show(buf, commandName(code), Target(MIXER, dev, obj)); + + case K_CM_LISTEN: + case K_CM_PREPARE_FOR_LISTEN: + { + int msecs = (params ? *((int*)params) : -1); + + extra = STG(FMT("msecs='%d'") % msecs); + + return show(buf, commandName(code), Target(PLAYER, dev, obj), extra); + } + + case K_CM_SEND_TO_CTBUS: + case K_CM_RECV_FROM_CTBUS: + { + KCtbusCommand *p = (KCtbusCommand*)(params); + + extra = STG(FMT("stream='%02d',timeslot='%02d',enable='%d'") + % (int)p->Stream % (int)p->TimeSlot % (int)p->Enable); + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + } + + case K_CM_SET_LINE_CONDITION: + case K_CM_SEND_LINE_CONDITION: + extra = "condition='"; +#if K3L_AT_LEAST(2,0,0) + extra += signGroupB((KSignGroupB) *((int *) params), r2_country); +#else + extra += signGroupB((KSignGroupB) *((int *) params)); +#endif + extra += "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + + case K_CM_SET_CALLER_CATEGORY: + extra = "category='"; +#if K3L_AT_LEAST(2,0,0) + extra += signGroupII((KSignGroupII) *((int *) params), r2_country); +#else + extra += signGroupII((KSignGroupII) *((int *) params)); +#endif + extra += "'"; + + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + +#if K3L_AT_LEAST(1,6,0) + case K_CM_CLEAR_LINK_ERROR_COUNTER: + return show(buf, commandName(code), Target(LINK, dev, obj)); + + case K_CM_SIP_REGISTER: + if (params != NULL) + { + extra += "param='"; + extra += (params ? params : ""); + extra += "'"; + + return show(buf, commandName(code), Target(DEVICE, dev), extra); + } + else + { + return show(buf, commandName(code), Target(DEVICE, dev)); + } +#endif + + case K_CM_SETUP_H100: + extra += "option='"; + extra += h100configIndex((KH100ConfigIndex)obj_idx); + extra += "'value='"; + extra += (params ? STG(FMT("%02d") % (int)(*params)) : ""); + extra += "'"; + + return show(buf, commandName(code), Target(DEVICE, dev), extra); + + case K_CM_HARD_RESET: + return show(buf, commandName(code), Target(LINK, dev, obj)); + +#if !K3L_AT_LEAST(2,0,0) + /* como funciona? */ + case K_CM_LOG_REQUEST: + case K_CM_LOG_CREATE_DISPATCHER: + case K_CM_LOG_DESTROY_DISPATCHER: + + case K_CM_PING: +#endif + return show(buf, commandName(code), Target(NONE)); +#if K3L_AT_LEAST(2,1,0) + case K_CM_START_FAX_TX: + case K_CM_START_FAX_RX: + case K_CM_ADD_FAX_FILE: + extra = "params='"; + extra += (params ? params : ""); + extra += "'"; + return show(buf, commandName(code), Target(CHANNEL, dev, obj), extra); + case K_CM_STOP_FAX_TX: + case K_CM_STOP_FAX_RX: + case K_CM_ADD_FAX_PAGE_BREAK: + return show(buf, commandName(code), Target(CHANNEL, dev, obj)); +#endif + +#if K3L_AT_LEAST(2,1,0) + case K_CM_NOTIFY_WATCHDOG: + case K_CM_STOP_WATCHDOG: + case K_CM_START_WATCHDOG: + return show(buf, commandName(code) , Target(DEVICE, obj)); + case K_CM_WATCHDOG_COUNT: + return show(buf, commandName(code) , Target(NONE)); +#endif + + } + + /* default command handler */ + return show(buf, commandName(code), Target(CHANNEL, dev, obj)); +} + +#if K3L_AT_LEAST(2,0,0) +std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, R2CountryType r2_country, Verbose::Presentation fmt) +#else +std::string Verbose::event(KSignaling sig, int32 obj_idx, K3L_EVENT *ev, Verbose::Presentation fmt) +#endif +{ + unsigned short int dev = (unsigned short int) ev->DeviceId; + unsigned short int obj = (unsigned short int) obj_idx; + + kevent code = (kevent) ev->Code; + + std::string buf, extra; + + switch (code) + { + case K_EV_CHANNEL_FREE: + case K_EV_SEIZE_SUCCESS: + case K_EV_CALL_SUCCESS: + case K_EV_NO_ANSWER: + case K_EV_CONNECT: + case K_EV_DTMF_SEND_FINISH: + case K_EV_SEIZURE_START: + case K_EV_BILLING_PULSE: + case K_EV_REFERENCE_FAIL: + +#if K3L_AT_LEAST(1,4,0) + case K_EV_CALL_HOLD_START: + case K_EV_CALL_HOLD_STOP: +#endif + +#if K3L_AT_LEAST(1,5,0) + case K_EV_NEW_CALL: +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_FLASH: + case K_EV_POLARITY_REVERSAL: + case K_EV_COLLECT_CALL: + case K_EV_SS_TRANSFER_FAIL: + case K_EV_RING_DETECTED: +#endif +#if K3L_HAS_MPTY_SUPPORT + case K_EV_CALL_MPTY_START: + case K_EV_CALL_MPTY_STOP: +#endif + break; + +#if K3L_AT_LEAST(1,6,0) + case K_EV_RECV_FROM_MODEM: + case K_EV_SMS_INFO: + case K_EV_SMS_DATA: + extra = "data='"; + extra += (ev->Params ? (const char *)(ev->Params) : ""); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_SMS_SEND_RESULT: + extra = "result='"; +#if K3L_AT_LEAST(2,0,0) + extra += gsmSmsCause((KGsmSmsCause)ev->AddInfo); +#else + extra += gsmCallCause((KGsmCallCause)ev->AddInfo); +#endif + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + +#if K3L_HAS_MPTY_SUPPORT + case K_EV_GSM_COMMAND_STATUS: + extra = "result='"; + extra += gsmMobileCause((KGsmMobileCause)ev->AddInfo); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); +#endif + + case K_EV_CALL_ANSWER_INFO: + extra = "info='"; + extra += callStartInfo((KCallStartInfo)ev->AddInfo); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_NEW_SMS: + if (ev->AddInfo != 0) + { + extra = "messages='"; + extra += STG(FMT("%d") % ev->AddInfo); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } + else + { + return show(buf, eventName(code), Target(CHANNEL, dev, obj)); + } + + case K_EV_ISDN_PROGRESS_INDICATOR: + if (ev->AddInfo != 0) + { + extra = "indication='"; + extra += q931ProgressIndication((KQ931ProgressIndication)ev->AddInfo); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } + else + { + return show(buf, eventName(code), Target(CHANNEL, dev, obj)); + } +#endif + + case K_EV_CAS_LINE_STT_CHANGED: + extra = STG(FMT("[a=%d,b=%d,c=%d,d=%d]") + % ((ev->AddInfo & 0x8) >> 3) % ((ev->AddInfo & 0x4) >> 2) + % ((ev->AddInfo & 0x2) >> 1) % (ev->AddInfo & 0x1)); + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_CAS_MFC_RECV: + extra = STG(FMT("digit='%d'") % ev->AddInfo); + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_CALL_FAIL: + extra = "cause='"; +#if K3L_AT_LEAST(2,0,0) + extra += callFail(sig, r2_country, ev->AddInfo); +#else + extra += callFail(sig, ev->AddInfo); +#endif + extra += "'"; + + if (ev->Params != NULL && ev->ParamSize != 0) + { + if (!extra.empty()) + extra += ","; + + extra += "params='"; + extra += (const char *) ev->Params; + extra += "'"; + } + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_DISCONNECT: + switch (sig) + { +#if K3L_AT_LEAST(1,5,1) + case ksigOpenCCS: + case ksigPRI_EndPoint: + case ksigPRI_Network: + case ksigPRI_Passive: + extra = "cause='"; + extra += isdnCause((KQ931Cause) ev->AddInfo); + extra += "'"; +#endif + default: + break; + } + + if (ev->Params != NULL && ev->ParamSize != 0) + { + if (!extra.empty()) + extra += ","; + + extra += "params='"; + extra += (const char *) ev->Params; + extra += "'"; + } + + if (!extra.empty()) + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + else + return show(buf, eventName(code), Target(CHANNEL, dev, obj)); + + break; + +#if K3L_AT_LEAST(1,6,0) + case K_EV_SIP_DTMF_DETECTED: +#endif + case K_EV_DTMF_DETECTED: + case K_EV_PULSE_DETECTED: + case K_EV_DIALED_DIGIT: + extra = STG(FMT("digit='%c'") % (char)ev->AddInfo); + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_SEIZURE: + { + KIncomingSeizeParams *n = (KIncomingSeizeParams *) + ( ((char*)ev) + sizeof(K3L_EVENT) ); + + extra += "orig_addr='"; + extra += n->NumberA; + extra += "',dest_addr='"; + extra += n->NumberB; + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } + +#if K3L_AT_LEAST(1,4,0) + case K_EV_VOIP_SEIZURE: + { + char *numB = ((char*)ev) + sizeof(K3L_EVENT); + char *numA = numB + 61; + + extra = "numberA='"; + extra += numA; + extra += "',numberB='"; + extra += numB; + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } +#endif + + + case K_EV_END_OF_STREAM: + return show(buf, eventName(code), Target(PLAYER, dev, obj)); + + case K_EV_AUDIO_STATUS: + extra = "tone='"; + extra += mixerTone((KMixerTone)ev->AddInfo); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_CADENCE_RECOGNIZED: + extra = STG(FMT("cadence='%c'") % (char)(ev->AddInfo)); + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_CHANNEL_FAIL: + extra = "reason='"; + extra += channelFail(sig, ev->AddInfo); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_SEIZE_FAIL: + extra = "reason='"; + extra += seizeFail((KSeizeFail) ev->AddInfo); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_INTERNAL_FAIL: + extra = "reason='"; + extra += internalFail((KInternalFail) ev->AddInfo); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_HARDWARE_FAIL: + extra = "component='"; + extra += systemObject((KSystemObject) ev->AddInfo); + extra += "'"; + + switch (ev->AddInfo) + { + case ksoChannel: + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + case ksoLink: + return show(buf, eventName(code), Target(LINK, dev, obj), extra); + case ksoLinkMon: + case ksoH100: + case ksoFirmware: + case ksoDevice: + return show(buf, eventName(code), Target(DEVICE, dev), extra); + case ksoAPI: + return show(buf, eventName(code), Target(NONE), extra); + } + + + case K_EV_LINK_STATUS: + // EV_LINK_STATUS has always zero in ObjectInfo (and AddInfo!) + /* fall throught... */ + +#if K3L_AT_LEAST(1,6,0) + case K_EV_PHYSICAL_LINK_UP: + case K_EV_PHYSICAL_LINK_DOWN: + return show(buf, eventName(code), Target(LINK, dev, obj)); +#endif + +#if K3L_AT_LEAST(1,5,1) + case K_EV_USER_INFORMATION: + { + KUserInformation *info = (KUserInformation *)(ev->Params); + + std::string data((const char *)info->UserInfo, + std::min(info->UserInfoLength, KMAX_USER_USER_LEN)); + + extra = STG(FMT("proto='%d',length='%d',data='%s'") + % info->ProtocolDescriptor % info->UserInfoLength % data); + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } +#endif + +#if K3L_AT_LEAST(1,6,0) + case K_EV_SIP_REGISTER_INFO: + extra = "params='"; + extra += (ev->Params ? (const char *) (ev->Params) : ""); + extra += "',status='"; + extra += sipFailures((KSIP_Failures)(ev->AddInfo)); + extra += "'"; + + return show(buf, eventName(code), Target(DEVICE, dev), extra); +#endif + +#if !K3L_AT_LEAST(2,0,0) + case K_EV_PONG: +#endif + +#if K3L_AT_LEAST(1,4,0) + case K_EV_CLIENT_RECONNECT: +#endif + return show(buf, eventName(code), Target(NONE)); + +#if K3L_AT_LEAST(2,1,0) + case K_EV_FAX_CHANNEL_FREE: + extra = "status='"; + extra += faxResult((KFaxResult)ev->AddInfo); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_FAX_FILE_SENT: + extra = "filename='"; + extra += (ev->Params ? (const char *) (ev->Params) : ""); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_FAX_FILE_FAIL: + extra = "cause='"; + extra += faxFileErrorCause((KFaxFileErrorCause)ev->AddInfo); + extra += "',filename='"; + extra += (ev->Params ? (const char *) (ev->Params) : ""); + extra += "'"; + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + case K_EV_FAX_REMOTE_INFO: + extra = ((ev->Params && ev->ParamSize != 0) ? (const char *) ev->Params : ""); + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + + /*case K_EV_FAX_MESSAGE_CONFIRMATION:*/ + case K_EV_FAX_PAGE_CONFIRMATION: + case K_EV_FAX_TX_TIMEOUT: + return show(buf, eventName(code), Target(CHANNEL, dev, obj)); +#endif + +#if K3L_AT_LEAST(2,1,0) + case K_EV_WATCHDOG_COUNT: + extra = STG(FMT("count='%d'") % (char)ev->AddInfo); + return show(buf , eventName(code), Target(NONE), extra); +#endif + + } + + // default handler... + if (ev->Params != NULL && ev->ParamSize != 0) + { + extra += "params='"; + extra.append((const char *) ev->Params, (unsigned int) std::max(ev->ParamSize - 1, 0)); + extra += "'"; + + return show(buf, eventName(code), Target(CHANNEL, dev, obj), extra); + } + else + return show(buf, eventName(code), Target(CHANNEL, dev, obj)); +} + +/********************************************/ + +std::string Verbose::show(std::string & buf, std::string name, Target tgt, std::string & extra) +{ + if (tgt.type == NONE) + { + generate(buf, name, tgt, extra); + } + else + { + std::string tmp(","); + tmp += extra; + + generate(buf, name, tgt, tmp); + } + + return buf; +} + +std::string Verbose::show(std::string & buf, std::string name, Target tgt) +{ + std::string tmp(""); + + generate(buf, name, tgt, tmp); + return buf; +} + +void Verbose::generate(std::string &buf, std::string &name, Target tgt, std::string &extra) +{ + switch (tgt.type) + { + case NONE: + if (extra.empty()) + buf += STG(FMT("<%s>") % name); + else + buf += STG(FMT("<%s> (%s)") % name % extra); + break; + + case DEVICE: + buf += STG(FMT("<%s> (d=%02d%s)") + % name % tgt.device % extra); + break; + + default: + { + const char *kind = "o"; + + switch (tgt.type) + { + case CHANNEL: + kind = "c"; + break; + case PLAYER: + kind = "p"; + break; + case MIXER: + kind = "m"; + break; + case LINK: + kind = "l"; + default: + break; + } + + buf += STG(FMT("<%s> (d=%02d,%s=%03d%s)") + % name % tgt.device % kind % tgt.object % extra); + break; + } + } +} + diff --git a/src/mod/endpoints/mod_khomp/commons/verbose.hpp b/src/mod/endpoints/mod_khomp/commons/verbose.hpp new file mode 100644 index 0000000000..4668ea6a9f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/commons/verbose.hpp @@ -0,0 +1,505 @@ +/* + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2009 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file under + the MPL, indicate your decision by deleting the provisions above and replace them + with the notice and other provisions required by the LGPL License. If you do not + delete the provisions above, a recipient may use your version of this file under + either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include +#include + +#include + +// k3lApiMajorVersion +#ifndef CM_PING +# include +# include +#endif + +#include +#include +#include + +#ifndef _VERBOSE_HPP_ +#define _VERBOSE_HPP_ + +struct Verbose +{ + typedef enum + { + K_CM_SEIZE = CM_SEIZE, + K_CM_SYNC_SEIZE = CM_SYNC_SEIZE, +#if K3L_AT_LEAST(1,6,0) + K_CM_SIP_REGISTER = CM_SIP_REGISTER, +#endif + K_CM_DIAL_DTMF = CM_DIAL_DTMF, + K_CM_DISCONNECT = CM_DISCONNECT, + K_CM_CONNECT = CM_CONNECT, + K_CM_PRE_CONNECT = CM_PRE_CONNECT, + K_CM_CAS_CHANGE_LINE_STT = CM_CAS_CHANGE_LINE_STT, + K_CM_CAS_SEND_MFC = CM_CAS_SEND_MFC, + K_CM_SET_FORWARD_CHANNEL = CM_SET_FORWARD_CHANNEL, + K_CM_CAS_SET_MFC_DETECT_MODE = CM_CAS_SET_MFC_DETECT_MODE, + K_CM_DROP_COLLECT_CALL = CM_DROP_COLLECT_CALL, + K_CM_MAKE_CALL = CM_MAKE_CALL, + K_CM_RINGBACK = CM_RINGBACK, + K_CM_USER_INFORMATION = CM_USER_INFORMATION, +#if !K3L_AT_LEAST(2,2,0) + K_CM_VOIP_SEIZE = CM_VOIP_SEIZE, //deprecated +#endif + K_CM_LOCK_INCOMING = CM_LOCK_INCOMING, + K_CM_UNLOCK_INCOMING = CM_UNLOCK_INCOMING, + K_CM_LOCK_OUTGOING = CM_LOCK_OUTGOING, + K_CM_UNLOCK_OUTGOING = CM_UNLOCK_OUTGOING, + K_CM_START_SEND_FAIL = CM_START_SEND_FAIL, + K_CM_STOP_SEND_FAIL = CM_STOP_SEND_FAIL, + K_CM_END_OF_NUMBER = CM_END_OF_NUMBER, +#if K3L_AT_LEAST(1,6,0) + K_CM_SS_TRANSFER = CM_SS_TRANSFER, + K_CM_GET_SMS = CM_GET_SMS, + K_CM_PREPARE_SMS = CM_PREPARE_SMS, + K_CM_SEND_SMS = CM_SEND_SMS, +#endif +#if K3L_HAS_MPTY_SUPPORT + K_CM_HOLD_SWITCH = CM_HOLD_SWITCH, + K_CM_MPTY_CONF = CM_MPTY_CONF, + K_CM_MPTY_SPLIT = CM_MPTY_SPLIT, +#endif + K_CM_ENABLE_DTMF_SUPPRESSION = CM_ENABLE_DTMF_SUPPRESSION, + K_CM_DISABLE_DTMF_SUPPRESSION = CM_DISABLE_DTMF_SUPPRESSION, + K_CM_ENABLE_AUDIO_EVENTS = CM_ENABLE_AUDIO_EVENTS, + K_CM_DISABLE_AUDIO_EVENTS = CM_DISABLE_AUDIO_EVENTS, + K_CM_ENABLE_CALL_PROGRESS = CM_ENABLE_CALL_PROGRESS, + K_CM_DISABLE_CALL_PROGRESS = CM_DISABLE_CALL_PROGRESS, + K_CM_FLASH = CM_FLASH, + K_CM_ENABLE_PULSE_DETECTION = CM_ENABLE_PULSE_DETECTION, + K_CM_DISABLE_PULSE_DETECTION = CM_DISABLE_PULSE_DETECTION, + K_CM_ENABLE_ECHO_CANCELLER = CM_ENABLE_ECHO_CANCELLER, + K_CM_DISABLE_ECHO_CANCELLER = CM_DISABLE_ECHO_CANCELLER, + K_CM_ENABLE_AGC = CM_ENABLE_AGC, + K_CM_DISABLE_AGC = CM_DISABLE_AGC, + K_CM_ENABLE_HIGH_IMP_EVENTS = CM_ENABLE_HIGH_IMP_EVENTS, + K_CM_DISABLE_HIGH_IMP_EVENTS = CM_DISABLE_HIGH_IMP_EVENTS, +#if K3L_AT_LEAST(1,6,0) + K_CM_ENABLE_CALL_ANSWER_INFO = CM_ENABLE_CALL_ANSWER_INFO, + K_CM_DISABLE_CALL_ANSWER_INFO = CM_DISABLE_CALL_ANSWER_INFO, +#endif + K_CM_RESET_LINK = CM_RESET_LINK, +#if K3L_AT_LEAST(1,6,0) + K_CM_CLEAR_LINK_ERROR_COUNTER = CM_CLEAR_LINK_ERROR_COUNTER, +#endif + K_CM_SEND_DTMF = CM_SEND_DTMF, + K_CM_STOP_AUDIO = CM_STOP_AUDIO, + K_CM_HARD_RESET = CM_HARD_RESET, + K_CM_SEND_TO_CTBUS = CM_SEND_TO_CTBUS, + K_CM_RECV_FROM_CTBUS = CM_RECV_FROM_CTBUS, + K_CM_SETUP_H100 = CM_SETUP_H100, + K_CM_MIXER = CM_MIXER, + K_CM_CLEAR_MIXER = CM_CLEAR_MIXER, + K_CM_PLAY_FROM_FILE = CM_PLAY_FROM_FILE, + K_CM_RECORD_TO_FILE = CM_RECORD_TO_FILE, + K_CM_PLAY_FROM_STREAM = CM_PLAY_FROM_STREAM, + K_CM_INTERNAL_PLAY = CM_INTERNAL_PLAY, + K_CM_STOP_PLAY = CM_STOP_PLAY, + K_CM_STOP_RECORD = CM_STOP_RECORD, + K_CM_PAUSE_PLAY = CM_PAUSE_PLAY, + K_CM_PAUSE_RECORD = CM_PAUSE_RECORD, + K_CM_RESUME_PLAY = CM_RESUME_PLAY, + K_CM_RESUME_RECORD = CM_RESUME_RECORD, + K_CM_INCREASE_VOLUME = CM_INCREASE_VOLUME, + K_CM_DECREASE_VOLUME = CM_DECREASE_VOLUME, + K_CM_LISTEN = CM_LISTEN, + K_CM_STOP_LISTEN = CM_STOP_LISTEN, + K_CM_PREPARE_FOR_LISTEN = CM_PREPARE_FOR_LISTEN, + K_CM_PLAY_SOUND_CARD = CM_PLAY_SOUND_CARD, + K_CM_STOP_SOUND_CARD = CM_STOP_SOUND_CARD, + K_CM_MIXER_CTBUS = CM_MIXER_CTBUS, + K_CM_PLAY_FROM_STREAM_EX = CM_PLAY_FROM_STREAM_EX, + K_CM_INTERNAL_PLAY_EX = CM_INTERNAL_PLAY_EX, + K_CM_ENABLE_PLAYER_AGC = CM_ENABLE_PLAYER_AGC, + K_CM_DISABLE_PLAYER_AGC = CM_DISABLE_PLAYER_AGC, + K_CM_START_STREAM_BUFFER = CM_START_STREAM_BUFFER, + K_CM_ADD_STREAM_BUFFER = CM_ADD_STREAM_BUFFER, + K_CM_STOP_STREAM_BUFFER = CM_STOP_STREAM_BUFFER, + K_CM_SEND_BEEP = CM_SEND_BEEP, + K_CM_SEND_BEEP_CONF = CM_SEND_BEEP_CONF, + K_CM_ADD_TO_CONF = CM_ADD_TO_CONF, + K_CM_REMOVE_FROM_CONF = CM_REMOVE_FROM_CONF, + K_CM_RECORD_TO_FILE_EX = CM_RECORD_TO_FILE_EX, + K_CM_SET_VOLUME = CM_SET_VOLUME, + K_CM_SET_LINE_CONDITION = CM_SET_LINE_CONDITION, + K_CM_SEND_LINE_CONDITION = CM_SEND_LINE_CONDITION, + K_CM_SET_CALLER_CATEGORY = CM_SET_CALLER_CATEGORY, + K_CM_DIAL_MFC = CM_DIAL_MFC, +#if !K3L_AT_LEAST(2,0,0) + K_CM_VOIP_START_DEBUG = CM_VOIP_START_DEBUG, + K_CM_VOIP_STOP_DEBUG = CM_VOIP_STOP_DEBUG, + K_CM_VOIP_DUMP_STAT = CM_VOIP_DUMP_STAT, + K_CM_ISDN_DEBUG = CM_ISDN_DEBUG, + K_CM_PING = CM_PING, + K_CM_LOG_REQUEST = CM_LOG_REQUEST, + K_CM_LOG_CREATE_DISPATCHER = CM_LOG_CREATE_DISPATCHER, + K_CM_LOG_DESTROY_DISPATCHER = CM_LOG_DESTROY_DISPATCHER, +#endif +#if K3L_AT_LEAST(1,6,0) + K_CM_START_CADENCE = CM_START_CADENCE, + K_CM_STOP_CADENCE = CM_STOP_CADENCE, + K_CM_CHECK_NEW_SMS = CM_CHECK_NEW_SMS, + K_CM_SEND_TO_MODEM = CM_SEND_TO_MODEM, +#endif +#if K3L_AT_LEAST(2,1,0) + K_CM_START_FAX_TX = CM_START_FAX_TX, + K_CM_STOP_FAX_TX = CM_STOP_FAX_TX, + K_CM_ADD_FAX_FILE = CM_ADD_FAX_FILE, + K_CM_ADD_FAX_PAGE_BREAK = CM_ADD_FAX_PAGE_BREAK, + K_CM_START_FAX_RX = CM_START_FAX_RX, + K_CM_STOP_FAX_RX = CM_STOP_FAX_RX, + K_CM_SIM_CARD_SELECT = CM_SIM_CARD_SELECT, +#endif + +#if K3L_AT_LEAST(2,1,0) + K_CM_NOTIFY_WATCHDOG = CM_NOTIFY_WATCHDOG, + K_CM_STOP_WATCHDOG = CM_STOP_WATCHDOG, + K_CM_WATCHDOG_COUNT = CM_WATCHDOG_COUNT, + K_CM_START_WATCHDOG = CM_START_WATCHDOG, +#endif + + } + kcommand; + + typedef enum + { + K_EV_CHANNEL_FREE = EV_CHANNEL_FREE, + K_EV_CONNECT = EV_CONNECT, + K_EV_DISCONNECT = EV_DISCONNECT, + K_EV_CALL_SUCCESS = EV_CALL_SUCCESS, + K_EV_CALL_FAIL = EV_CALL_FAIL, + K_EV_NO_ANSWER = EV_NO_ANSWER, + K_EV_BILLING_PULSE = EV_BILLING_PULSE, + K_EV_SEIZE_SUCCESS = EV_SEIZE_SUCCESS, + K_EV_SEIZE_FAIL = EV_SEIZE_FAIL, + K_EV_SEIZURE_START = EV_SEIZURE_START, + K_EV_CAS_LINE_STT_CHANGED = EV_CAS_LINE_STT_CHANGED, + K_EV_CAS_MFC_RECV = EV_CAS_MFC_RECV, + K_EV_NEW_CALL = EV_NEW_CALL, + K_EV_USER_INFORMATION = EV_USER_INFORMATION, + K_EV_DIALED_DIGIT = EV_DIALED_DIGIT, +#if K3L_AT_LEAST(1,6,0) + K_EV_SIP_REGISTER_INFO = EV_SIP_REGISTER_INFO, + K_EV_RING_DETECTED = EV_RING_DETECTED, +#endif + K_EV_CALL_HOLD_START = EV_CALL_HOLD_START, + K_EV_CALL_HOLD_STOP = EV_CALL_HOLD_STOP, +#if K3L_AT_LEAST(1,6,0) + K_EV_SS_TRANSFER_FAIL = EV_SS_TRANSFER_FAIL, + K_EV_FLASH = EV_FLASH, +#endif + K_EV_DTMF_DETECTED = EV_DTMF_DETECTED, + K_EV_DTMF_SEND_FINISH = EV_DTMF_SEND_FINISH, + K_EV_AUDIO_STATUS = EV_AUDIO_STATUS, + K_EV_CADENCE_RECOGNIZED = EV_CADENCE_RECOGNIZED, + K_EV_END_OF_STREAM = EV_END_OF_STREAM, + K_EV_PULSE_DETECTED = EV_PULSE_DETECTED, + K_EV_POLARITY_REVERSAL = EV_POLARITY_REVERSAL, +#if K3L_AT_LEAST(1,6,0) + K_EV_ISDN_PROGRESS_INDICATOR = EV_ISDN_PROGRESS_INDICATOR, + K_EV_CALL_ANSWER_INFO = EV_CALL_ANSWER_INFO, + K_EV_COLLECT_CALL = EV_COLLECT_CALL, + K_EV_SIP_DTMF_DETECTED = EV_SIP_DTMF_DETECTED, + K_EV_RECV_FROM_MODEM = EV_RECV_FROM_MODEM, + K_EV_NEW_SMS = EV_NEW_SMS, + K_EV_SMS_INFO = EV_SMS_INFO, + K_EV_SMS_DATA = EV_SMS_DATA, + K_EV_SMS_SEND_RESULT = EV_SMS_SEND_RESULT, +#endif +#if K3L_HAS_MPTY_SUPPORT + K_EV_CALL_MPTY_START = EV_CALL_MPTY_START, + K_EV_CALL_MPTY_STOP = EV_CALL_MPTY_STOP, + K_EV_GSM_COMMAND_STATUS = EV_GSM_COMMAND_STATUS, +#endif + K_EV_CHANNEL_FAIL = EV_CHANNEL_FAIL, + K_EV_REFERENCE_FAIL = EV_REFERENCE_FAIL, + K_EV_INTERNAL_FAIL = EV_INTERNAL_FAIL, + K_EV_HARDWARE_FAIL = EV_HARDWARE_FAIL, + K_EV_LINK_STATUS = EV_LINK_STATUS, +#if K3L_AT_LEAST(1,6,0) + K_EV_PHYSICAL_LINK_UP = EV_PHYSICAL_LINK_UP, + K_EV_PHYSICAL_LINK_DOWN = EV_PHYSICAL_LINK_DOWN, +#endif + K_EV_CLIENT_RECONNECT = EV_CLIENT_RECONNECT, + K_EV_VOIP_SEIZURE = EV_VOIP_SEIZURE, + K_EV_SEIZURE = EV_SEIZURE, + +#if K3L_AT_LEAST(2,1,0) + K_EV_FAX_CHANNEL_FREE = EV_FAX_CHANNEL_FREE, + K_EV_FAX_FILE_SENT = EV_FAX_FILE_SENT, + K_EV_FAX_FILE_FAIL = EV_FAX_FILE_FAIL, + K_EV_FAX_MESSAGE_CONFIRMATION = EV_FAX_MESSAGE_CONFIRMATION, + K_EV_FAX_TX_TIMEOUT = EV_FAX_TX_TIMEOUT, + K_EV_FAX_PAGE_CONFIRMATION = EV_FAX_PAGE_CONFIRMATION, + K_EV_FAX_REMOTE_INFO = EV_FAX_REMOTE_INFO, +#endif + +#if K3L_AT_LEAST(2,1,0) + K_EV_WATCHDOG_COUNT = EV_WATCHDOG_COUNT, +#endif + +#if !K3L_AT_LEAST(2,0,0) + K_EV_PONG = EV_PONG, +#endif + } + kevent; + + typedef enum + { + R2_COUNTRY_ARG = 1, + R2_COUNTRY_BRA = 2, + R2_COUNTRY_CHI = 3, + R2_COUNTRY_MEX = 4, + R2_COUNTRY_URY = 5, + R2_COUNTRY_VEN = 6 + } + R2CountryType; + + typedef enum + { + HUMAN, + EXACT + } + Presentation; + + /* dynamic (object) stuff */ + + Verbose(K3LAPI & api): _api(api) {}; + +#if K3L_AT_LEAST(2,0,0) + std::string event(int32, K3L_EVENT*, R2CountryType r2_country = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + std::string event(int32, K3L_EVENT*, Presentation fmt = HUMAN); +#endif + + std::string channelStatus(int32, int32, int32, Presentation fmt = HUMAN); + + /* end of dynamic (object) stuff */ + + protected: + K3LAPI & _api; + + /* used internally */ + struct internal_not_found {}; + + public: + + /* static (class) stuff */ + + static std::string echoLocation(KEchoLocation, Presentation fmt = HUMAN); + static std::string echoCancellerConfig(KEchoCancellerConfig, Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string event(KSignaling, int32, K3L_EVENT*, R2CountryType = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string event(KSignaling, int32, K3L_EVENT*, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string command(int32, K3L_COMMAND*, R2CountryType = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); + static std::string command(int32, int32, int32, const char *, R2CountryType = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string command(int32, K3L_COMMAND*, Presentation fmt = HUMAN); + static std::string command(int32, int32, int32, const char *, Presentation fmt = HUMAN); +#endif + + + static std::string deviceName(KDeviceType, int32, Presentation fmt = HUMAN); + + static std::string deviceType(KDeviceType, Presentation fmt = HUMAN); + static std::string deviceModel(KDeviceType, int32, Presentation fmt = HUMAN); + + static std::string channelFeatures(int32, Presentation fmt = HUMAN); + static std::string signaling(KSignaling, Presentation fmt = HUMAN); + static std::string systemObject(KSystemObject, Presentation fmt = HUMAN); + static std::string mixerTone(KMixerTone, Presentation fmt = HUMAN); + static std::string mixerSource(KMixerSource, Presentation fmt = HUMAN); + + static std::string seizeFail(KSeizeFail, Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string callFail(KSignaling, R2CountryType, int32, Presentation fmt = HUMAN); +#else + static std::string callFail(KSignaling, int32, Presentation fmt = HUMAN); +#endif + + static std::string channelFail(KSignaling, int32, Presentation fmt = HUMAN); + static std::string internalFail(KInternalFail, Presentation fmt = HUMAN); + + static std::string linkErrorCounter(KLinkErrorCounter, Presentation fmt = HUMAN); + + static std::string linkStatus(KSignaling, int32, Presentation fmt = HUMAN); + static std::string channelStatus(KSignaling, int32, Presentation fmt = HUMAN); + static std::string callStatus(KCallStatus, Presentation fmt = HUMAN); + static std::string status(KLibraryStatus, Presentation fmt = HUMAN); + +#if K3L_AT_LEAST(2,0,0) + static std::string signGroupB(KSignGroupB, R2CountryType contry = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string signGroupB(KSignGroupB, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string signGroupII(KSignGroupII, R2CountryType contry = R2_COUNTRY_BRA, + Presentation fmt = HUMAN); +#else + static std::string signGroupII(KSignGroupII, Presentation fmt = HUMAN); +#endif + + static std::string h100configIndex(KH100ConfigIndex, Presentation fmt = HUMAN); + + static std::string eventName(int32); + static std::string commandName(int32); + +#if K3L_AT_LEAST(1,5,0) + static std::string sipFailures(KSIP_Failures, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,5,1) + static std::string isdnCause(KQ931Cause, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,5,2) + static std::string isdnDebug(int32, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,6,0) + static std::string callStartInfo(KCallStartInfo, Presentation fmt = HUMAN); + + static std::string gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN); + static std::string gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN); + static std::string gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN); + + static std::string q931ProgressIndication(KQ931ProgressIndication, + Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,1,0) + static std::string faxResult(KFaxResult code, Presentation fmt = HUMAN); + static std::string faxFileErrorCause(KFaxFileErrorCause code, Presentation fmt = HUMAN); +#endif + + /* end of static (class) stuff */ + + private: + static std::string internal_deviceType(KDeviceType); + static std::string internal_deviceModel(KDeviceType, int32); + +#if K3L_AT_LEAST(1,5,0) + static std::string internal_sipFailures(KSIP_Failures, Presentation fmt = HUMAN); +#endif +#if K3L_AT_LEAST(1,5,1) + static std::string internal_isdnCause(KQ931Cause, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(2,0,0) + static std::string internal_signGroupB(KSignGroupB, R2CountryType contry, Presentation fmt = HUMAN); + static std::string internal_signGroupII(KSignGroupII, R2CountryType contry, Presentation fmt = HUMAN); +#else + static std::string internal_signGroupB(KSignGroupB, Presentation fmt = HUMAN); + static std::string internal_signGroupII(KSignGroupII, Presentation fmt = HUMAN); +#endif + +#if K3L_AT_LEAST(1,6,0) + static std::string internal_gsmCallCause(KGsmCallCause, Presentation fmt = HUMAN); + static std::string internal_gsmMobileCause(KGsmMobileCause, Presentation fmt = HUMAN); + static std::string internal_gsmSmsCause(KGsmSmsCause, Presentation fmt = HUMAN); + + static std::string internal_q931ProgressIndication(KQ931ProgressIndication, Presentation fmt = HUMAN); +#endif + + private: + enum Type + { + DEVICE, + CHANNEL, + PLAYER, + MIXER, + LINK, + NONE + }; + + struct Target + { + Target(Type _type) + : type(_type), device(-1), object(-1) + {}; + + Target(Type _type, int32 _device) + : type(_type), device(_device), object(-1) + {}; + + Target(Type _type, int32 _device, int32 _object) + : type(_type), device(_device), object(_object) + {}; + + Type type; + int32 device; + int32 object; + }; + + static void generate(std::string &, std::string &, Target, std::string &); + + static std::string show(std::string &, std::string, Target, std::string &); + static std::string show(std::string &, std::string, Target); + + template < typename ReturnType > + static ReturnType presentation(Presentation fmt, ReturnType str_exact, ReturnType str_human) + { + switch (fmt) + { + case HUMAN: return str_human; + case EXACT: return str_exact; + }; + + return str_exact; + } +}; + +#endif /* _VERBOSE_HPP_ */ diff --git a/src/mod/endpoints/mod_khomp/docs/Manual.html b/src/mod/endpoints/mod_khomp/docs/Manual.html new file mode 100644 index 0000000000..863ef76847 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/docs/Manual.html @@ -0,0 +1,1083 @@ +Mod Khomp: Manual +

Considerações iniciais

+

Este documento aborda informações sobre o Endpoint da Khomp como um todo, desde opções disponíveis de configuração, os applications disponibilizados, os possíveis comandos de CLI, entre outros. +

Para procedimentos sobre a instalação, favor consultar o README do Endpoint. +
+

+

Configuração

+

Configurar o Endpoint da Khomp é uma tarefa que consiste de três etapas: +

+
  • Configuração das placas, através da K3L; +
  • Configuração do Endpoint; +
  • Configuração do FreeSWITCH. +
+

Estas etapas são descritas mais detalhadamente abaixo. +
+

+

Configuração da API K3L

+

Esta etapa é realizada de maneira semi-automatizada através do programa khompwizard, um assistente que configura os parâmetros básicos das placas do sistema. Esse assistente inicializa os arquivos de configuração através de informações obtidas do usuário, quando estas forem necessárias, inicializando as configurações menos utilizadas com os valores padrões. +

Normalmente, este programa é executado automaticamente após a instalação do sistema. Entretanto, pode ser necessário executá-lo manualmente caso uma atualização esteja sendo realizada, ou se novas placas foram adicionadas no sistema após a instalação dos drivers da placa. +

Caso seja necessária a configuração de parâmetros avançados da placa e/ou da sinalização, o programa k3lconfig permite acessar todas as configurações disponíveis de cada placa instalada. Para maiores informações sobre este programa, consulte a documentação do mesmo. Para soluções de problemas de sincronismo, consulte a seção Solução de problemas sobre o procedimento de configuração manual das placas. +
+

+

Configuração do Endpoint

+

A configuração padrão do sistema costuma atender à maior parte das necessidades. Entretanto, as configurações do Endpoint da Khomp podem ser modificadas através do arquivo de configuração '/usr/local/freeswitch/conf/autoload_configs/khomp.conf.xml'. +

A lista de opções é a seguinte: +

+

<channels>

+

Define as configurações gerais de todos os canais da Khomp. +

+
Sintaxe: <param name="..." value="..."/>
+
+
  • dialplan: Nome do módulo de dialplan em uso. +
  • auto-fax-adjustment: Ativa ("yes") ou desativa ("no") o ajuste automático do canal (desabilitar o cancelador de eco e a supressão DTMF) ao detectar tom de FAX; +
  • auto-gain-control: Ativa ("yes") ou desativa ("no") a ativação do controle automático de ganho (AGC) pelo Endpoint; +
  • context-digital: Contexto de entrada para ligações em placas digitais (o padrão é "khomp-DD-LL", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "LL" pelo número do link, "CCC" pelo número do canal e "SSSS" pelo número serial do dispositivo); +
  • context-fxo: Contexto de entrada para placas FXO (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo); +
  • context-fxs: Contexto de entrada para placas FXS (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo); +
  • context-gsm-call (ou "context-gsm"): Contexto de entrada para ligações GSM (o padrão é "khomp-DD-CC", onde "DD" será substituído no momento da ligação pelo número do dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo); +
  • context-gsm-sms: Contexto de entrada para SMSs (o padrão é "khomp-sms-DD-CC", onde "DD" será substituído pelo número de dispositivo, "CC" pelo número do canal, e "SSSS" pelo número serial do dispositivo); +
  • context-pr: Contexto de entrada para ligações em placas KPR (o padrão é "khomp-DD-CC", onde "DD" será substituído, no momento da ligação, pelo número do dispositivo, "CC" pelo número do canal); +
  • disconnect-delay: Define o tempo em milissegundos para realizar o processamento de um evento de desconexão, para ignorar situações onde outros equipamentos realizam o duplo atendimento para derrubar chamadas a cobrar; +
  • echo-canceller: Ativa ("yes") ou desativa ("no") o cancelamento de eco automático pelo Endpoint; +
  • fxo-send-pre-audio: Quando ativada ("yes") libera canal de áudio sainte antes da conexão da chamada em placas KFXO (o valor padrão é "yes"); +
  • fxs-global-orig: Número inicial para numeração seqüencial de ramais das placas KFXS que não estiverem listadas na seção <fxs-branches> (a numeração segue ordem crescente por número da placa e número do canal físico) (o padrão é "0"); +
  • fxs-co-dialtone: Seqüências de números, separados por vírgula, que disparam um tom contínuo (de central pública) em ramais FXS (ex: "0,99" faz com que, ao discar "0" ou "99", o usuário receba o tom de linha contínuo) (o padrão é vazio); +
  • fxs-bina: Quando ativada ("yes"), ligações para ramais FXS enviarão os dígitos correspondentes ao telefone de origem em sinalização BINA DTMF (o valor padrão é "no"); +
  • input-volume: Define o volume de entrada das ligações, varia de -10 a +10 ; +
  • kommuter-activation: Define se a ativação de dispositivos kommuter encontrados no sistema será feita de forma automática ("auto"), ou de forma manual ("manual") pelo usuário, através do comando "khomp kommuter on/off"; +
  • kommuter-timeout: Define o timeout (em segundos) com que os kommuters serão inicializados. Se chegarem a este timeout sem receberem notificação do channel, os dispositivos irão comutar para o estado "desligado". O valor mínimo é "0" , onde os links permanecerão sempre comutados no estado "ligado", e o valor máximo é "255"; +
  • language: Define idioma para ligações nas placas Khomp; +
  • log-to-console: Define mensagens de log que devem ser impressas na console; +
  • log-to-disk: Define mensagens de log que devem ser salvar em disco; +
  • out-of-band-dtmfs: Ativa ("yes") ou desativa ("no") a supressão DTMF e o envio destes out-of-band; +
  • output-volume: Define o volume de saída das ligações, varia de -10 a +10 ; +
  • pulse-forwarding: Ativa ("yes") ou desativa ("no") a detecção de pulsos e a conversão dos mesmos em DTMFs; +
  • r2-preconnect-wait: Define o tempo de espera do envio da sinalização de ringback, no protocolo R2/MFC, para iniciar o envio de áudio de silêncio. Apenas utilizado quando "r2-strict-behaviour" estiver ajustado para "no"; +
  • r2-strict-behaviour: Ativa ("yes") ou desativa ("no") o comportamento da sinalização R2/MFC conforme a norma define. O padrão é "no", e pode ser alterado para "yes" caso seja necessário receber/enviar dados precisos da sinalização do protocolo (condição de B, por exemplo); +
  • ringback-delay-co: Define o tempo de delay para ativar a geração de tom de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e não há áudio sendo enviado por quem indicou a situação de controle da chamada; +
  • ringback-delay-pbx: Define o tempo de delay para ativar a geração de controle de chamada (ringback) pelo Endpoint da Khomp quando há uma indicação de ringback, e o áudio de controle enviado não possui nenhum tom (ou seja, está em silêncio); +
  • suppression-delay: Ativa ("yes") ou desativa ("no") o delay necessário para supressão DTMF. Se desativado ("no"), também desativa supressão de DTMFs; +
  • trace: Define opções de depuração. Não deve ser utilizado em produção a não ser que estritamente necessário; +
  • user-transfer-digits: Define uma seqüência de dígitos DTMF para iniciar a transferencia entre o FreeSWITCH® e um outro PABX (utilizando sinalização de usuário, como QSig ou FXO FLASH); +
  • flash-to-digits: Define os dígitos para serem enviados quando o FLASH é detectado na FXS; +
+


+

+

<groups>

+

Define os grupos para serem usados na alocação de canal. +

Neste caso, as opções são usadas para definir nomes para strings de alocação de canais. O formato segue o padrão <param name="nome grupo" value="string alocação"/>, onde as strings de alocação de canais são as mesmas utilizadas no application bridge, e nome do grupo é um nome arbitrário escolhido pelo usuário. +

+
Por exemplo, para definir o grupo pstn como os canais 0 e 5 da placa 0, deveria-se utilizar a linha: +
+
<param name="pstn" value="b0c0 + b0c5"/> 
+
+

Este grupo, por sua vez, poderia ser usado no application bridge como <action application="bridge" data="Khomp/Gpstn/..."/>. +

+
Pode-se também associar um determinado contexto de entrada a um grupo de canais, bastando especificar um nome de contexto após a string de alocação, separado por ':' da mesma. +
+

Por exemplo, para definir o mesmo grupo pstn acima como os canais 0 até 20 da placa 0, com contexto de entrada from-pstn, poderia-se utilizar a linha: +

+
<param name="pstn" value="b0c0-20:from-pstn"/>
+
+

Este grupo, por sua vez, poderia ser usado no application bridge como <action application="bridge" data="Khomp/Gpstn/..."/>, e todas as ligações vindas destes canais seriam tratadas no contexto from-pstn. +
+

+

<cadences>

+

Define configurações de cadências para o Endpoint. +

Neste caso, as opções são nomes de cadências e um ou dois pares de números, que definem os intervalos de tom e silêncio a ser utilizado nas cadências. Para maiores detalhes, favor consultar o arquivo de configuração. +
+

+

<fxs-branches>

+

Define números de origem para a placa KFXS. +

Neste caso, as opções são seqüências de prefixos de ramais e números seriais das placas, que definem os números base dos endereços de origem, e a ordem numérica das placas. O formato das opções é: +

+
<param name="prefixo" value="serial1, serial2, ...."/>
+
+

Por exemplo, para definir que as placas K0374 e K2352 devem ser numeradas seqüencialmente, partido do ramal 200, basta escrever: +

+
<param name="200" value="374, 2352"/>
+
+

Para maiores detalhes, favor consultar o arquivo de configuração. +
+

+

<fxs-hotlines>

+

Define hotlines para a placa KFXS. +

Neste caso, as opções são seqüências de ramais e números de destino, definindo os ramais listados nesta seção para serem tratados como "hotlines". Para cada ramal listado, o número de destino especificado será discado quando o ramal for retirado do gancho. Exemplo: +

+
<param name="100" value="1234"/>
+<param name="200" value="4321"/> 
+
+

No primeiro exemplo, o ramal de número 100 irá telefonar para número 1234 ao ser retirado do gancho; no segundo, o ramal de número 200 irá telefonar para o número 4321 ao ser retirado do gancho. +

+

<fxs-options>

+

Permite definir configurações específicas por ramal FXS. +

Neste caso, as configurações são números de ramais (baseado nos definidos na seção <fxs-branches>), e as opções e seus valores. As opções disponíveis são: +

+
  • context; +
  • input-volume; +
  • output-volume; +
  • accountcode; +
  • calleridnum; +
  • calleridname; +
  • mailbox; +
  • flash-to-digits. +
+

Cada opção é separada uma da outra por um pipe "|" ou uma barra "/" e definidas após dois pontos ":", exemplo: +

+
 <param name="200" value="language:en|context:master-branch" />
+
+

Para maiores informações sobre a sintaxe e exemplos, favor consultar o arquivo de configuração. +


+

Para maiores informações, consultar o arquivo de configuração 'khomp.conf.xml'. +
+

+

Configuração do FreeSWITCH

+

Quando as ligações são recebidas nas placas e dispositivos Khomp, estas são encaminhadas pelo Endpoint da Khomp para contextos específicos dentro do plano de discagem do FreeSWITCH®. Estes contextos podem ser alterados através do arquivo de configurações khomp.conf.xml, disponível no diretório de configuração do FreeSWITCH (por padrão, "/usr/local/freeswitch/conf/autoload_configs"). +

Para maiores detalhes sobre os contextos específicos, consultar a seção de Configuração do Endpoint. +

Abaixo, encontram-se informações de como configurar os contextos de entrada de chamadas: +
+


+

+

Contextos de entrada em canais E1

+

Para placas E1, as ligações de entrada por padrão chegam em um contexto pré-definido conforme a opção context-digital: +

+
<param name="context-digital" value="khomp-DD-LL"/>
+
+

Este contexto padrão define que as ligações serão redirecionadas de acordo com o número da placa e número do link: DD é o número dispositivo (com dois dígitos), e LL é o número do link (também com dois dígitos). +

Entretanto, é possível configurar outros contextos de entrada, com formatos diferenciados. Pode-se utilizar a opção CCC, que significa o número do canal na placa (com três dígitos), e SSSS, que representa o número serial da placa (com quatro dígitos). +

Exemplos de configuração no arquivo khomp.conf.xml: +

+
<!-- número seqüencial da placa e do link (ex: khomp-01-00) -->
+<param name="context-digital" value="khomp-DD-LL"/>
+
+
<!-- número serial da placa e seqüencial do link (ex: khomp-3049-00) -->
+<param name="context-digital" value="khomp-SSSS-LL"/>
+
+
<!-- número seqüencial da placa e do canal (ex: khomp-00-001) -->
+<param name="context-digital" value="khomp-DD-CCC"/>
+
+
<!-- recebe todas as chamadas em um só contexto (khomp-digital) -->
+<param name="context-digital" value="khomp-digital"/>
+
+

Abaixo um exemplo de contexto no plano de discagem: + +

+
<!-- 
+Este contexto presente em seu arquivo de dialplan, irá manipular chamadas
+de entrada no link 0 (primeiro link) da placa 0.
+-->
+<context name="khomp-00-00">
+             .
+             .
+             .
+</context>
+
+

Outro exemplo, utilizando o mesmo formato: + +

+
<!-- 
+Este contexto presente em seu arquivo de dialplan, irá manipular chamadas
+de entrada no link 1 (segundo link) da placa 0.
+-->
+<context name="khomp-00-01>
+             .
+             .
+             .
+</context>
+
+

Um exemplo completo, com algumas ações simples: + +

+
<context name="khomp-00-00">
+    <extension name="exemplo_1">
+        <condition field="destination_number" expression="^1234$">
+            <action application="bridge" data="Khomp/b0L1/2345"/>
+        </condition>
+    </extension>
+    <extension name="exemplo_2">
+        <condition field="destination_number" expression="^23(\d{2})$">
+            <action application="bridge" data="sofia/${use_profile}/11$1@${sip_from_host}"/>
+        </condition>
+    </extension>
+</context>
+
+
<context name="khomp-00-01">
+    <extension name="exemplo_3">
+        <condition field="destination_number" expression="^1111$">
+            <action application="bridge" data="Khomp/b0L0/2345"/>
+        </condition>
+    </extension>
+</context>
+
+

Este plano de discagem define o recebimento de chamadas na placa 0 e no link 0, redirecionando chamadas para o número 1234 feitas para o link 1 da placa 0, pro ramal/telefone 2345, e redirecionando qualquer número de quatro dígitos começado com 23 para telefones SIP de quatro dígitos começados com 11 mais os dois últimos dígitos recebidos. +

Também há mais uma extensão definida, onde as ligações recebidas no link 1 da placa 0 para o número 1111, são redirecionadas para o link 0 da placa 0, para o telefone/ramal 2345. +
+

+

Contextos de entrada em canais FXS/FXO/GSM

+

Da mesma forma que no contexto de placas E1, as ligações de entrada são encaminhadas pelo Endpoint para o FreeSWITCH. +

O contexto é pré-definido da seguinte forma, conforme o arquivo khomp.conf.xml: +

+
<param name="context-gsm" value="khomp-DD-CC"/> ;placas GSM
+
+
<param name="context-fxs" value="khomp-DD-CC"/> ; placas FXS
+
+
<param name="context-fxo" value="khomp-DD-CC"/> ; placas FXO
+
+


+Nestes casos, DD é o número dispositivo (com dois dígitos), e CC é o número do canal da placa. Pode-se utilizar também SSSS, que representa o número serial da placa. +

+
  • IMPORTANTE: No caso da placa KGSM, as ligações entrantes são sempre encaminhadas para o extension "s" por padrão, visto que o protocolo GSM não identifica o número de destino nas ligações entrantes, apenas o número de origem - quando não omitido. +
+

Prioridade de contextos na placa FXS

+

Em ligações originadas a partir de um ramal FXS, o Endpoint driver procura uma extensão válida (dos dígitos discados) após o dígito # ou após o timeout (configurável pela opção fxs-digit-timeout, no arquivo khomp.conf.xml). Essa busca é realizada no contexto específico do ramal (definido na seção <fxs-options> do arquivo de configuração khomp.conf.xml), caso não seja configurado, a busca é realizada no contexto definido na opção context-fxs; +


+

+

Contextos de mensagens SMS (apenas GSM)

+

Mensagens SMS são recebidas pelo Endpoint da Khomp e encaminhadas para o FreeSWITCH como uma ligação normal, mas sem áudio, que possui algumas variáveis ajustadas com informações recebidas na mensagem - para maiores informações sobre estas variáveis, consulte a documentação das variáveis do Endpoint. Este contexto também pode ser alterado, de mesma forma que o contextos acima. +

Esta ligação entra no seguinte contexto, conforme o arquivo khomp.conf.xml: +

+
<param name="context-gsm-sms" value="khomp-sms-DD-CC"/> 
+
+

Onde DD é o número dispositivo (com dois dígitos), e CC é o número do canal (também com dois dígitos). Por exemplo: +

+
<context name="khomp-sms-00-01">
+    <extension name="sms">
+        <condition field="destination_number" expression="^s$">
+            <action application="log" data="DEBUG KSmsType=${KSmsType}"/>
+            <action application="log" data="DEBUG KSmsBody=${KSmsBody}"/>
+        </condition>
+    </extension>
+</context>
+
+

Contexto de entrada em canais Khomp_PR (KPR)

+

Para estas placas, as ligações de entrada possuem um contexto pré-definido, conforme exemplo abaixo: +

+
<param name="context-pr" value="khomp-DD-CC"/> 
+
+

Neste caso, DD é o número do dispositivo (com dois dígitos), e CC é o número do canal da placa. +
+

+

Contextos por grupo de chamada

+

A seção groups, no arquivo de configuração khomp.conf.xml, pode ser utilizado para definir contextos específicos para determinados grupos de canais. +

Esta seção é detalhada na seção Configuração do Endpoint. +
+

+

Utilização do application bridge

+

O aplicativo (ou application) bridge é responsável por gerar chamadas no FreeSWITCH a partir de um dialplan. Este aplicativo pode ser utilizado para gerar chamadas a partir de diversos tipos de Endpoints, sendo que cada Endpoint segue um formato específico para definir tanto as opções quanto os canais de comunicações a serem utilizados. +

+

Campos relativos ao Endpoint

+

Quando utilizado para canais da Khomp, a string de bridge pode ter dois, três ou quatro campos separados por uma barra (/). Algumas strings de exemplo: + +

+
<action application="bridge" data="Khomp/B2L0/32625644"/>
+<action application="bridge" data="Khomp/*B2L0/32625644"/>
+<action application="bridge" data="Khomp/S0411/99991234"/>
+<action application="bridge" data="Khomp/Gpstn/99991234"/>
+<action application="bridge" data="Khomp/*Gpstn/99991234"/>
+<action application="bridge" data="Khomp/B2C58/32625644/category=4:orig=4855553232"/>
+<action application="bridge" data="Khomp/b0c9"/>
+<action application="bridge" data="Khomp/b0c1+b0c14"/>
+<action application="bridge" data="Khomp/r304"/>
+
+

Nos cinco primeiros exemplos, temos três campos sendo especificados; no sexto, quatros campos são utilizados; e por fim, nos três últimos exemplos, apenas dois são utilizados. +

Sobre os campos utilizados, segue a descrição: +

+
  • 1° campo, 'Khomp': identifica o tipo do Endpoint em questão; +
  • 2° campo, 'B2L0', 'S0411', 'Gpstn', etc: representa a Política de Alocação de Canais; +
  • 3° campo, '32625644' e '99991234': são os números de destino, para onde será efetuada a ligação (ausente em placas KFXS); +
  • 4° campo, 'category=4:orig=4855553232': opções adicionais não-obrigatórias, detalhadas mais à frente. +
+

OBS: A string de bridge com somente dois campos é específica à ligações para uma placa KFXS, onde o destino está atrelado automaticamente ao canal alocado, ou ao ramal especificado. +

+

Política de alocação de canais

+

A política de alocação de canais, no módulo da Khomp, pode ser especificado na própria string de bridge ou através de grupos, no arquivo de configuração khomp.conf.xml. Para especificar placas, canais e links a serem alocados existe a seguinte sintaxe disponível (considerando X, Y e Z como números quaisquer): +

+
  • bX -- busca os canais na placa 'X', de maneira crescente. +
  • bXLY -- busca canais no link 'Y' da placa 'X', fazendo uma procura crescente (com relação ao número dos canais). +
  • bXcY -- utiliza apenas o canal 'Y' da placa 'X'. +
  • bXcY-Z -- busca por canais, iniciando do canal 'Y' e indo até o canal 'Z' (inclusive), da placa 'X', de maneira crescente. +
  • BXcY-Z -- idem ao anterior, de maneira decrescente. +
  • sX -- busca os canais na placa de serial 'X', de maneira crescente. +
  • sXLY -- busca canais no link 'Y' da placa de serial 'X', fazendo uma procura crescente (com relação ao número dos canais). +
  • sXcY -- utiliza apenas o canal 'Y' da placa de serial 'X'. +
  • sXcY-Z -- busca por canais, iniciando do canal 'Y' e indo até o canal 'Z' (inclusive), da placa de serial 'X', de maneira crescente. +
  • SXcY-Z -- idem ao anterior, de maneira decrescente. +
+

Para buscar por ramais de placas KFXS de acordo com o número do ramal, pode ser utilizada a seguinte sintaxe (considerando X e Y números de ramais válidos): +

+
  • rX -- busca ramal 'X'. +
  • RX -- equivalente ao anterior. +
  • rX-Y -- busca de ramal 'X' a 'Y', ordem crescente. +
  • RX-Y -- busca de ramal 'X' a 'Y', ordem decrescente. +
+

É interessante notar que apenas a capitalização da letra 'B', 'S' ou 'R' define a ordem de busca dos canais; se minúscula, crescente, e se maiúscula, decrescente. +

Já para a alocação de canais através de grupos, existe a seguinte sintaxe disponível: +

+
  • Ggroupname -- utiliza a string de bridge definida ao grupo "groupname" no arquivo de configuração; já detalhado na seção de configuração do Endpoint. +
  • ggroupname -- equivalente ao anterior. +
+

Agrupando alocações de canais

+

Existem casos onde é necessário buscar canais mais de um determinado dispositivo, ou determinado grupo de ramais. Para isto, existe uma extensão disponível na string de alocação, que diz respeito ao uso do símbolo de soma (+) para concatenar várias strings de ligação, da seguinte forma: +

+
<action application="bridge" data="Khomp/B1L0+B2L0/32332933"/>
+<action application="bridge" data="Khomp/*B2+B3+B4/99887766"/>
+<action application="bridge" data="Khomp/S0411+B1L0/99887766"/>
+<action application="bridge" data="Khomp/Gpstn1+Gpstn2/99991234"/>
+<action application="bridge" data="Khomp/*gOperadora1+gOperadora2/98891234"/>
+
+

Esta extensão está disponível tanto no application bridge quanto na especificação de grupos, e pode ser utilizada para agrupar qualquer string de alocação válida à outra. O processamento das strings de alocação se dá da esquerda para a direita - exceto quanto utilizando a alocação cíclica, onde todos os canais especificados são verificados simultaneamente. +

+

Escolha cíclica e/ou justa

+

Uma variação da alocação de canais é através de uma escolha cíclica e/ou justa, que consiste em escolher o canal que completou - até o momento - o menor número de ligações saintes. Essa forma é caracterizada por um asterisco (*) antes da string de alocação de canais (conforme pode ser verificado acima, no segundo e quinto exemplos). +

Quando iniciada com um asterisco (*), as outras formas de alocação subseqüentes (crescente, decrescente, etc) são utilizadas para decidir, entre os canais com menor número de ligações saintes, qual será verificado primeiro para realizar a chamada. +

+
  • AVISO: O uso da alocação justa e/ou cíclica é recomendável somente em placas analógicas (KFXO), de ramais (KFXS) e de interface celular (KGSM). Conexões E1 tendem a alocar os canais de maneira crescente ou decrescente de um lado (na operadora, por exemplo), e o inverso do outro (no PABX, por exemplo), para evitar problemas de dupla ocupação (o que pode ocorrer na sinalização R2/MFC). A alocação cíclica/justa também consome mais recursos de memória e processamento que a alocação tradicional, o que é agravado ainda mais pelo fato de placas E1 terem um número muito maior de canais (30 por link).

    Por estes motivos, alocações justas e/ou cíclicas devem ser utilizadas apenas em sinalizações onde isso pode representar alguma diferença real, como equalizar a tarifação das linhas, o uso das mesmas, ou o número de ligações recebidas por cada ponto de atendimento (PA). +
+

Opções disponíves

+
  • orig: Define o número de origem a ser utilizado na chamada, sem alterar a variável ${origination_caller_id_number}. Ou seja, a opção orig serve apenas para repassar um número de origem diferente do ${origination_caller_id_number}. Caso o FreeSWITCH já tenha ajustado a variável ${origination_caller_id_number}, o que é o comportamento padrão, o Endpoint utiliza este valor automaticamente como referência do número de origem, sem ser necessário repassar nenhuma opção adicional.

    Nas placas KGSM, se ajustado para restricted, omite o número de origem. Exemplo:
    +
+
+ <action application="bridge" data="Khomp/b0/99887766/orig=restricted"/>
+
+
  • category: Quando ajustado para um valor numérico, define a categoria do número de A. Disponível apenas em sinalização R2/MFC; +
  • uui: Quando ajustado para um número e uma string de texto, separados por cerquilha ("#"), envia uma mensagem "User-to-User" para a outra ponta, antes de realizar a chamada, utilizando o descritor como o número e a mensagem como o texto. Disponível apenas em sinalização RDSI (ISDN); +
  • ring_cadence: Quando ajustado para um identificador, utiliza cadência definida com este nome na seção "cadences" do arquivo de configuração do Endpoint da Khomp para chamar o canal desejado. Disponível apenas em sinalização FXS; +
  • ring: Quando ajustado para dois números, separados por ponto ("."), define as cadências de chamada de um ramal FXS para estes valores, sendo o primeiro relativo ao tempo de chamando, e o segundo, ao tempo de silêncio; +
  • ring_ext: Quando ajustado para dois números, separados por ponto ("."), define as cadências de chamada extendidas (a serem executadas depois da cadência principal) de um ramal FXS para estes valores, sendo o primeiro relativo ao tempo de chamando, e o segundo, ao tempo de silêncio; +
  • usr_xfer: Quando ajustado para uma seqüência de dígitos DTMF, define estes como dígitos a serem utilizados para iniciar uma transferência entre PABXes (utilizando sinalizações de usuário); +
  • drop_on: Quando ajustado para "message_box", "human_answer", "answering_machine", "carrier_message", "unknown" ou uma lista destes (separados por mais ("+") ou ponto (".")), faz com que a chamada seja derrubada ao detectar tons de caixa postal, atendimento humano, secretária eletrônica, mensagens da operadora, ou algum atendimento desconhecido - respectivamente. Disponível em sinalizações digitais (links E1 e placas KGSM). Adicionalmente, a informação de atendimento é reportada para o usuário na variável KCallAnswerInfo; +
  • answer_info: Opção booleana (não necessita de valor). Quando especificada, reporta informações de atendimento para o usuário através da variável KCallAnswerInfo; +
  • pre: Quando ajustado para uma seqüência de dígitos DTMF, utiliza estes para pre-alocar um canal de saída em um PABX analógico, discando o número de B desejado a seguir. Somente disponível para sinalização analógica (FXO); +
  • pre_answer: Opção booleana (não necessita de valor). Quando especificada, "antende" o canal antes de a ligação ser completada permitindo, por exemplo, que DTMFs possam ser enviados - útil para utilizar em um DISA; +
  • output_volume: Define o volume de saída da ligação. Varia de -10 a +10; +
  • input_volume: Define o volume de entrada da ligação. Varia de -10 a +10; +
+


+

+

Lista das variáveis

+

Segue lista de variáveis disponíveis no Endpoint: +

+
  • KDropCollectCall: Quando definida antes do atendimento (ao receber uma chamada), ativa ("yes") ou desativa ("no", padrão) o derrubamento de chamadas à cobrar baseado na sinalização recebida da central pública; através do duplo atendimento; ou através do reconhecimento por áudio de uma chamada à cobrar (pode ser definido de maneira global); +
  • KR2SendCondition: Quando definida antes do envio de ringback pelo FreeSWITCH (ao receber uma chamada), ajusta a condição de B para o valor numérico que foi ajustada. Apenas disponível para sinalização R2; +
  • KR2GotCategory: Ajustada pelo Endpoint ao receber uma chamada entrante, e possui a categoria do número de A. Apenas disponível para sinalização R2; +
  • KR2GotCondition: Ajustada pelo Endpoint, e disponível após o retorno de uma chamada realizada pelo FreeSWITCH. Contém a condição de B recebida ao realizar a chamada. Apenas disponível para sinalização R2; +
  • KISDNGotCause: Ajustada pelo Endpoint, e disponível após o retorno de uma chamada realizada pelo FreeSWITCH. Contém o código de cause do ISDN recebido ao realizar a chamada. Apenas disponível para sinalização ISDN; +
  • KCallAnswerInfo: Ajustada pelo Endpoint, e disponível após o retorno de uma chamada realizada pelo FreeSWITCH. Contém as informações de atendimento detectadas ao realizar a chamada e está disponível apenas para sinalizações digitais (E1, GSM); +
  • KSmsDelivered: Ajustada pelo Endpoint ao enviar uma mensagem SMS com o application KSendSMS, e define se a mensagem foi entregue com sucesso ("yes") ou não ("no"); +
  • KSmsErrorCode: Ajustada pelo Endpoint ao enviar uma mensagem SMS com o application KSendSMS, e define o código de erro ao enviar a mensagem; +
  • KSmsErrorName: Ajustada pelo Endpoint ao enviar uma mensagem SMS com o application KSendSMS, contém o nome do erro em forma textual, ou "None" caso não tenha ocorrido nenhum erro. +
  • KSmsType: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, define o tipo da mensagem recebida (pode conter os valores "message", "confirm" ou "broadcast"; +
  • KSmsFrom: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, define o número de origem da mensagem recebida (disponível em tipos "message" e "confirm"); +
  • KSmsDate: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, define a data de envio da mensagem (disponível em tipos "message" e "confirm"); +
  • KSmsSize: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o tamanho (em bytes) da mensagem recebida (disponível em tipos "message" e "broadcast"); +
  • KSmsMode: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o tipo codificação da mensagem recebida (disponível em tipos "message" e "broadcast"); +
  • KSmsBody: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o texto da mensagem recebida (disponível em tipos "message" e "broadcast"); +
  • KSmsDelivery: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém a data de entrega de mensagem enviada anteriormente cuja confirmação foi requisitada (disponível no tipo "confirm"); +
  • KSmsStatus: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o status de envio de mensagem anteriormente cuja confirmação foi requisitada (disponível no tipo "confirm"); +
  • KSmsSerial: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o número de série da mensagem recebida (disponível no tipo "broadcast"); +
  • KSmsPage: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o número da página relativo à mensagem recebida (disponível no tipo "broadcast"); +
  • KSmsPages: Ajustada pelo Endpoint no contexto de entrada das mensagens SMS, contém o número total de páginas a serem recebidas (disponível no tipo "broadcast"); +
  • KUserInfoDescriptor: Define/informa descritor do protoloco utilizado na mensagem User-to-User Information (RDSI). +
  • KUserInfoData: Define/informa os dados na mensagem User-to-User Information (RDSI). +
  • KFaxSent: Ajustada pelo Endpoint ao enviar FAX com o application KSendFax, e define se o FAX foi enviado com sucesso ("yes") ou não ("no"); +
  • KFaxReceived: Ajustada pelo Endpoint ao receber FAX com o application KReceiveFax, e define se o FAX foi recebido com sucesso ("yes") ou não ("no"); +
  • KFaxResult: Ajustada pelo Endpoint ao enviar ou receber FAX com o application KSendFax ou KReceiveFax, respectivamente, e define o seu resultado. +
+


+

+

Descrição das variáveis

+

Abaixo, segue uma explanação sobre como utilizar as variáveis do Endpoint da Khomp disponíveis no dialplan, tanto para comunicar quanto para receber informações: +


+

+

KDropCollectCall

+

Quando ativada, faz com que o Endpoint da Khomp derrube chamadas a cobrar através de duplo atendimento (disponível para sinalizações 'R2 Digital' e FXO), através da informação disponível no protocolo RDSI e R2/MFC, ou através da detecção do áudio de chamada a cobrar (disponível para qualquer sinalização digital por link E1, e para sinalização GSM). +

Esta variável é útil para derrubar chamadas a cobrar para determinados ramais, e deve ser ajustado obrigatoriamente antes de realizar qualquer tipo de atendimento - aplicações como playback e bridge devem ser executadas sempre após ajustar esta variável, por exemplo. +

Para melhor funcionalidade, é recomendado também que nenhum estado de chamada (ringback) seja enviado antes desta variável ser ajustada, então aplicações devem ser executadas apenas após o ajuste correto desta variável. +

Esta variável pode ser ajustada localmente e globalmente, tanto para yes quanto para no. O ajuste da variável global para yes fará com que todas as chamadas a cobrar sejam derrubadas, a não ser que a chamada específica seja ajustada para no - isto permite a criação de um filtro global de chamadas a cobrar, com algumas poucas exceções. +

Ativando a variável dentro do contexto default: + +

<context name="default"> +

+
<extension name="exemplo">
+ .
+ .
+ .
+ <action aplication="set" data="KDropCollectCall=yes"/>
+ .
+ .
+ .
+</extension>
+
+

</context> +

Ativando a variável no contexto global, lembrando que a mesma deve ser configurada no arquivo vars.xml: + +

+
<X-PRE-PROCESS cmd="set" data="KDropCollectCall=yes"/>
+
+

KR2SendCondition

+

Ao receber uma chamada, pode ser definida antes do envio de ringback pelo FreeSWITCH (ou seja, antes do FreeSWITCH executar as aplicações answer, ou bridge). Quando utilizada em sinalização R2/MFC, esta variável ajusta a condição de B para o valor numérico desejado. +

Exemplo: + +

+
<!-- Condição "NUMBER CHANGED", avisa ao chamador que o número de B mudou. -->
+<action application="KR2SendCondition" data="3"/>
+
+

KR2GotCategory

+

Ao receber uma chamada, é ajustada pelo Endpoint com a categoria recebida do número que originou a chamada. É ajustada na sinalização R2/MFC, e pode ser consultada em qualquer local do dialplan. +

Exemplo: + +

+
<action application="log" data="DEBUG KR2GotCategory [${KR2GotCategory}]"/> 
+
+

KR2GotCondition

+

Variável ajustada pelo Endpoint, e disponível após o retorno de uma chamada realizada pelo FreeSWITCH. Contém a condição de B recebida ao realizar a chamada. Disponível apenas para sinalização R2/MFC. +

Exemplo: + +

+
<action application="log" data="DEBUG KR2GotCondition [${KR2GotCondition}]"/>
+
+

KUserInfoDescriptor

+

Variável ajustada pelo Endpoint no contexto de entrada, a partir de informações recebidas pela rede RDSI através da funcionalidade User-to-User Information. Contém o número do descritor do protocolo utilizado pela outra ponta, e normalmente contém valor '0', mas este valor é dependente da aplicação utilizada. +

Maiores informações, consultar a especificação ITU-T Q931 (mais precisamente, a tabela 4-26 da especificação). +

Exemplo (trabalhando com o número do descritor do protocolo): +

+
<action application="log" data="DEBUG KUserInfoDescriptor [${KUserInfoDescriptor}]"/>
+
+

KUserInfoData

+

Variável ajustada pelo Endpoint no contexto de entrada, a partir de informações recebidas pela rede RDSI através da funcionalidade User-to-User Information. Contém os dados propriamente ditos, que foram recebidos, em forma de uma 'string' de texto. +

Maiores informações sobre este recurso, consultar a especificação ITU-T Q931. +

Exemplo (trabalhando com os dados recebidos): +

+
<action application="log" data="DEBUG KUserInfoData [${KUserInfoData}]"/>
+
+

É importante salientar que as variáveis são sensíveis à capitalização das letras (case sensitive). +

+

KCallAnswerInfo

+

Variável ajustada pelo Endpoint em ligações de saída, representando o tipo de atendimento realizado pela outra ponta. Pode conter os seguintes valores: +

+
  • "MessageBox" (*): detectada caixa postal de um telefone celular; +
  • "CarrierMessage": mensagem de operadora enviada antes do atendimento; +
  • "AnsweringMachine" (**): atendimento por secretária eletrônica; +
  • "HumanAnswer" (**): atendimento humano; +
  • "Unknown": tipo de atendimento desconhecido; +
  • "Fax": reportado quando um tom de fax for detectado. +
+
+


+(*) Este tipo de atendimento é detectado por sinais em determinadas freqüências que são enviados antes da chamada entrar em uma caixa postal, e variam conforme a operadora. O algoritmo captura a maior parte das caixas postais, mas pode falhar se não existir um sinal claro, ou se o mesmo não estiver dentro dos padrões mais utilizados; +

(**) A diferenciação entre estes dois tipos de atendimento depende de configuração específica utilizando o programa k3lanswerinfoconfig, sendo a detecção apenas baseada em heurísticas e nunca com precisão de 100%. +
+

+

Comandos de console

+

Lista de comandos disponíveis no console do FreeSWITCH para o Endpoint da Khomp: +


+

+
  • khomp channels disconnect : Desconecta um ou vários canais. Este comando envia uma mensagem diretamente para o canal físico da placa em questão, requisitando a desconexão. Use com cautela; +
  • khomp channels unblock : Desbloqueia canais bloqueados para entrada ou para saída. Somente disponível em sinalização digital via link E1; +
  • khomp clear links: Limpa os contadores de erros nos links; +
  • khomp clear statistics: Limpa as estatísticas de ligações dos canais, ou as estatísticas de um canal específico; +
  • khomp get : Obtém as opções diversas do Endpoint da Khomp; +
  • khomp kommuter : Ativa ou desativa os kommuters ligados via USB nesta máquina. Somente acessível quando a configuração "kommuter-activation" estiver setada como "manual"; +
  • khomp kommuter count: Obtém a quantidade de kommuters ligados via USB nesta máquina; +
  • khomp log console: Ajusta opções de logs no console. +
  • khomp log disk: : Ajusta opções de log em disco. +
    • khomp log console e khomp log disk dispõem de opções auxiliares no, que inverte a escolha de mensagens, e just, que generaliza a escolha. Exemplos: +
      • khomp log disk just commands events (Habilita somente o registro de comandos e eventos da API em disco). +
      • khomp log disk no commands (Desabilita o registro em disco de comandos enviados à API). +
      • khomp log disk warnings (Habilita também o registro em disco dos avisos do Endpoint). +
      +
    • Mais informações sobre as opções de log nos comando "help khomp log disk" ou "help khomp log console". +
    +
  • khomp log rotate: Rotaciona arquivos de log do Endpoint; +
  • khomp log status: Mostra mensagens de log atualmente sendo escritas em disco e mostradas no console; +
  • khomp log trace isdn: Ativa a depuração da sinalização RDSI (ISDN); +
  • khomp log trace k3l : Ativa a depuração de baixo nível da API K3L; +
  • khomp log trace r2 : Ativa a depuração de baixo nível da sinalização R2/MFC; +
  • khomp reset links: Envia um comando de reset para um determinado link E1 de uma determinada placa; +
  • khomp revision: Mostra número da versão e revisão do Endpoint; +
  • khomp select sim: Seleciona o SIM card, disponível nas placas KGSM; +
  • khomp send command : Envia comando da API K3L diretamente para a placa. Apenas para depuração de problemas, pode compromenter a estabilidade do sistema se utilizado de maneira incorreta; +
  • khomp send raw command : Envia um comando diretamente para o DSP da placa. Apenas para depuração de problemas, pode compromenter a estabilidade do sistema se utilizado de maneira incorreta; +
  • khomp set : Ajusta opções diversas do Endpoint da Khomp; +
  • khomp show calls : Mostra estados das chamadas Khomp, podendo listar também por placa ou canal específico; +
  • khomp show channels : Mostra o estado dos canais Khomp, podendo listar também por placa específica; +
  • khomp show links: Mostra estados dos links E1 disponíveis. +
  • khomp show statistics : Mostra as estatísticas de ligações dos canais, ou as estatísticas de um canal específico; +
  • khomp sms : Envia uma mensagem SMS utilizando canais da placa KGSM para um determinado número; +
  • khomp summary :Imprime um sumário das placas do sistema e de suas características; +
+


+

+

Recursos adicionais

+

Este capítulo trata de recursos adicionais do Endpoint, relacionados às funcionalidades especiais presentes em algumas sinalizações. +
+

+

Aplicações (applications) e canais

+

O Endpoint da Khomp, além de registrar um tipo de canal de comunicação "Khomp", registra também os seguintes itens: +
+

+

Aplicação "KUserTransfer"

+

Realiza o processo de transferência do canal atual para o ramal número' utilizando o protocolo de sinalização QSig (Single Step Call Transfer) para placas E1 configuradas com sinalização RDSI (ISDN), ou utiliza comando de FLASH para linhas FXO, LineSide, CAS_EL7 e E1LC. +

A sintaxe segue: +

+
<action application="KUserTransfer" data="número[,opções])"/>
+
+

Exemplo: +

+
<action application="answer"/>
+<action application="KUserTransfer" data="2345"/>
+
+

Os campos têm o seguinte significado: +

+
  • número: Número para onde a ligação deve ser transferida. +
  • opções: Define as opções de transferência a utilizar, que são: +
    • n: Aguarda até o canal ser desconectado. +
    +
+


+


+

+

Aplicação "KSendSMS"

+

Esta aplicação tem a função de enviar mensagens SMS através das placas KGSM da Khomp, utilizando os módulos e SIM cards presentes na placa para tal. A sintaxe da aplicação é a seguinte: +

+
<action application="KSendSMS" data="recurso|destino|mensagem" />
+
+

Podendo cada campo ser resumido em: +

+
  • recurso: Segue uma sintaxe idêntica à alocação de canais do application Bridge, e define qual modem utilizar; +
  • destino: Número para onde enviar a mensagem, podendo ser precedido ou sucedido por ! para requisitar uma mensagem de confirmação de envio; +
  • mensagem: Texto (sem aspas) que deve ser enviado para destino. +
+

Após o envio da mensagem, as variáveis KSmsDelivered e KSmsErrorCode conterão o resultado do envio da mensagem. Para maiores informações sobre estas, favor consultar a seção sobre as variáveis utilizadas no Endpoint. +

Exemplos de uso desta aplicação seguem abaixo: +

+
  • Envia "Mensagem de teste." para telefone "99887766" utilizando o modem "1" (segundo modem) da placa "0": +
+
<action application="log" data="DEBUG Enviando SMS..." />
+<action application="KSendSMS" data="b0c1|99887766|Mensagem de teste" />
+
+
  • Envia "Mensagem de teste." para telefone "99887766" utilizando o primeiro modem livre da placa "0", e verifica retorno do envio: +
+
<action application="log" data="DEBUG Enviando SMS..." />
+<action application="KSendSMS" data="b0|99887766|Mensagem de teste" />
+<action application="log" data="DEBUG Enviou? ${KSmsDelivered}" />
+<action application="log" data="DEBUG Codigo: ${KSmsErrorCode}" />
+<action application="log" data="DEBUG Descr.: ${KSmsErrorName}" />
+
+
  • Envia "Mensagem de teste." para telefone "99887766" utilizando o primeiro modem livre da placa "0", ou para o primeiro canal livre da placa "1" (se não houver canal livre na primeira placa): +
+
<action application="log" data="DEBUG Enviando SMS..." />
+<action application="KSendSMS" data="b0+b1|99887766|Mensagem de teste" />
+
+
  • Envia "Mensagem de teste." para telefone "99887766" utilizando o primeiro modem livre da placa "0", requisitando confirmação: +
+
<action application="log" data="DEBUG Enviando SMS..." />
+<action application="KSendSMS" data="b0|99887766!|Mensagem de teste" />
+
+


+

+

Aplicação "KEchoCanceller"

+

Esta aplicação tem a função de habilitar ou desabilitar o cancelador de eco do canal. +

+
<action application="KEchoCanceller" data="ação[,opções])"/>
+
+

Onde: +

+
  • ação: Pode ser on para habilitar o cancelador de eco, e off para desabilitar; +
+

Exemplo de uso desta aplicação: +

+
<action application="KEchoCanceller" data="off"/>
+
+


+

+

Aplicação "KAutoGainControl"

+

Esta aplicação tem a função de habilitar ou desabilitar o controle automático de ganho no canal. +

+
<action application="KAutoGainControl" data="ação[,opções])"/>
+
+

Onde: +

+
  • ação: Pode ser on para habilitar o controle automático de ganho, e off para desabilitar; +
+

Exemplo de uso desta aplicação: +

+
<action application="KAutoGainControl" data="on"/>
+
+


+

+

Aplicação "KDTMFSuppression"

+

Esta aplicação tem a função de habilitar ou desabilitar a supressão de DTMF do canal. A sintaxe da aplicação é a seguinte: +

+
<action applicatin="KDTMFSuppression" value="ação[,opções])"/>
+
+

Onde: +

+
  • ação: Pode ser on para habilitar a supressão DTMF, e off para desabilitar; +
+

É importante notar que quando desabilitada a supressão de DTMF, os DTMFs serão passados inband e não serão mais reportados ao FreeSWITCH. Dessa forma o FreeSWITCH não reconhecerá os DTMFs, o que pode ocasionar em mau funcionamento de aplicações como por exemplo, URAs. +

Exemplo de uso desta aplicação: +

+
<action applicatin="KDTMFSuppression" value="off"/>
+
+


+

+

Aplicação "KSetVolume"

+

Esta aplicação tem a função de ajustar o volume de entrade e saída de canais da Khomp, sendo a sua sintaxe a seguinte: +

+
<action application="KSetVolume" data="<volume>"/>
+<action application="KSetVolume" data="<output-volume>|<input-volume>"/>
+
+

Onde os campos possuem o seguinte significado: +

+
  • volume: Ajusta o volume de entrada e saída (-10 a +10); +
  • output-volume: Ajusta o volume de saída (-10 a +10, "none" para não alterar); +
  • input-volume: Ajusta o volume de entrada (-10 a +10, "none" para não alterar). +
+


+

+

Aplicação "KAdjustForFax"

+

Esta aplicação tem a função de ajustar um canal da Khomp para o recebimento de sinal de FAX/modem, otimizando o canal de comunicação para o tráfego de dados. Sintaxe: +

+
<action application="KAdjustForFax" data=""/>
+
+

Esta aplicação não recebe parâmetros. Exemplo de utilização: +

+
<action application="KAdjustForFax" data=""/>
+
+


+

+

Aplicação "KSendFax"

+

Esta aplicação tem a função de enviar fax utilizando canais digitais ou FXO da Khomp em ligações pré-estabelecidas, sendo a sua sintaxe a seguinte: +

+
<action application="KSendFax" data="<arquivo>[:<arquivo2>[:...]][|<faxid>]"/>
+
+

Esta aplicação necessita de uma licença adquirida à parte para ser utilizada em canais digitais. Os campos possuem os seguintes significados: +

+
  • arquivos: Arquivos a serem enviados para o fax devem estar encapsulados no formato TIFF e possuírem resolução de 98, 196 ou 392 dpi; +
  • faxid: Número do fax. Caso não seja especificado, o valor será obtido pela id da ligação, e caso esta, também não seja válida, o número do fax será o configurado como padrão na K3L. +
+

Exemplo de uso desta aplicação: +

+
<action application="KSendFax" data="/tmp/fax.tif:/home/root/fax2.tif,1234"/>
+
+


+

+

Aplicação "KReceiveFax"

+

Esta aplicação tem a função de receber fax utilizando canais digitais ou FXO da Khomp, sendo a sua sintaxe a seguinte: +

+
<action application="KReceiveFax" data="<arquivo>[|<faxid>]/>
+
+

Esta aplicação necessita de uma licença adquirida à parte para ser utilizada em canais digitais. Os campos possuem os seguintes significados: +

+
  • arquivo: Nome que será atribuído ao arquivo de fax recebido. +
  • faxid: Número do fax. Caso não seja especificado, o valor será obtido pela id da ligação, e caso esta, também não seja válida, o número do fax será o configurado como padrão na K3L. +
+

Exemplo de uso desta aplicação: +

+
<action application="answer" />
+<action application="KReceiveFax" data="/tmp/fax.tif"/>
+
+


+

+

Canal "Khomp_SMS"

+

Este canal de comunicação é utilizado para receber mensagens SMS e criar ligações entrantes no FreeSWITCH para cada mensagem recebida. Este canal não possui qualquer tipo de tratamento ou processamento de áudio, e é chamado com cinco variáveis ajustadas: +

+
  • KSmsFrom, contendo o número de origem de quem enviou a mensagem; +
  • KSmsDate, que define a data/hora do recebimento da mensagem; +
  • KSmsSize, representando o tamanho da mensagem (em bytes); +
  • KSmsMode, contendo a codificação utilizada para transmitir a mensagem; +
  • KSmsBody, que é a mensagem em si. +
+

O processamento do dialplan do FreeSWITCH pode ser utilizado para guardar esta mensagem em um banco de dados, executar alguma aplicação, entre outros. Entretanto, a única ação aceita por este channel é desligamento (hangup) - ou seja, esta ligação entrante não pode ser considerada uma ligação comum. +
+

+

Canal "Khomp_PR"

+

Este canal de comunicação é utilizado para receber ligações em placas de gravação passiva (família KPR e KFXO-HI), criando ligações entrantes no FreeSWITCH para cada chamada recebida. Este canal permite apenas o recebimento de áudio capturado do link, não permitindo tanto o envio de mensagens de áudio quanto o de sinalizações de controle. +

O processamento do dialplan do FreeSWITCH pode ser utilizado para gravar dados sobre esta ligação em um banco de dados, executar alguma aplicação especial e/ou algum application de gravação (como o record), entre outros. Entretanto, a única ação aceita por este channel é desligamento (hangup) - ou seja, esta ligação entrante não pode ser considerada uma ligação comum. +
+


+

+

Códigos e significados

+

Este capítulo apresenta os códigos presentes no Endpoint da Khomp e seus significados, utilizados nos comandos de console: +
+

+

Estados de canais

+

Refletem o estado do canal relativo à placa. No caso de links E1, o estado pode ter uma ou mais das seguintes opções: +

+
  • Free: o canal está livre; +
  • Busy: o canal não está livre (ou ocupado, ou em falha); +
  • Outgoing: o canal possui uma ligação de saída; +
  • Incoming: o canal possui uma ligação de entrada; +
  • Locked: o canal está bloqueado; +
  • Outgoing Lock: o canal está bloqueado para chamadas saintes; +
  • Local Fail: o canal possui uma falha local (nesta ponta); +
  • Incoming Lock: o canal está bloqueado para chamadas entrantes; +
  • Remote Lock: há um bloqueio remoto (na outra ponta) neste canal. +
+

No caso de um canal FXS, o estado é definido por um destes valores: +

+
  • On Hook: o telefone conectado neste canal está no gancho ou desconectado; +
  • Off Hook: o telefone conectado neste canal está fora do gancho; +
  • Ringing: o canal está sendo chamado; +
  • Failure: o canal está em falha devido a problemas de comunicação entre a central e a placa. +
+

No caso de um canal GSM, o estado também é definido por um dos valores a seguir: +

+
  • Idle: o canal está livre e disponível para realizar chamadas; +
  • Call In Progress: o canal está ocupado em uma ligação; +
  • Modem Error: ocorreu um erro na comunicação com o modem do canal; +
  • SIM Card Error: o SIM card não está presente ou não foi inserido/detectado corretamente; +
  • Network Error: ocorreu um erro ao comunicar-se com a rede; +
  • Not Ready: o modem está sendo inicializado no canal. +
+

E no caso de um canal FXO, os estados serão os seguintes: +

+
  • Disabled: o canal está desabilitado; +
  • Enabled: o canal está habilitado. +
+


+

+

Estados de chamada

+

Define o estado de cada canal relativo ao software, que pode ser:: +

+
  • Free: o canal está livre; +
  • Incoming: o canal está recebendo uma chamada; +
  • Outgoing: o canal está realizando uma chamada; +
  • Failure: o canal está em falha. +
+


+

+

Estados da chamada FreeSWITCH

+

Reflete diretamente o estado de chamada controlado pelo FreeSWITCH, que pode se +

+
  • new: Canal é recém criado; +
  • init: Canal foi inicializado; +
  • routing: Canal está procurando uma extensão para executar; +
  • execute: Canal está executando seu dialplan; +
  • ex_media: Canal está trocando media com outro canal; +
  • cs_media: Canal está consumindo toda media; +
  • hangup: O canal está marcada para hangup e pronto para terminar. +
+


+

+

Códigos GSM

+

Os seguintes códigos numéricos são reportados: +

+

Códigos de SMS (SMS cause)

+
1	Unassigned number
+8	Operator determined barring
+10	Call barred
+21	SMS transfer rejected
+27	Destination out of service
+28	Unidentified subscriber
+29	Facility rejected
+30	Unknown subscriber
+38	Network out of order
+41	Temporary failure
+42	Congestion
+47	Resources unavailable
+50	Facility not subscribed
+69	Facility not implemented
+81	Invalid SMS transfer reference value
+95	Invalid message
+96	Invalid mandatory information
+97	Message type non existent
+98	Message not compatible with SMS protection state
+99	Information element non existent
+111	Protocol error
+127	Interworking
+128	Telematic interworking not supported
+129	SMS type zero not supported
+130	Cannot replace SMS
+143	Unspecified TPPID error
+144	Alphabet not supported
+145	Message class not supported
+159	Unspecified TPDCS error
+160	Command cannot be actioned
+161	Command unsupported
+175	Unspecified TP command error
+176	TPDU not supported
+192	SC busy
+193	No SC subscription
+194	SC system failure
+195	Invalid SME address
+196	Destination SME barred
+197	SM rejected duplicate SM
+198	TPVPF not supported
+199	TPVP not supported
+208	SIM SMS storage full
+209	No SMS storage capability in SIM
+210	Error in SMS
+211	Memory capatity exceeded
+213	SIM data download error
+255	Unspecified error
+300	Phone failure
+301	SMS service reserved
+302	Operation not allowed
+303	Operation not supported
+304	Invalid PDU mode parameter
+305	Invalid text mode parameter
+310	SIM not inserted
+311	SIM PIN necessary
+312	Phone SIM PIN necessary
+313	SIM failure
+314	SIM busy
+315	SIM wrong
+320	Memory failure
+321	Invalid memory index
+322	Memory full
+330	SMSC address unknown
+331	No network service
+332	Network timeout
+500	Unknown error
+512	Network busy
+513	Invalid destination address
+514	Invalid message body length
+515	Phone is not in service
+516	Invalid preferred memory storage
+517	User terminated
+
+

Códigos de chamada (call cause)

+
1	Unallocated number
+3	No route to destination
+6	Channel unacceptable
+8	Operator determined barring
+16	Normal call clear
+17	User busy
+18	No user responding
+19	No answer from user
+21	Call rejected
+22	Number changed
+26	Non Selected user clear
+27	Destination out of order
+28	Invalid number format
+29	Facility rejected
+30	Response status enquiry
+31	Normal, unspecified
+34	No circuit channel available
+38	Network out of order
+41	Temporary failure
+42	Switch congestion
+43	Access information discarded
+44	Requested channel unavailable
+47	Resource unavailable
+49	QoS unavailable
+50	Request facility not subscribed
+55	Call barred with UG
+57	Bearer capability not authorized
+58	Bearer capability not available
+63	Service not available
+65	Bearer capability not implemented
+69	Request facility not implemented
+70	Only restricted bearer capability available
+79	Service not implemented
+81	Invalid call reference value
+82	User not member of UG
+88	Incompatible destination
+91	Invalid transit network selected
+95	Invalid message
+96	Missing mandatory information element
+97	Message type not implemented
+98	Message incompatible with state
+99	Information element not implemented
+100	Invalid information element
+101	Message incompatible with state (2)
+102	Recovery on timer expiry
+111	Protocol error
+127	Interworking
+
+

Códigos gerais (mobile cause)

+
0	Phone failure
+1	No connection to phone
+2	Phone adaptor link reserved
+3	Operation not allowed
+4	Operation not supported
+5	Phone SIM PIN required
+6	Phone FSIM PIN required
+7	Phone FSIM PUK required
+10	SIM not inserted
+11	SIM PIN required
+12	SIM PUK required
+13	SIM failure
+14	SIM busy
+15	SIM wrong
+16	Incorrect password
+17	SIM PIN2 required
+18	SIM PUK2 required
+20	Memory full
+21	Invalid index
+22	Not found
+23	Memory failure
+24	Text string too long
+25	Invalid character in text string
+26	Dial string too long
+27	Invalid character in dial string
+30	No network service
+31	Network timeout
+32	Network not allowed
+33	Command aborted
+34	Number parameter instead of text parameter
+35	Text parameter instead of number parameter
+36	Numeric parameter out of bounds
+37	Text string too short
+40	Network PIN required
+41	Network PUK required
+42	Network subset PIN required
+43	Network subset PUK required
+44	Network service provider PIN required
+45	Network service provider PUK required
+46	Corporate PIN required
+47	Corporate PUK required
+60	SIM Service option not supported
+100	Unknown
+103	Illegal MS #3
+106	Illegal MS #6
+107	GPRS service not allowed #7
+111	PLMN not allowed #11
+112	Location area not allowed #12
+113	Roaming not allowed #13
+132	Service option not supported #32
+133	Registration service option not subscribed #33
+134	Service option temporary out of order #34
+147	Long context activation
+148	Unspecified GPRS error
+149	PDP authentication failure
+150	Invalid mobile class
+151	GPRS disconnection TMR active
+256	Too many active calls
+257	Call rejected
+258	Unanswered call pending
+259	Unknown calling error
+260	No phone number recognized
+261	Call state not idle
+262	Call in progress
+263	Dial state error
+264	Unlock code required
+265	Network busy
+266	Invalid phone number
+267	Number entry already started
+268	Cancelled by user
+269	Number entry could not be started
+280	Data lost
+281	Invalid message body length
+282	Inactive socket
+283	Socket already open
+
+


+

+

Solução de problemas

+

Nesta seção, erros e suas soluções mais comuns são apresentados. +

+

Erro durante a instalação do módulo de kernel

+

Durante a instalação do Endpoint da Khomp, podem ocorrer as seguintes mensagens: + +

+
K3L: WARNING: Unable to find a module for [...]
+
+

ou + +

+
install: ******  THE KERNEL MODULE HAS NOT BEEN INSTALLED: *******
+install: 
+install: ** Please, untar the file kpdriver*.tar.gz located in: **
+install: **                 '/usr/src/khomp/'                   **
+install: **             then check the README.txt               **
+install: **  for knowing how to proceed with the installation.  **
+
+

Neste caso, será necessário compilar os drivers manualmente para o seu sistema. Prossiga para o item abaixo para maiores informações. +
+

+

Compilandos os drivers e iniciando os serviços

+

Basta seguir ao diretório /usr/src/khomp, descompactar o arquivo "kpdriver_2.0.0XX.tar.gz", e acompanhar procedimentos descritos no arquivo README.txt. +

Após realizar a compilação e a instalação do módulo, basta carregá-lo no sistema, configurar as placas, e iniciar o servidor de processos da Khomp. +

Para carregar o driver de kernel, é necessário executar o seguinte comando: + +

+
# /etc/init.d/khompdrv start
+
+

Para configurar as placas, por sua vez, necessário executar o comando: + +

+
# khompwizard
+
+

Isto executará um assistente de configuração, que irá perguntar a sinalização utilizada no sistema, bem como outros parâmetros de utilização das placas. +

Caso seja necessário configurar outros parâmetros adicionais, pode-se utilizar o seguinte comando: + +

+
# k3lconfig
+
+

Este configurador, por sua vez, mostra todas as opções possíveis de configuração da placa. Os parâmetros que não forem configurados assumem os valores padrão automaticamente, e são compatíveis com a maior parte dos sistemas. Maiores detalhes sobre este programa podem ser obtidos na seção de número '2'. +


+

+
  • IMPORTANTE: Para o FreeSWITCH iniciar, é preciso que a placa da khomp esteja configurada e todos módulos estejam rodando (conforme mostrado acima). Caso a placa não esteja configurada, o FreeSWITCH não iniciará.

    Se você deseja rodar o sistema sem a placa da Khomp, é preciso configurar o FreeSWITCH para ele não carregar o módulo da Khomp. Para isso, abra o arquivo "/usr/local/freeswitch/conf/autoload_configs/modules.conf.xml", e comente a linha que carrega o módulo:
    +
+
+  <!-- <load module="mod_khomp" /> -->
+

+

Quando a placa da Khomp estiver devidamente configurada e os módulos da khomp carregados (explicado acima), lembre-se de descomentar esta linha no arquivo. +


+Por fim, para carregar o servidor de processos, basta executar o seguinte comando: + +

+
# kserver start
+
+

Após realizar estes procedimentos, o Endpoint já estará operacional, e o FreeSWITCH já pode ser carregado. +
+

+

Configurando parâmetros especiais de sinalização ou áudio

+

Para configurar parâmetros especiais de sincronismo e/ou sinalização, é possível utilizar o programa "k3lconfig": basta selecionar a placa desejada, e as opções das placas serão apresentadas, divididas em seções e subseções para facilitar o acesso. Não é necessário efetuar a configuração de todos os parâmetros: os valores padrão são assumidos, caso não sejam configurados. +

Para ajustar a sinalização do link, basta - depois de selecionar a placa - entrar na seção "Opções de sinalização", e em seguida, em "Sinalização da linha". Para escolher uma sinalização específica, basta utilizar as teclas de direcionamento (setas) até selecioná-la, pressionar 'espaço', e confirmar a opção pressionando 'Enter' sobre o botão "Confirmar". +

Por fim, para salvar as configurações modificadas, basta sair do programa: ele irá mostrar uma janela, com opções para salvar ou não as alterações realizadas. +

É importante notar que não é necessário alterar/ativar as seguintes opções: +

+
  • Cancelamento de eco automático; +
  • Supressão de DTMFs automática; +
  • Controle de ganho (AGC) automático. +
+

Estas opções são controladas pelo Endpoint, e devem estar desabilitadas no 'k3lconfig'. +
+

+

Inicialização automática dos serviços e módulos de kernel

+

Se a carga dos módulos de kernel ou a inicialização dos serviços da Khomp não for realizada automaticamente na inicialização do sistema, é possível realizar esta instalação manualmente, criando um link para os scripts /etc/init.d/khompdrv e /etc/init.d/kserver no diretório de inicialização do sistema. +

Na caso da distribuição Debian, o script de carga dos módulos de kernel seria linkado dentro do diretório /etc/rcS.d/, enquanto o script de inicialização dos serviços seria linkado dentro dos diretórios /etc/rc2.d, /etc/rc3.d, /etc/rc4.d, /etc/rc5.d, da seguinte forma: +

+

+
# ln -s /etc/init.d/khompdrv  /etc/rcS.d/S19khompdrv
+# ln -s /etc/init.d/kserver   /etc/rc2.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc3.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc4.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc5.d/S20kserver
+
+

É interessante verificar as normas da sua distribuição para inicializar os serviços de acordo com o que é esperado pela inicialização da mesma. +
+

+

Apêndice

+

Nesta seção, encontram-se informações úteis sobre o Endpoint e componentes relacionados. +

+

Disposição dos arquivos

+

Os diretórios criados/modificados nesta instalação são: + +

+
/etc/init.d/                -- Scripts de inicialização;
+
+/etc/khomp/                 -- Arquivos de firmware e configurações;
+
+/usr/local/freeswitch/conf/ -- Configurações do FreeSWITCH e Endpoint;
+
+/usr/doc/khomp/             -- Documentação das placas, do mod_khomp e dos utilitários;
+
+/usr/sbin/                  -- Utilitários e servidor de processos;
+
+/usr/lib/                   -- Bibliotecas compartilhadas da K3L;
+
+/usr/local/freeswitch/mod/  -- Módulo 'mod_khomp.so';
+ 
+/var/log/khomp2.1/          -- Diretório de logs da K3L e Endpoint
+
+


+O script /etc/init.d/khompdrv é responsável por carregar os módulos kpci9030.ko e kpex8311.ko no kernel, que deve ser realizada automaticamente na inicialização do sistema. Em caso de problemas, verifique a seção Solução de problemas. +
+


+

\ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/docs/Manual.pdf b/src/mod/endpoints/mod_khomp/docs/Manual.pdf new file mode 100644 index 0000000000..935b299dbc Binary files /dev/null and b/src/mod/endpoints/mod_khomp/docs/Manual.pdf differ diff --git a/src/mod/endpoints/mod_khomp/docs/README.html b/src/mod/endpoints/mod_khomp/docs/README.html new file mode 100644 index 0000000000..e4cae5ad3b --- /dev/null +++ b/src/mod/endpoints/mod_khomp/docs/README.html @@ -0,0 +1,39 @@ +Mod Khomp: README

Guia Rápido

+

Depois de instalar a placa no sistema, e executar o programa de instalação pela primeira vez, os drivers e serviços da Khomp serão adicionados na inicialização do sistema, e automaticamente carregados. +

Se o sistema possuir pelo menos uma placa de tronco E1 e/ou uma placa FXO, uma tela de configuração básica deverá ser apresentada ao final do processo, questionando parâmetros de sinalização - no caso de existirem placas E1 - e/ou realizando o ajuste de cadências - no caso de existirem placas FXO. +

Se todas estas etapas foram executadas com sucesso, prossiga para o item Utilizando o Endpoint da Khomp. Caso algum problema ocorra, consulte o Manual do Endpoint, seguindo para a seção de Solução de problemas. +

+

Utilizando o Endpoint da Khomp

+

Após a instalação e inicialização dos serviços necessários pela Khomp, o FreeSWITCH já pode ser carregado ou inicializado. +

+
  • AVISO: É imprescindível que o FreeSWITCH não seja executado utilizando a opção que desabilita o escalonamento em tempo real (-nort), especialmente se este estiver sendo executado lado-a-lado com servidores web ou servidores de banco de dados. Não realizar este procedimento pode resultar em perda de qualidade do áudio, gerando um sério comprometimento no andamento das ligações do sistema. +
+

Após a inicialização do FreeSWITCH, pode-se verificar se o módulo da Khomp foi carregado através do seguinte comando:
+

+
 freeswitch@hostname> module_exists mod_khomp
+
+

A próxima linha deverá responder algo tipo: +

+
 true
+
+

Para verificar se o FreeSWITCH reconheceu todas as placas, digite: +

+
 freeswitch@hostname> khomp summary
+
+

A saída desse comando mostrará detalhes de todas placas reconhecidas. +

No caso de uma placa de tronco E1, pode-se verificar o estado dos links com o seguinte comando: +

+
 freeswitch@hostname> khomp show links
+
+

O estado dos canais individuais, por sua vez, pode ser aferido com o comando: +

+
 freeswitch@hostname> khomp show channels
+
+

Para mais detalhes sobre os comandos do Endpoint da khomp digite no console do FreeSWITCH: +

+
 freeswitch@hostname> help khomp
+
+
  • IMPORTANTE: Para fazer completo uso da sua placa Khomp, será preciso configurar suas regras de discagem, seja através do arquivo default.xml ou de um aplicativo externo, definindo regras específicas para realizar ao receber ligações.

    No Manual do Endpoint, podem ser encontradas informações sobre o formato dos contextos de entrada (responsáveis por receber as ligações) e sobre as opções disponíveis no application Bridge (responsável por realizar ligações) que podem ser utilizadas com o Endpoint da Khomp, além de outras funcionalidades especiais providas pelo mesmo. +
+


+

\ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/docs/README.pdf b/src/mod/endpoints/mod_khomp/docs/README.pdf new file mode 100644 index 0000000000..2b95cfaad4 Binary files /dev/null and b/src/mod/endpoints/mod_khomp/docs/README.pdf differ diff --git a/src/mod/endpoints/mod_khomp/docs/README_en.html b/src/mod/endpoints/mod_khomp/docs/README_en.html new file mode 100644 index 0000000000..5d44b8219f --- /dev/null +++ b/src/mod/endpoints/mod_khomp/docs/README_en.html @@ -0,0 +1,40 @@ +Mod Khomp: README: en

Quick guide

+

After installing the card in the system and run the installation program for the first time, the drivers and Khomp services will be added at system startup, and automatically loaded. +

If your system has at least one E1 trunk card and / or an FXO card, a basic setup screen will be presented at the end of the process, questioning signaling parameters - if there are signs E1 - and/or performing the adjustment cadences - where that FXO cards. +

If all these steps were performed successfully, proceed to the item Using Khomp Endpoint. If a problem occurs, see the User Guide, in the section Troubleshooting. +

+

Using the Khomp Endpoint

+

After installation and startup services required by Khomp, FreeSWITCH can now be loaded or initialized. +

+
  • WARNING: It is imperative that theFreeSWITCH is not executed using the option that disables the escalation in real time (-nort), especially if this is running side-by server-side with web servers or database. Failure to do so may result in loss of audio quality, causing a serious commitment on the progress of system connections. +
+

After initialization of FreeSWITCH, you can verify that the module was loaded Khomp through the following command:
+


+

+
 freeswitch@hostname> module_exists mod_khomp
+
+

The next line should answer something like: +

+
 true
+
+

To verify that the FreeSwitch recognize all the cards, type: +

+
 freeswitch@hostname> khomp summary
+
+

The output of this command will show details of all cards accepted. +

In the case of an E1 card, you can check the status of links with the following command: +

+
 freeswitch@hostname> khomp show links
+
+

The state of individual channels, in turn, can be measured with the command: +

+
 freeswitch@hostname> khomp show channels
+
+

For more details on the commands of the Endpoint khomp type in the console of FreeSWITCH: +

+
 freeswitch@hostname> help khomp
+
+
  • IMPORTANT: To make full use of your card Khomp, you must configure your dialing rules, either through the extension.conf or from an external application by setting specific rules for conduct by receiving connections.
    In the User Guide, information can be found on the format of input contexts (responsible for receiving calls) and on the options available on application Dial (responsible for make calls) that can be used with the Endpoint Khomp, and other special features provided by it. +
+


+

\ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/docs/README_en.pdf b/src/mod/endpoints/mod_khomp/docs/README_en.pdf new file mode 100644 index 0000000000..25be8ab0b2 Binary files /dev/null and b/src/mod/endpoints/mod_khomp/docs/README_en.pdf differ diff --git a/src/mod/endpoints/mod_khomp/docs/User_Guide.html b/src/mod/endpoints/mod_khomp/docs/User_Guide.html new file mode 100644 index 0000000000..eb5cfc6c4e --- /dev/null +++ b/src/mod/endpoints/mod_khomp/docs/User_Guide.html @@ -0,0 +1,1088 @@ +Mod Khomp: User Guide +

First considerations

+

This document covers information about the Endpoint of Khomp as a whole, include the options, applications, CLI commands, among others. +

For first installation procedures, please see the README. +
+

+

Configuration

+

Configuring the Khomp Endpoint is a task that consists of three steps: +

+
  • Configuration of the boards through the K3L; +
  • Setting up the Endpoint; +
  • Setting up the FreeSWITCH. +
+

These steps are described more fully below. +
+

+

K3L API Configuration

+

This step is carried out in a semi-automated way using the khompwizard program, a wizard that configures the basic parameters of the system boards. This wizard initializes the configuration files using information from the user when they are needed, initializing the standard settings to default values. +

Typically, this program runs automatically after installation of the system. However, you may need to run it manually if an update is being performed, or if new cards were added to the system after installing new drivers. +


+If you need to set advanced parameters of the board and/or signaling, the program k3lconfig allows you to access all the available settings for each installed card. For more information about this program, check the k3lconfig User's Guide. For solving synchronization issues, check the Troubleshooting section for manual configuration of the boards. +
+

+

Endpoint Configuration

+

The system's default configuration normally meet most user's needs. However, the configuration of the Endpoint Khomp can be modified through the configuration file '/usr/local/freeswitch/conf/autoload_configs/khomp.conf.xml'. +

The list of options is as follows: +

+

<channels>

+

Define general settings of all channels of Khomp: +

+
Sintaxe: <param name="..." value="..."/>
+
+
  • dialplan: Name of the dialplan module in use. +
  • auto-fax-adjustment: Enable ("yes") or disables ("no") the automatic adjustment of the channel (disable the echo canceller and the suppression DTMF) tone to detect FAX (local option) ; +
  • auto-gain-control:Enable ("yes") or disables ("no") the activation of the automatic gain control (AGC) by the Endpoint (local option); +
  • context-digital: Context for incoming connections on digital boards (the default is "khomp-DD-LL", where "DD" will be replaced at the time of connection by the device number, "LL" by the number of the link, "CCC" by channel number and "SSSS" for the device serial number); +
  • context-fxo: Context for incoming connections on FXO cards (the default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC" by channel number, and "SSSS" by the device serial number); +
  • context-fxs: Context for incoming connections on FXS cards (the default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC" by channel number, and "SSSS" by the device serial number); +
  • context-gsm-call (or context-gsm): Context of entry for GSM boards (the default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC" by channel number, and "SSSS" by the device serial number); +
  • context-gsm-sms: Context for incoming SMSs (the default is "khomp-sms-CC-DD", where "DD" will be replaced by the number of device, "CC" by channel number and "SSSS" by the device's serial number); +
  • context-pr: Context for incoming connections on boards KPR (default is "khomp-CC-DD", where "DD" will be replaced at the time of connection by the device number, "CC "by channel number); +
  • disconnect-delay: Sets the time in milliseconds to perform processing a disconnect event, to ignore situations where other equipment performing the double service to overthrow collect calls (local option); +
  • echo-canceller (former 'echocanceller): Active ("yes") or disables ("no") echo cancellation automatic Endpoint (local option); +
  • fxo-send-pre-audio: When enabled ("yes") releases audio channel before the outgoing call connection boards KFXO (the default value is "yes"); +
  • fxs-global-orig: Start number for sequencial branch numbering in FXS cards that are not listed in the [fxs-branches] section (the numbering follows ascending order from board number and physical channel number) (default is "0"); +
  • fxs-co-dialtone: Sequences of numbers, separated by commas, which fires a continuous tone (of central office) in FXS branches (eg: "0,99" means that, when you dial "0" or "99", the user will hear a continuous dial tone) (default is empty); +
  • fxs-bina: When enabled ("yes"), calls to FXS lines will send digits corresponding to the source phone identification using BINA DTMF signaling (the default value is "no") (local option); +
  • input-volume: Sets the volume gain for incoming audio (entering the board), from -10 to +10 (local option); +
  • kommuter-activation: Sets whether to activate devices kommuter found in the system will be done automatically ("auto") by the channel, or manually ("manual") by the user through the command "khomp kommuter on/off" +
  • kommuter-timeout: Sets the timeout (in seconds) for initializing the kommuter devices. If this timeout is reached without receiving notification of the channel, the devices will switch back to "off" condition. The minimum value is "0", where the links will always remain switched "on", and the maximum is "255"; +
  • language: Set language to Khomp channel calls (local option); +
  • log-to-console: Set log messages to be printed on the console; +
  • log-to-disk (old "log"): Set log messages to be saved to disk; +
  • out-of-band-DTMF (former dtmfsuppression): Activate ("yes") or disables ("no") the removal and DTMF sending these out-of-band (local option); +
  • output-volume: Define o volume de saída das ligações, varia de -10 a +10 ; +
  • pulse-forwarding (former 'pulsedetection): Active ("yes") or disables ("no") for the detection of pulses and converting them into DTMF (local option); +
  • r2-preconnect-wait (former 'r2preconnectwait): Sets the timeout sending the ringback signaling, protocol R2/MFC to start sending audio silence. Only used when "r2-strict-Behavior" is set to "no" (local option); +
  • r2-strict-Behaviour: Enable ("yes") or disables ("no") the behavior of signaling R2/MFC as the standard sets. The default is "no", and can be changed to "yes" if needed to receive / send data precise signaling protocol (condition B, for example) (local option); +
  • ringback-delay-co: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication from signaling and there is no audio being sent by the channel which indicated the situation (local option); +
  • ringback-delay-pbx: Sets the delay to enable the generation of call control tone (ringback) by the Endpoint Khomp when there is an ringback indication, and the audio has no tone (silence) (local option); +
  • suppression-delay (former suppressiondelay): Activate ("yes") or disables ("no") the delay necessary to suppress DTMF. If disabled ("no"), also disables suppression of DTMF (local option); +
  • trace: Set debugging options. Should not be used in production unless absolutely necessary; +
  • user-transfer-digits: Defines a sequence of DTMF digits to initiate the transfer between FreeSWITCH® and another PBX (using user signaling, like QSig or FXO FLASH). +
  • flash-to-digits: Defines the digits to be sent when the FLASH is detected on FXS channels.. +
+


+

+

<groups>

+

Defines the groups to be used in channel allocation. +

In this case, the options are used to define names for strings allocation of channels. The format follows the standard <group name> = <allocation string>, where the allocation string is the same string used in the bridge application, and group name is an arbitrary name chosen by the user. +

+
For example, to define the group pstn as the channels 0 and 5 of the board 0, the following line could be used: +
+
<param name="pstn" value="b0c0 + b0c5"/> 
+
+

This group, in turn, could be used in the bridge application as <action application="bridge" data="Khomp/Gpstn/..."/>. +

+
You can associate a given input context to a channel group, simply specify a name of context string after the allocation, separated by ':'. +
+

For example, to define the same group pstn as channels 0 to 20 of card 0, and defining the incoming context to for channels in this groups to from-pstn, one could use the line: +

+
<param name="pstn" value="b0c0-20:from-pstn"/>
+
+

This group would be used the same way as before in the bridge application, and all the calls coming from these channels would be treated in context from-pstn. +
+

+

<cadences>

+

Defines settings for the Endpoint cadences. +

In this case, the options are names cadences, followed by one or two pairs of numbers - that define the ranges of tone and silence to be used in cadences. +For details, please refer to the configuration file for examples. +
+

+

<fxs-branches>

+

Defines source numbers for the board KFXS. +

In this case, the options are sequences of prefixes of branches and serial numbers of the boards, which define the basic numbers of source addresses, and the numerical order of the boards. The format of the options is: +

+
<param name="prefixo" value="serial1, serial2, ...."/>
+
+

For example, if two KFXS-300 SPX boards with serial numbers K0374 and K2352 must be numbered sequentially, starting from branch 200, you may write: +

+
<param name="200" value="374, 2352"/>
+
+

This will define the first branch of board 'K0374 as number 200, the second as 201, and so one. The first branch from board K2352 will have number 230 (as K0374 has 30 channels), the second will be numbered 231, and so on - until the last channel, numbered 259. +

For more details, please refer to the configuration file for other exemples. +
+

+

<fxs-hotlines>

+

Sets hotlines for the KFXS based boards +

In this case, the options are sequences of branches and sequences of destination numbers, which define branches to be treated as "hotlines" and numbers to be dialed when they are take off hook. For instance: +

+
<param name="100" value="1234"/>
+<param name="200" value="4321"/> 
+
+

In the first line, the branch numbered 100 will call extension 1234 when taken off hook, while in the second one, branch 200 will call number 4321 when taken off hook. +
+

+

<fxs-options>

+

Allows you to set specific settings for FXS extension. +

In this case, the settings are extension numbers (based on those defined in the <fxs-branches>), and the options and their values. +

+
  • context; +
  • input-volume; +
  • output-volume; +
  • accountcode; +
  • calleridnum; +
  • calleridname; +
  • mailbox; +
  • flash-to-digits. +
+

Each option is separated from each other by a pipe "|" or a slash "/" and defined after the colon ":". Example: +

+
<param name="200" value="language:en|context:master-branch" />
+
+

For more information on the syntax and examples, please refer to the configuration file. +

For more information visit the configuration file 'khomp.conf.xml'. +
+

+

FreeSWITCH Configuration

+

When connections are received on the boards and devices Khomp, they are forwarded by the Endpoint to specific contexts within the dialplan of FreeSWITCH®. These settings can be changed via the configuration file khomp.conf.xml, available on the FreeSWITCH configuration directory (by default, "/usr/local/freeswitch/conf/autoload_configs"). +

For details about the specific contexts, see section Endpoint configuration. +

Below are details of how to configure the settings for incoming calls +
+


+

+

Contexts for E1 channels

+

For E1 boards, inbound contexts are predefined as option context-digital with default value as following: +

+
<param name="context-digital" value="khomp-DD-LL"/>
+
+

This standard defines the context that links will be redirected in accordance with the number of the board and number of the link: DD is the device number (two digits), and LL is the number of the link (also with two digits). +

However, it is possible to configure other inbound contexts, with different formats. There is format CCC, which means the channel number on the card (three digits), and SSSS, which represents the serial board number (with four digits). +

Examples for configuration entries (khomp.conf.xml): +

+
<!-- Serial board number and sequential link (ex: khomp-01-00) -->
+<param name="context-digital" value="khomp-DD-LL"/>
+
+
<!-- Serial board number and sequential link (ex: khomp-3049-00) -->
+<param name="context-digital" value="khomp-SSSS-LL"/>
+
+
<!-- Sequential board number and the channel (ex: khomp-00-001) -->
+<param name="context-digital" value="khomp-DD-CCC"/>
+
+
<!-- Receive all calls in one context (khomp-digital) -->
+<param name="context-digital" value="khomp-digital"/>
+
+

Follows an example the context usage inside the dialplan: + +

+
<!--
+The present context in 'extensions.conf' will handle calls
+that come from the link 0 (first link) of the board 0.
+-->
+<context name="khomp-00-00">
+             .
+             .
+             .
+</context>
+
+

Another example, using the same format: + +

+
<!-- 
+The present context in 'extensions.conf' will handle calls
+that come from the link 1 (second link) of the board 0.
+-->
+<context name="khomp-00-01>
+             .
+             .
+             .
+</context>
+
+

A complete example, with a few simple actions: + +

+
<context name="khomp-00-00">
+    <extension name="exemplo_1">
+        <condition field="destination_number" expression="^1234$">
+            <action application="bridge" data="Khomp/b0L1/2345"/>
+        </condition>
+    </extension>
+    <extension name="exemplo_2">
+        <condition field="destination_number" expression="^23(\d{2})$">
+            <action application="bridge" data="sofia/${use_profile}/11$1@${sip_from_host}"/>
+        </condition>
+    </extension>
+</context>
+
+
<context name="khomp-00-01">
+    <extension name="exemplo_3">
+        <condition field="destination_number" expression="^1111$">
+            <action application="bridge" data="Khomp/b0L0/2345"/>
+        </condition>
+    </extension>
+</context>
+
+

This dialplan defines that: +

+
  1. The incoming calls on the link 0 of the board 0 will have the following handling: +
    • Calls to the extension 1234 for will be redirected to the second link on the first board (b0L1), calling number 2345; +
    • Calls to any four digit number starting with23 will be redirected to SIP phones numbered 11 plus the last two digits of the number dialed. +
    +
  2. The incoming calls on the link 1 of the board 0 for the number 1111 will be redirected to the first link of the first board (b0L0) calling number 2345. +
+

Contexts of FXS/FXO/GSM channels

+

Just as in the context of E1 cards, inbound links are forwarded to the Endpoint FreeSwitch. +

The context is pre-defined as follows, according to the file khomp.conf.xml: +

+
<param name="context-gsm" value="khomp-DD-CC"/> ;placas GSM
+
+
<param name="context-fxs" value="khomp-DD-CC"/> ; placas FXS
+
+
<param name="context-fxo" value="khomp-DD-CC"/> ; placas FXO
+
+

For these options, DD is the device number (two digits), and CC is the channel number (also two digits). There is also the SSSS format, which represents the serial number board. +

+
  • NOTE: In the KGSM board, incoming calls are always redirected to the "s" extension, since the GSM protocol does not identify the target number, only the originator - if not omitted. +
+

Priority settings on the FXS branches

+

On calls originated from an FXS branch, the Endpoint searches for a valid extension (digits sent) after the DTMF # or after the timeout (option fxs-digit-timeout). That search is done in the context defined in section <fxs-options>, or if no context configured, the search is done in context defined in context-fxs. +
+

+

Contexts for SMS messages (GSM only)

+

SMS messages are received by the Khomp Endpoint and forwarded to FreeSWITCH as a normal connection but no audio, which has some variables set with information received in the message - for more information on these variables, see the documentation of the variables of the Endpoint. This context can also be modified in the same way as the above contexts. +

The default value for this option follows (khomp.conf.xml): +

+
<param name="context-gsm-sms" value="khomp-sms-DD-CC"/> 
+
+

Where DD is the device number (two digits), and CC is the channel number (also with two digits). For example: +

+
<context name="khomp-sms-00-01">
+    <extension name="sms">
+        <condition field="destination_number" expression="^s$">
+            <action application="log" data="DEBUG KSmsType=${KSmsType}"/>
+            <action application="log" data="DEBUG KSmsBody=${KSmsBody}"/>
+        </condition>
+    </extension>
+</context>
+
+

Contexts for Khomp_PR channels (KPR)

+

For these cards, inbound links have a pre-defined context, as shown below: +

+
<param name="context-pr" value="khomp-DD-CC"/> 
+
+

In this case, DD is the device number (two digits), andCC is the channel number (also two digits). The name and format of this context can also be changed through the "context-pr" in the configuration file. +
+

+

Groups contexts

+

The section groups, in the configuration file khomp.conf.xml, can be used to define specific settings for certain groups of channels. +

This section is detailed in the section Endpoint Configuration. +
+

+

Using the bridge application

+

The bridge application is responsible for generating calls from the FreeSWITCH from a dialplan. This application can be used to generate calls from different Endpoints technologies, following a specific format to define destination, dialing options and define the communication Endpoint to be used. +

+

Fields relating to the Khomp Endpoint

+

When used for Khomp channels, the bridge string can have two, three or four fields separated by slash (/). Some example strings: + +

+
<action application="bridge" data="Khomp/B2L0/32625644"/>
+<action application="bridge" data="Khomp/*B2L0/32625644"/>
+<action application="bridge" data="Khomp/S0411/99991234"/>
+<action application="bridge" data="Khomp/Gpstn/99991234"/>
+<action application="bridge" data="Khomp/*Gpstn/99991234"/>
+<action application="bridge" data="Khomp/B2C58/32625644/category=4:orig=4855553232"/>
+<action application="bridge" data="Khomp/b0c9"/>
+<action application="bridge" data="Khomp/b0c1+b0c14"/>
+<action application="bridge" data="Khomp/r304"/>
+
+

In the first five examples, three fields have been specified; in the sixth, four fields are used; in the last three examples, just two are used. +

The fields description for the Khomp Endpoint: +

+
  • 1st field: Khomp: identifying the type of Endpoint in question; +
  • 2nd field: B2L0, S0411, Gpstn, etc: represents the Policy for channel allocation (detailed below); +
  • 3rd field: 32625644 and 99991234: the destination numbers (missing for calls to KFXS channels); +
  • 4th field: category=4:orig=4855553232: additional options, detailed below. +
+

NOTE: The bridge allocation string with only two fields is specific to the KFXS boards, where the destination is the channel itself. +

+

Policy for channel allocation

+

The policy for allocation of channels on the Khomp Endpoint can be specified in the bridge string itself or in the groups section (inside the configuration file khomp.conx.conf). To specify boards, links and channels, the following syntax is available (considering X, Y and Z as any numbers): +

+
  • bX -- search the channels on the board X, ascending order; +
  • bXLY -- search channel on the link Y from X board, ascending order; +
  • bXcY -- try to allocate channel Y from board X; +
  • bXcY-Z -- search for channels starting from channel Y to channel Z (inclusive) of board X, ascending order; +
  • BXcY-Z -- same as above, but descending order; +
  • sX -- search the channels on the board of serial number X, ascending order; +
  • sXLY -- search channel on the link Y from board of serial number X, ascending order; +
  • sXcY -- try to allocate channel Y from board of serial number X; +
  • sXcY-Z -- search for channels starting from channel Y to channel Z (inclusive) from board of serial number X, ascending order; +
  • SXcY-Z-- same as above, but descending order. +
+

To search for extensions of cardsKFXS according to the extension number, can be used the following syntax (whereas X and Y valid extension numbers): +

+
  • rX- search branch numbered X; +
  • RX- equivalent to the above; +
  • rX-Y- search from branch X to Y, ascending order; +
  • RX-Y- search from branch X to Y, descending order. +
+

The capitalization of the letter 'B', 'S' or 'R' defines the search order of the channels: if capitalized, order is descending; otherwise, ascending. +

As for the allocation of channels across groups, the following syntax is available: +

+
  • ggroupname - uses the string defined the group "groupname" in the configuration file (detailed in the configuration section of the Endpoint). +
  • Ggroupname - equivalent to the above. +
+

Grouping channel allocations

+

There are cases where you need to get more channels for a particular device or particular group of extensions. For this, there is an extension available in string allocation, with respect to the use of token sum (+) to concatenate multiple stringsbinding, as follows: + +

+
<action application="bridge" data="Khomp/B1L0+B2L0/32332933"/>
+<action application="bridge" data="Khomp/*B2+B3+B4/99887766"/>
+<action application="bridge" data="Khomp/S0411+B1L0/99887766"/>
+<action application="bridge" data="Khomp/Gpstn1+Gpstn2/99991234"/>
+<action application="bridge" data="Khomp/*gOperadora1+gOperadora2/98891234"/>
+
+

This grouping is available for the application bridge and on the specification of groups. The processing of allocation takes place from left to right - except when using cyclic channel allocation, whereall the specified channels are scanned simultaneously. +

+

Cyclical and/or fair allocation

+

Another way for allocation of channels is the cyclic and/or fair allocation, which chooses the channel that has completed the the lowest number of outgoing calls. This mode of allocation may be used by passing an asterisk (*) before the allocation string of channels (as can be seen in the section above, in the second and fifth examples). +

When started with an asterisk (*), other forms of allocation (increasing, decreasing, etc) are used to decide what channel will be allocated when there are two or more channels with less number of outgoing calls. +

+
  • WARNING: The use of fair and/or cyclic is recommended only for analog (KFXO), branches (KFXS) and cellular interface (KGSM) boards. E1 connections should allocate channels in one way (ascending/descending) from one side and the opposite on the other to avoid problems of double seizure (which may occur in R2/MFC signaling). Fair/cyclic allocation also costs more in memory and processor footprint, which tends to be a higher cost in E1 due to the higher number of channels (30 in each link).

    For these reasons, fair/cyclic allocations should only be used on signalizations where it can represent any real difference, like equalizing the charge costs of the lines, the total usage, or the number of connections received by each branch. +
+

Available options

+
  • orig: Sets the originator number, without changing the variable ${CALLERID(num)}. That is, the option orig serves only to pass a number of different source of${origination_caller_id_number}. If FreeSWITCH has already set the variable ${origination_caller_id_number}, which is the default behavior, Endpoint automatically uses this value as a reference to the number of origin, without having to pass any additional options.

    On the boards KGSM, is set to restricted, omits the number of origin. Example:
    +
+
+ <action application="bridge" data="Khomp/b0/99887766/orig=restricted"/>
+
+
  • category: When set to a numeric value, sets the category of outgoing call to this value (available only in R2/MFC signaling); +
  • uui: When adjusted for a number and a string of text, separated by hash ("#"), sends a "UserToUser" to the other end before making the call - the first value will be the descriptor and the second one will be the message as the text (available only in ISDN signaling); +
  • ring_cadence: When set to a cadence name (listed in the [cadences] section), uses this for ringing FXS channels; +
  • ring: When set to two numbers separated by a dot ("."), defines the cadences to be used while ringing a FXS channel - the first time is the ringing time, and the second one, the silence time; +
  • ring_ext: When set to two numbers separated by a dot ("."), defines the extended cadences to be used while ringing a FXS channel, executed after the ring specification - the first time +
  • usr_xfer: Defines a group of DTMF digits to initiate a transfer between PBXes (using QSig or FXO FLASH, for instance); +
  • drop_on: When set to "message_box", "human_answer", "answering_machine", "carrier_message", "unknown" or a list them - separated by plus sign ("+") or dot ("." ) - drops the call when detect voice mail box, human answer, answering machine messages, operator messages, or unknown answer pattern - respectively. Available in digital signals (E1 links and boards KGSM). Additionally, the information service is reported to the user in the variableKCallAnswerInfo; +
  • answer_info: When specified (take no parameters), report answer information to the user through the variableKCallAnswerInfo +
  • pre: When set to a string of DTMF digits, uses these to pre-allocate an output channel in an analog PABX, dial the desired number of B below. Only available for signaling analog (FXO); +
  • pre_answer: When set (need no value), answers the channel before the connection is completed - allowing, for instance, DTMF tones to sent (useful for use in a DISA); +
  • output_volume: Sets the output volume of the link (ranges from -10 to +10); +
  • input_volume: Sets the volume of inbound link (ranges from -10 to +10); +
+


+

+

List of variables

+

Here's a list of variables available in the Endpoint: +

+
  • KDropCollectCall: When set before ringing or answer an incoming call, enables ("yes") or disables ("no", default) the drop of collect calls based on signaling received from the central public, double answer, audio tone recognition (can be defined globally); +
  • KR2SendCondition: When set to a numeric value, before the ringing an incoming call, adjusts the condition for this Endpoint to this value (available only on R2 signaling); +
  • KR2GotCategory: Adjusted by the Endpoint when an incoming call is received, with the category number of the caller (only available on R2 signaling); +
  • KR2GotCondition *: Adjusted by the Endpoint, available after returning from a call made by FreeSWITCH (bridge application). Has the condition of the remote end received when making the call (available only for R2 signaling); +
  • KISDNGotCause *: Adjusted by the Endpoint, available after returning from a call made by FreeSWITCH (bridge application). Has the ISDN "cause" code received when making the call (available only for ISDN signaling); +
  • KCallAnswerInfo *: Adjusted by the Endpoint, available after returning from a call made by FreeSWITCH (bridge application). Contains the service information identified to make the call (available only for digital signaling - E1 and GSM); +
  • KSmsDelivered: Adjusted by the Endpoint when sending a SMS message with the application KSendSMS, saying whether the message was delivered successfully ("yes") or not ("no"); +
  • KSmsErrorCode: Adjusted by the Endpoint when sending a SMS message with the application KSendSMS, containing the error code that happened when sending the message; +
  • KSmsErrorName: Adjusted by the Endpoint when sending a SMS message with the application KSendSMS, contains the name of the error or "None" if there has been no error; +
  • KSmsType: Adjusted for the input Endpoint in the context of SMS messages, defines the type of message received (can contain the values "message", "confirm" or "broadcast"; +
  • KSmsFrom: Adjusted for the input Endpoint in the context of SMS messages, sets the number of origin of the received message (available on types" message "and" confirm "); +
  • KSmsDate: Adjusted for the input Endpoint in the context of SMS messages, sets the date of sending the message (available on types "message" and "confirm"); +
  • KSmsSize: Adjusted for the input Endpoint in the context of SMS messages, contains the size (in bytes) of the received message (available on types "message" and "broadcast"); +
  • KSmsMode: Adjusted for the input Endpoint in the context of SMS messages, contains the encoding type of the received message (available on types "message" and "broadcast"); +
  • KSmsBody: Adjusted for the input Endpoint in the context of SMS messages, contains the text of the received message (available in types "message" and "broadcast"); +
  • KSmsDelivery: Adjusted for the input Endpoint in the context of SMS messages, containing the date of delivery of the message sent earlier (available in type "confirm"); +
  • KSmsStatus: Adjusted for the input Endpoint in the context of SMS messages, contains the status of the message sent earlier (available on the type "confirm"); +
  • KSmsSerial: Adjusted for the input Endpoint in the context of SMS messages, contains the serial number of the received message (available on the type "broadcast"); +
  • KSmsPage: Adjusted for the input Endpoint in the context of SMS messages, contains the page number of the received message (available on the type broadcast"); +
  • KSmsPages: Adjusted for the input Endpoint in the context of SMS messages, contains the total number of pages to be received (available in type "broadcast"); +
  • KUserInfoDescriptor: Sets/reports protocol descriptor of the User-to-User Information message (ISDN). +
  • KUserInfoData: Sets/reports data in the User-to-User Information message (ISDN). +
  • KFaxSent: Adjusted by the Endpoint when sending FAX with KSendFax application, and determines whether the fax was successfully sent ("yes") or not ("No"); +
  • KFaxReceived: Adjusted by channel when receiving FAX with KReceiveFax application, and determines whether the fax was successfully received ("yes") or not ("no"); +
  • KFaxResult: Adjusted by the channel when sending or receiving FAX with the application KSendFax or KReceiveFax (respectively), and defines the result of execution. +
+


+

+

Description of variables

+

Below, follows an explanation on how to use variables of Khomp Endpoint in the dialplan, to communicate and/or to receive information: +


+

+

KDropCollectCall

+

When activated, causes the Endpoint to drop Khomp collect calls through dual service (available for signaling 'R2 Digital' and FXO), through information available on the ISDN protocol and R2/MFC, or by detecting the audio call collect (available for any digital signage for E1, and GSM signaling). +

This variable is useful to filter collect calls to certain extensions, and must be set before making any type of answer - applications such as playback and bridge should always be executed after setting this variable, for example. +

For better functionality, is also recommended that no call status (ringback) is sent before this variable is set, so applications should be performed only after the correct setting of this variable. +

This variable can be set locally and globally, both to yes or no. The adjustment of global variable to yes will drop all the collect calls, unless the particular call is set to no - this allows the creation of a global filter of collect calls, with few exceptions. +

Enabling the variable in context default: +

+<context name="default"> +

+
<extension name="example">
+ .
+ .
+ .
+ <action aplication="set" data="KDropCollectCall=yes"/>
+ .
+ .
+ .
+</extension>
+
+

</context> +

Enabling the variable in the global context, remembering that it must be configured in the file vars.xml: + +

+
<X-PRE-PROCESS cmd="set" data="KDropCollectCall=yes"/>
+
+

KR2SendCondition

+

When you receive a call, can be set before sending ringback by FreeSWITCH (ie, before the run FreeSWITCH applications answer, bridge). When used in signaling R2/MFC, this variable sets the condition for B to the numeric value desired. +

Exemplo: + +

+
<!-- Condition "NUMBER CHANGED" warns the caller that the number of B has changed. -->
+<action application="KR2SendCondition" data="3"/>
+
+

KR2GotCategory

+

When you receive a call, is set by the Endpoint with the category received from the number that originated the call. It is set in signaling R2/MFC, and can be found anywhere in the dialplan. +

Example: + +

+
<action application="log" data="DEBUG KR2GotCategory [${KR2GotCategory}]"/>
+
+

KR2GotCondition

+

Variable adjusted by the Endpoint, and available after returning from a call made by FreeSWITCH. Has the condition of B received when making the call. Available only for signaling R2/MFC. +

Example: + +

+
<action application="log" data="DEBUG KR2GotCondition [${KR2GotCondition}]"/>
+
+

KUserInfoDescriptor

+

Variable adjusted by the Endpoint in the context of entry, from information received by the ISDN network functionality through user-to-User Information. Contains the descriptor number of the protocol used by the other end, and usually contains the value '0 ', but this is dependent on application. +

For further information, consult the specification ITU-T Q931 (more precisely, the specification table 4-26). +

Example (working with the descriptor number of the protocol): + +

+
<action application="log" data="DEBUG KUserInfoDescriptor [${KUserInfoDescriptor}]"/>
+
+

KUserInfoData

+

Variable adjusted by the channel in the context of entry, from information received by the ISDN network functionality through user-to-User Information. Contains the actual data, which were received in the form of a string of text. +

More information about this feature, see the specification ITU-T Q931. +

Example (working with the data received): + +

+
<action application="log" data="DEBUG KUserInfoData [${KUserInfoData}]"/>
+
+

It is important to note that the variables are sensitive to the capitalization of letters (case sensitive). +

+

KCallAnswerInfo

+

Variable adjusted by the Endpoint. It is set in outbound connections, representing the type of answer performed by the other end. May contain the following values: +

+
  • "MessageBox" (*): detected mailbox of a cell phone; +
  • "CarrierMessage": message sent before the service provider; +
  • "AnsweringMachine" (**): answering answering machine; +
  • "HumanAnswer" (**): human service; +
  • "Fax": reported when a fax tone is detected. +
  • "Unknown": unknown type of care; +
+
+

(*) This type of service is detected by signals at certain frequencies that are sent before the call comes into a mailbox, and vary by operator. The algorithm captures most of the mailboxes, but can fail if there is not a clear signal, or if it is not within the standards most commonly used; +

(**) The difference between these two types of care depends on the specific configuration using the program k3lanswerinfoconfig, with the detection only based on heuristics and never with an accuracy of 100%. +
+

+

Console commands

+

List of available commands in the console for the FreeSWITCH Endpoint of Khomp: +


+

+
  • khomp channels disconnect : Disconnect one or more channels. This command sends a message directly to the physical channel of the card in question, requesting a disconnection. Use with caution; +
  • khomp channels unblock : Unlock blocked channels for input or output. Only available in digital signage via E1; +
  • khomp clear links: Clears error counters on the links; +
  • khomp clear statistics: Clears the statistics of channel connections, or statistics for a particular channel; +
  • khomp get : Gets the number of options Endpoint Khomp; +
  • khomp kommuter : Enables or disables kommuters connected via USB on this machine. Only accessible when the configuration "kommuter-activation" is set to "manual". +
  • khomp kommuter count: Gets the amount of kommuters connected via USB on this machine; +
  • khomp log console: Sets options in the console logs; +
  • khomp log disk: Sets logging options to disk; +
    • khomp log console and khomp log disk have auxiliary options No, which reverses the selection of messages, and just, which generalizes the choice. Examples: +
      • khomp log disk just commands events (Enables only logging to the disk of commands and events); +
      • khomp log disk no commands (Disable logging to the disk of commands sent to board); +
      • khomp log disk warnings (Enables also logging to the disk of warnings from Endpoint). +
      +
    • More information on options for the log command, type: "help khomp log disk" or "help console log khomp". +
    +
  • khomp log rotate: Rotate log files from the Endpoint; +
  • khomp log status: Shows log messages currently being written to disk and displayed on the console; +
  • khomp log trace isdn: Enable Debugging ISDN signaling; +
  • khomp log trace k3l : Enables debugging low-level API K3L; +
  • khomp log trace r2 : Enables debugging low-level signaling R2/MFC; +
  • khomp reset links: Sends a reset command for a specific E1 of a particular card; +
  • khomp revision: Shows version number and revision of the Endpoint; +
  • khomp select sim: Select the SIM card, available on the boards KGSM; +
  • khomp send command : Sends command API K3L directly to the board (only for debugging, may compromise the stability of the system if used improperly); +
  • khomp send raw command : Sends a command directly to the DSP board (only for debugging, may compromise the stability of the system if used improperly); +
  • khomp set : Sets various options of the Endpoint Khomp; +
  • khomp show calls : Shows states for calls, may also listing specific channels or boards; +
  • khomp show channels : Shows the status of the channels Khomp and may also list specific adapter; +
  • khomp show links: Display states of E1 links available. +
  • khomp show statistics : Shows the statistics of channel connections, or statistics for a particular channel; +
  • khomp sms : Send an SMS message for a given number, using KGSM channels; +
  • khomp summary : Prints a summary of system boards and their features; +
+


+

+

Additional features

+

This chapter discusses additional features of the Endpoint, related to the special features present in certain signs. +
+

+

Aplicações (applications) e canais

+

The Endpoint Khomp, and to record a type of communication channel "Khomp" also records the following items: +
+

+

"KUserTransfer" application

+

Performs the transfer process from the current channel number for the extension using the signaling protocol QSig (Single Step Call Transfer) for boards configured with E1 ISDN signaling (ISDN), or use the FLASH command for FXO. +

The syntax follows: +

+
 <action application="KUserTransfer" data="number[,options])"/>
+
+

Example: +

+
<action application="answer"/>
+<action application="KUserTransfer" data="2345"/>
+
+

The fields have the following meanings: +

+
  • number: Number where the link should be transferred. +
  • options: Sets the transfer options to be used, which are: +
    • N: Wait until the channel is disconnected. +
    +
+


+

+

Application "KSendSMS"

+

This application has the function of sending SMS messages through the boards of KGSM Khomp using modules and SIM cards in the board to do so. The syntax of the application is as follows: +

+
<action application="KSendSMS" data="resource | destination | message" />
+
+

Each field can be summarized in: +

+
  • resource: The following is a syntax identical to the allocation of channels Dial application, and defines what modem use; +
  • destination: Number where to send the message, may be preceded or succeeded by! to request a confirmation of transmission; +
  • message: Text (without quotes) to be sent todestination. +
+

After sending the message, the variables KSmsDelivered and KSmsErrorCode will contain the result of the post. For more information about these, please consult the section on variables used in the Endpoint. +

Examples of use of this application are as follows: +

+
  • Sends "Test message." phone for "99887766" using the modem "1" (second modem) card "0": +
+
<action application="log" data="DEBUG Sending SMS ..." />
+<action application="KSendSMS" data="b0c1|99887766|Test message" />
+
+
  • Sends "Test message." phone for "99887766" using the first free modem card "0", and checks the return shipment: +
+
<action application="log" data="DEBUG  Sending SMS ..." />
+<action application="KSendSMS" data="b0|99887766|Test message" />
+<action application="log" data="DEBUG Sent? ${KSmsDelivered}" />
+<action application="log" data="DEBUG Code: ${KSmsErrorCode}" />
+<action application="log" data="DEBUG Desc: ${KSmsErrorName}" />
+
+
  • Sends "Test message." phone for "99887766" using the first free modem card "0", or the first free channel board "1" (if no free channel at the first sign): +
+
<action application="log" data="DEBUG Sending SMS ..." />
+<action application="KSendSMS" data="b0+b1|99887766|Test message" />
+
+
  • Sends "Test message." phone for "99887766" using the first free modem card "0", requesting confirmation: +
+
<action application="log" data="DEBUG Sending SMS ..." />
+<action application="KSendSMS" data="b0|99887766!|Test message" />
+
+


+

+

Application "KEchoCanceller"

+

This application has the function to enable or disable the echo canceller channel. +

+
<action application="KEchoCanceller" data="action[,options])"/>
+
+

Where: +

+
  • actions: It is on to enable the echo canceller, and off to disable; +
+

Example usage of this application: +

+
<action application="KEchoCanceller" data="off"/>
+
+


+

+

Application "KAutoGainControl"

+

This application has the function to enable or disable the automatic gain control in the channel. +

+
<action application="KAutoGainControl" data="action[,options])"/>
+
+

Where: +

+
  • actions: It is on to enable the automatic gain control, and off to disable; +
+

Example usage of this application: +

+
  <action application="KAutoGainControl" data="on"/>
+
+


+

+

Application "KDTMFSuppression"

+

This application has the function to enable or disable the suppression of DTMF channel. The syntax of the application is as follows: +

+
<action applicatin="KDTMFSuppression" value="action[,options])"/>
+
+

Where: +

+
  • actions: It ison to enable DTMF suppression, and off to disable; +
+

It is important to note that when disabled suppression of DTMF, DTMF tones are passed inband and will not be reported to FreeSWITCH. Thus FreeSWITCH does not recognize the DTMF tones, which may result in malfunction of applications such as IVR. +

Example usage of this application: +

+
<action applicatin="KDTMFSuppression" value="off"/>
+
+


+

+

Application "KSetVolume"

+

This application has the function to adjust the volume of incoming and outgoing channels Khomp, and its syntax as follows: +

+
<action application="KSetVolume" data="<volume>"/>
+<action application="KSetVolume" data="<output-volume>|<input-volume>"/>
+
+

Where the fields have the following meanings: +

+
  • volume: Sets the volume of input and output (-10 to +10); +
  • output-volume: Sets the output volume (-10 to +10, "none" for no change); +
  • input-volume: Sets the input level (-10 to +10, "none" for no change). +
+


+

+

Application "KAdjustForFax"

+

This application has the function of setting a channel for receiving Khomp signal FAX/modem, optimizing the communication channel for data traffic. Syntax: +

+
<action application="KAdjustForFax" data=""/>
+
+

This application does not receive parameters. Example of use: +

+
<action application="KAdjustForFax" data=""/>
+
+


+

+

Application "KSendFax"

+

This application has the function to send faxes using digital channels or FXO connections Khomp in pre-established, and its syntax as follows: +

+
<action application="KSendFax" data="<file>[:<file2>[:...]][|<faxid>]"/>
+
+

This application requires a license purchased separately to be used in digital (non-FXO) channels. Fields have the following meanings: +

+
  • file: Files to be sent to the fax should be encapsulated in TIFF format and have a resolution of 98, 196 or 392 dpi; +
  • faxid: the fax number. If not specified, the value is obtained by the id of the link, and if this also is not valid, the fax number will be set as default in K3L. +
+

Example usage of this application: +

+
<action application="KSendFax" data="/tmp/fax.tif:/home/root/fax2.tif,1234"/>
+
+


+

+

Application "KReceiveFax"

+

This application has the function of receiving digital channels or fax using the FXO Khomp, and its syntax as follows: +

+
<action application="KReceiveFax" data="<file>[|<faxid>]/>
+
+

This application requires a license purchased separately to be used in digital (non-FXO) channels. Fields have the following meanings: +

+
  • file: Name that file will be assigned to incoming fax. +
  • faxid: the fax number. If not specified, the value is obtained by the id of the link, and if this also is not valid, the fax number will be set as default in K3L. +
+

Example usage of this application: +

+
<action application="answer" />
+<action application="KReceiveFax" data="/tmp/fax.tif"/>
+
+


+

+

Channel "Khomp_SMS"

+

This communication channel is used to receive SMS and create incoming links in FreeSWITCH for each message received. This channel does not have any treatment or audio processing, and is called with five variables set: +

+
  • KSmsFrom, containing the number of source who sent the message; +
  • KSmsDate, which sets the date/time of receipt of the message; +
  • KSmsSize, representing the message size (in bytes); +
  • KSmsMode, containing the encoding used to transmit the message; +
  • KSmsBody, that is the message itself. +
+

The FreeSWITCH dialplan processing can be used to store this message in a database, run any application, among others. However, the only action accepted by this channel is shutdown (Hangup), so this incoming call should be considered a special dialplan execution without audio streams or channel allocation. +
+

+

Channel "Khomp_PR"

+

This communication channel is used to receive calls on boards passive recording (KPR family and KFXO-HI), creating incoming links on FreeSWITCH for each incoming call. This channel allows only receiving audio captured the linkby not allowing both the transmission of audio signalings as the control. +

The FreeSWITCH dialplan processing can be used to record data on this link in a database, perform some special application and/or some recording application (such as record), among others. However, the only action accepted by this channel is shutdown (Hangup), so this should not be considered a common call. +
+

+

Codes and meanings

+

This chapter presents the codes present in the channel Khomp and their meanings, used in both events as in the AMI console commands: +
+

+

Channel state

+

Reflect the state of the channel on the board. In the case of E1 links, the state may have one or more of the following: +

+
  • Free: the channel is free; +
  • Busy: the channel is not free (or occupied, or failure); +
  • Outgoing: the channel has an output connection; +
  • Incoming: the channel has an input connection; +
  • Locked: the channel is blocked; +
  • Outgoing Lock: The channel is blocked for outgoing calls; +
  • Local Fail: The channel has a fault (at this point); +
  • Incoming Lock: the channel is blocked for incoming calls; +
  • Remote Lock: there is a remote lock (at the other end) in this channel. +
+

In the case of a FXS channel, the state is defined by one of these values: +

+
  • On Hook: the phone connected to this channel is on-hook or disconnected; +
  • Off Hook: the phone connected to this channel is off the hook; +
  • Ringing: the channel is being called; +
  • Failure: the channel is in failure due to communication problems between the central and the plate. +
+

In the case of a GSM channel, the state is defined by one of the following values: +

+
  • Idle: the channel is free and available for calls; +
  • Call In Progress: the channel is busy on a call; +
  • SMS In Progress: the channel is busy sending / receiving SMS messages; +
  • Modem Error: an error occurred communicating with the modem channel; +
  • SIM Card Error: The SIM card is not present or is not inserted / detected correctly; +
  • Network Error: an error occurred while communicating with the network; +
  • Not Ready: The modem is initializing the channel. +
+

And in the case of an FXO channel, the states are as follows: +

+
  • Disabled: the channel is disabled; +
  • Enabled: the channel is enabled. +
+


+

+

Call state

+

Defines the logical state for each channel, which can be: +

+
  • Free: the channel is free; +
  • Incoming: the channel is receiving a call; +
  • Outgoing: the channel is making a call; +
  • Failure: the channel is in fault. +
+


+

+

FreeSWITCH call states

+

Directly reflects the call state controlled by FreeSWITCH, which can be: +


+

+
  • new: Channel is newly created; +
  • init: Channel has been initialized; +
  • routing: Channel is looking for an extension to execute; +
  • execute: Channel is executing its dialplan; +
  • ex_media: Channel is exchanging media with another channel; +
  • cs_media: Channel is consuming all media; +
  • hangup: Channel is flagged for hangup and ready to end. +
+


+

+

GSM Codes

+

The following numeric codes are reported: +

+

SMS codes (SMS causes)

+
1	Unassigned number
+8	Operator determined barring
+10	Call barred
+21	SMS transfer rejected
+27	Destination out of service
+28	Unidentified subscriber
+29	Facility rejected
+30	Unknown subscriber
+38	Network out of order
+41	Temporary failure
+42	Congestion
+47	Resources unavailable
+50	Facility not subscribed
+69	Facility not implemented
+81	Invalid SMS transfer reference value
+95	Invalid message
+96	Invalid mandatory information
+97	Message type non existent
+98	Message not compatible with SMS protection state
+99	Information element non existent
+111	Protocol error
+127	Interworking
+128	Telematic interworking not supported
+129	SMS type zero not supported
+130	Cannot replace SMS
+143	Unspecified TPPID error
+144	Alphabet not supported
+145	Message class not supported
+159	Unspecified TPDCS error
+160	Command cannot be actioned
+161	Command unsupported
+175	Unspecified TP command error
+176	TPDU not supported
+192	SC busy
+193	No SC subscription
+194	SC system failure
+195	Invalid SME address
+196	Destination SME barred
+197	SM rejected duplicate SM
+198	TPVPF not supported
+199	TPVP not supported
+208	SIM SMS storage full
+209	No SMS storage capability in SIM
+210	Error in SMS
+211	Memory capatity exceeded
+213	SIM data download error
+255	Unspecified error
+300	Phone failure
+301	SMS service reserved
+302	Operation not allowed
+303	Operation not supported
+304	Invalid PDU mode parameter
+305	Invalid text mode parameter
+310	SIM not inserted
+311	SIM PIN necessary
+312	Phone SIM PIN necessary
+313	SIM failure
+314	SIM busy
+315	SIM wrong
+320	Memory failure
+321	Invalid memory index
+322	Memory full
+330	SMSC address unknown
+331	No network service
+332	Network timeout
+500	Unknown error
+512	Network busy
+513	Invalid destination address
+514	Invalid message body length
+515	Phone is not in service
+516	Invalid preferred memory storage
+517	User terminated
+
+

Call codes (call causes)

+
1	Unallocated number
+3	No route to destination
+6	Channel unacceptable
+8	Operator determined barring
+16	Normal call clear
+17	User busy
+18	No user responding
+19	No answer from user
+21	Call rejected
+22	Number changed
+26	Non Selected user clear
+27	Destination out of order
+28	Invalid number format
+29	Facility rejected
+30	Response status enquiry
+31	Normal, unspecified
+34	No circuit channel available
+38	Network out of order
+41	Temporary failure
+42	Switch congestion
+43	Access information discarded
+44	Requested channel unavailable
+47	Resource unavailable
+49	QoS unavailable
+50	Request facility not subscribed
+55	Call barred with UG
+57	Bearer capability not authorized
+58	Bearer capability not available
+63	Service not available
+65	Bearer capability not implemented
+69	Request facility not implemented
+70	Only restricted bearer capability available
+79	Service not implemented
+81	Invalid call reference value
+82	User not member of UG
+88	Incompatible destination
+91	Invalid transit network selected
+95	Invalid message
+96	Missing mandatory information element
+97	Message type not implemented
+98	Message incompatible with state
+99	Information element not implemented
+100	Invalid information element
+101	Message incompatible with state (2)
+102	Recovery on timer expiry
+111	Protocol error
+127	Interworking
+
+

General codes (mobile causes)

+
0	Phone failure
+1	No connection to phone
+2	Phone adaptor link reserved
+3	Operation not allowed
+4	Operation not supported
+5	Phone SIM PIN required
+6	Phone FSIM PIN required
+7	Phone FSIM PUK required
+10	SIM not inserted
+11	SIM PIN required
+12	SIM PUK required
+13	SIM failure
+14	SIM busy
+15	SIM wrong
+16	Incorrect password
+17	SIM PIN2 required
+18	SIM PUK2 required
+20	Memory full
+21	Invalid index
+22	Not found
+23	Memory failure
+24	Text string too long
+25	Invalid character in text string
+26	Dial string too long
+27	Invalid character in dial string
+30	No network service
+31	Network timeout
+32	Network not allowed
+33	Command aborted
+34	Number parameter instead of text parameter
+35	Text parameter instead of number parameter
+36	Numeric parameter out of bounds
+37	Text string too short
+40	Network PIN required
+41	Network PUK required
+42	Network subset PIN required
+43	Network subset PUK required
+44	Network service provider PIN required
+45	Network service provider PUK required
+46	Corporate PIN required
+47	Corporate PUK required
+60	SIM Service option not supported
+100	Unknown
+103	Illegal MS #3
+106	Illegal MS #6
+107	GPRS service not allowed #7
+111	PLMN not allowed #11
+112	Location area not allowed #12
+113	Roaming not allowed #13
+132	Service option not supported #32
+133	Registration service option not subscribed #33
+134	Service option temporary out of order #34
+147	Long context activation
+148	Unspecified GPRS error
+149	PDP authentication failure
+150	Invalid mobile class
+151	GPRS disconnection TMR active
+256	Too many active calls
+257	Call rejected
+258	Unanswered call pending
+259	Unknown calling error
+260	No phone number recognized
+261	Call state not idle
+262	Call in progress
+263	Dial state error
+264	Unlock code required
+265	Network busy
+266	Invalid phone number
+267	Number entry already started
+268	Cancelled by user
+269	Number entry could not be started
+280	Data lost
+281	Invalid message body length
+282	Inactive socket
+283	Socket already open
+
+


+

+

Troubleshooting

+

In this section, errors and their most common solutions are presented. +

+

Error during installation of kernel module

+

During installation of the Endpointof Khomp may occur the following messages: + +

+
K3L: WARNING: Unable to find a module for [...]
+
+

or + +

+
install: ******  THE KERNEL MODULE HAS NOT BEEN INSTALLED: *******
+install: 
+install: ** Please, untar the file kpdriver*.tar.gz located in: **
+install: **                 '/usr/src/khomp/'                   **
+install: **             then check the README.txt               **
+install: **  for knowing how to proceed with the installation.  **
+
+

In this case, you must compile the drivers manually to your system. Proceed to the item below for more information. +
+

+

Compiling the drivers and starting the services

+

Just follow to the directory /usr/src/khomp, unpack the file "kpdriver_2.0.0XX.tar.gz", and follow procedures described in the file README_en.txt. +

After performing compilation and installation of the module, just load it into the system, configuring the boards and start the server processes Khomp. +

To load the kernel driver, you must run the following command: + +

+
# /etc/init.d/khompdrv start
+
+

To set up the boards, in turn, must run the command: + +

+
# khompwizard
+
+

This will run a setup wizard that will ask the signaling used in the system, as well as other parameters of use of the boards. +

If necessary configure other additional parameters you can use the following command: + +

+
# k3lconfig
+
+

This configurator, in turn, shows all possible options for card configuration. The parameters that are not configured automatically assume the default values, and are compatible with most systems. More details about this program can be obtained from the section number '2 '. +

+
  • ATTENTION': To start FreeSWITCH®, it is necessary that the board is configured Khomp and all modules are running (as shown above). If the card is not configured, FreeSWITCH will not start.

    If you want to run the system without the board Khomp, you need to configure FreeSWITCH for it does not load the module Khomp. To do this, open the "
    /usr/local/freeswitch/conf/autoload_configs/modules.conf.xml and comment the line:
    +
+
 
+<!-- <load module="mod_khomp" /> -->
+

+

When the board Khomp is properly configured and loaded modules khomp (explained above), remember to uncomment this line in the file. +

Finally, to load the server process, simply run the following command: + +

+
# kserver start
+
+

After performing these procedures, the Endpoint is already operational, and FreeSWITCH can now be loaded. +
+

+

Setting up special parameters for audio or signaling

+

To set specific parameters of timing and/or signaling, you can use the program "k3lconfig": simply select the card you want, and options of the boards will be presented, divided into sections and subsections for easy access. It is not necessary to effect the configuration of all parameters: default values are assumed, if not configured. +

To adjust the signaling link, simply - after selecting the card - enter the "Options signaling, and then in" Signs of the line. " To choose a particular signaling, just use the direction keys (arrows) to select it, press 'space', and confirm the option by pressing 'Enter' on the "Confirm" button. +

Finally, to save the modified settings, just exit the program: it will display a window with options to save the changes made or not. +

Please not that the following options are required to be unchanged from the defaults: +

+
  • Automatic echo cancellation; +
  • DTMF suppression; +
  • Automatic Gain Control (AGC). +
+

These options are controlled by Endpoint and should be disabled in 'k3lconfig' (the default configuration). +
+

+

Automatic load of services and kernel modules

+

If the loading of kernel module or Khomp services startup is not performed automatically at startup, you can perform this installation manually, creating a link for the scripts /etc/init.d/khompdrv and /etc/init.d/kserver in the system startup directory. +

In the case of Debian-based distributions the script for loading kernel modules would be linked within the directory /etc/rcS.d, while the services loader would be linked within the directories /etc/rc2.d, /etc/rc3.d, /etc/rc4.d, /etc/rc5.d as follows: +

+

+
# ln -s /etc/init.d/khompdrv  /etc/rcS.d/S19khompdrv
+# ln -s /etc/init.d/kserver   /etc/rc2.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc3.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc4.d/S20kserver
+# ln -s /etc/init.d/kserver   /etc/rc5.d/S20kserver
+
+

Please check the rules of your distribution to initialize the services in accordance with what is expected by the start of it. +
+

+

Apêndice

+

Nesta seção, encontram-se informações úteis sobre o Endpoint e componentes relacionados. +

+

Arrangement of installed files

+

The directories created/modified in this facility are: + +

+
/etc/init.d/                -- Startup scripts;
+
+/etc/khomp/                 -- Firmware files and settings;
+
+/usr/local/freeswitch/conf/ -- Settings for FreeSWITCH and Endpoint;
+
+/usr/doc/khomp/             -- Docs for the boards, Channel, and utilities;
+
+/usr/sbin/                  -- Utilities and server processes;
+
+/usr/lib/                   -- Shared libraries;
+
+/usr/local/freeswitch/mod/  -- Endpoint module;
+ 
+/var/log/khomp2.1/          -- Log directory for K3L and Endpoint;
+
+

The script /etc/init.d/khompdrv is responsible for loading modules kpci9030.ko and kpex8311.ko in the kernel, which should be carried out automatically at system startup. In case of problems, check the Troubleshooting section. +


+


+

\ No newline at end of file diff --git a/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf b/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf new file mode 100644 index 0000000000..832596bdb2 Binary files /dev/null and b/src/mod/endpoints/mod_khomp/docs/User_Guide.pdf differ diff --git a/src/mod/endpoints/mod_khomp/include/applications.h b/src/mod/endpoints/mod_khomp/include/applications.h new file mode 100644 index 0000000000..75f55ec5ca --- /dev/null +++ b/src/mod/endpoints/mod_khomp/include/applications.h @@ -0,0 +1,962 @@ +/******************************************************************************* + + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2010 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use your + version of this file under either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*******************************************************************************/ + +#ifndef _APPLICATIONS_H_ +#define _APPLICATIONS_H_ + +#include "lock.h" +#include "khomp_pvt.h" + +struct Application +{ + Application(Board::KhompPvt * pvt) : _pvt(pvt) {} + ~Application() {} + + Statistics * statistics() { return _app_statistics; } + + template + T* statistics() { return static_cast(_app_statistics); } + + Board::KhompPvt *_pvt; + Statistics *_app_statistics; +}; + +/*************************** FAX **********************************************/ +struct Fax +{ + Fax(Board::KhompPvt * pvt) : _pvt(pvt) {} + + /* + bool clear(Board::KhompPvt * pvt) + { + _pvt = pvt; + return true; + } + */ + + bool adjustForFax(); + + bool sendFax(switch_core_session_t * session, const char *data); + bool receiveFax(switch_core_session_t * session, const char *data); + + bool onFaxChannelRelease(K3L_EVENT *e); + + bool startFaxTX(const char * orig_addr = NULL); + bool stopFaxTX(); + bool startFaxRX(const char * filename, const char * orig_addr = NULL); + bool stopFaxRX(); + bool addFaxFile(const char * filename, bool last = true); + + + Board::KhompPvt *_pvt; + + /* used by app FAX */ + SavedCondition _fax_cond; + KFaxResult _fax_result; + +}; + +/*************************** TRANSFER *****************************************/ +template +struct Transfer +{ + Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {} + + bool clear() + { + if(!_is_ok) + { + _call = dynamic_cast(_pvt->call()); + + _is_ok = true; + + if(!_call) + { + DBG(FUNC, D("Error in cast")); + _is_ok = false; + } + } + + _call->_flags.clear(Kflags::XFER_DIALING); + + return true; + } + + bool userTransfer(switch_core_session_t * session, const char *data) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c")); + + std::string dest(""); + std::string opts(""); + + try + { + Strings::vector_type params; + + Strings::tokenize((const char *)data, params, "|,", 2); + + dest = params[0]; + + if (params.size() > 1) + { + // other options go here... + } + + ScopedPvtLock lock(_pvt); + + int timeout = 5; + + if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false)) + return false; + + DBG(FUNC, PVT_FMT(_pvt->target(), "flashing channel!")); + + _pvt->command(KHOMP_LOG, CM_FLASH); + + lock.unlock(); + + timeout = 15; // 15 * 200000 = 3s + + do + { + usleep(200000); + timeout--; + + ScopedPvtLock lock2(_pvt); + + if(!_pvt->call()->_flags.check(Kflags::IS_INCOMING) && !_pvt->call()->_flags.check(Kflags::IS_OUTGOING)) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "unable to do a user transfer, channel disconnected")); + return false; + } + + } + while(timeout); + + ScopedPvtLock lock3(_pvt); + + _pvt->command(KHOMP_LOG, CM_DIAL_DTMF, dest.c_str()); + + _pvt->call()->_flags.set(Kflags::WAIT_SEND_DTMF); + + lock3.unlock(); + + timeout = 300; // 300 * 200000 = 60s + + do + { + usleep(200000); + timeout--; + + ScopedPvtLock lock4(_pvt); + + if(!_pvt->call()->_flags.check(Kflags::WAIT_SEND_DTMF)) + break; + } + while(timeout); + + } + catch (ScopedLockFailed & err) + { + LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() ); + return false; + } + + + DBG(FUNC, PVT_FMT(_pvt->target(), "r")); + return true; + } + + /* User transfer functions */ + bool doUserXferUnlocked() + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c (flashing channel!)")); + + bool ret = false; + + ret = _pvt->command(KHOMP_LOG, CM_FLASH); + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false")); + return ret; + } + + bool checkUserXferUnlocked(std::string digit) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_FLASH)")); + + + if (_call->_user_xfer_digits.empty()) + { + _call->_digits_buffer += digit; + DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)")); + return false; + } + + _call->_user_xfer_buffer += digit; + + /* temporary buffer */ + std::string tmp = _call->_user_xfer_buffer; + + unsigned int amount = tmp.size(); + + try + { + + if (amount == _call->_user_xfer_digits.size()) + { + if (tmp == _call->_user_xfer_digits) + { + bool ret = doUserXferUnlocked(); + + _call->_user_xfer_buffer.clear(); + _call->_digits_buffer.clear(); + + Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial); + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false")); + return ret; + } + + _call->_digits_buffer += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no xfer)")); + return false; + } + + if (tmp == _call->_user_xfer_digits.substr(0,amount)) + { + if (!(_call->_flags.check(Kflags::XFER_DIALING))) + { + _call->_flags.set(Kflags::XFER_DIALING); + _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL); + } + else + { + Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial); + } + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)")); + return true; + } + + } + catch (K3LAPI::invalid_device & err) + { + LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device); + } + + _call->_digits_buffer += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)")); + + return false; + + } + + static void userXferTimer(Board::KhompPvt * pvt) + { + DBG(FUNC, PVT_FMT(pvt->target(), "c")); + + T * call = static_cast(pvt->call()); + + try + { + ScopedPvtLock lock(pvt); + + if (!call->_user_xfer_buffer.empty()) + { + pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str()); + + /* clear the buffer that has been send */ + call->_user_xfer_buffer.clear(); + } + + call->_flags.clear(Kflags::XFER_DIALING); + } + catch (ScopedLockFailed & err) + { + LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() ); + return; + } + + DBG(FUNC, PVT_FMT(pvt->target(), "r")); + } + + bool _is_ok; + T * _call; + Board::KhompPvt * _pvt; + Board::ChanTimer::Index _idx_xfer_dial; +}; + +template +struct Transfer +{ + Transfer(Board::KhompPvt * pvt) : _pvt(pvt), _is_ok(false) {} + + bool clear() + { + if(!_is_ok) + { + _call = dynamic_cast(_pvt->call()); + + _is_ok = true; + + if(!_call) + { + DBG(FUNC, D("Error in cast")); + _is_ok = false; + } + } + + _call->_flags.clear(Kflags::XFER_DIALING); + _call->_flags.clear(Kflags::XFER_QSIG_DIALING); + + return true; + } + + bool userTransfer(switch_core_session_t * session, const char *data) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c")); + + std::string dest(""); + + bool opt_nowait = false; + + try + { + Strings::vector_type params; + + Strings::tokenize((const char *)data, params, "|,", 2); + + dest = params[0]; + + if (params.size() > 1) + { + opt_nowait = (params[1].find('n') != std::string::npos); + + // other options go here... + } + + ScopedPvtLock lock(_pvt); + + int timeout = 5; + + if(!_pvt->call()->_flags.check(Kflags::REALLY_CONNECTED) && !_pvt->loopWhileFlagTimed(Kflags::REALLY_CONNECTED, timeout, false)) + return false; + + DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!")); + + _pvt->command(KHOMP_LOG, CM_SS_TRANSFER, + STG(FMT("transferred_to=\"%s\" await_connect=\"%d\"") + % dest % (opt_nowait ? 0 : 1)).c_str()); + + } + catch (ScopedLockFailed & err) + { + LOG(ERROR, PVT_FMT(_pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() ); + return false; + } + + + DBG(FUNC, PVT_FMT(_pvt->target(), "r")); + return true; + } + + /* User transfer functions */ + bool doUserXferUnlocked(void) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c")); + + bool ret = false; + + if (_call->_flags.check(Kflags::XFER_QSIG_DIALING)) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "ss_transfer on channel!")); + + _call->_flags.clear(Kflags::XFER_DIALING); + _call->_flags.clear(Kflags::XFER_QSIG_DIALING); + + ret = _pvt->command(KHOMP_LOG, CM_SS_TRANSFER, + STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % _call->_qsig_number).c_str()); + } + else + { + DBG(FUNC, PVT_FMT(_pvt->target(), "starting to store digits for ss_transfer...")); + _call->_flags.set(Kflags::XFER_QSIG_DIALING); + + _xfer_thread = threadCreate(Transfer::userXferPlayback,(void*) _pvt); + _xfer_thread->start(); + + ret = true; + } + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (%s)") % (ret ? "true" : "false")); + return ret; + + } + + bool checkUserXferUnlocked(std::string digit) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "c (CM_SS_TRANSFER)")); + + + if (_call->_user_xfer_digits.empty()) + { + _call->_digits_buffer += digit; + DBG(FUNC, PVT_FMT(_pvt->target(), "r (disabled)")); + return false; + } + + _call->_user_xfer_buffer += digit; + + DBG(FUNC, PVT_FMT(_pvt->target(), "c digits=[%s] buffer=[%s]") % _call->_user_xfer_digits % _call->_user_xfer_buffer ); + + /* temporary buffer */ + std::string tmp = _call->_user_xfer_buffer; + + unsigned int amount = tmp.size(); + + try + { + + if (amount == _call->_user_xfer_digits.size()) + { + if (tmp == _call->_user_xfer_digits) + { + bool ret = doUserXferUnlocked(); + + _call->_user_xfer_buffer.clear(); + _call->_qsig_number.clear(); + _call->_digits_buffer.clear(); + + if(!_call->_flags.check(Kflags::XFER_QSIG_DIALING)) + { + Board::board(_pvt->target().device)->_timers.del(_idx_xfer_dial); + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (ret=%s, done xfer)") % (ret ? "true" : "false")); + } + else + { + Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (waiting digits for transfer)")); + } + return ret; + } + + if (_call->_flags.check(Kflags::XFER_QSIG_DIALING)) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp); + + _call->_qsig_number += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial); + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig transfer)")); + return true; + } + + _call->_digits_buffer += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, no qsig)")); + return false; + } + + if (tmp == _call->_user_xfer_digits.substr(0,amount)) + { + if (!(_call->_flags.check(Kflags::XFER_DIALING) || _call->_flags.check(Kflags::XFER_QSIG_DIALING))) + { + _call->_flags.set(Kflags::XFER_DIALING); + _idx_xfer_dial = Board::board(_pvt->target().device)->_timers.add(Opt::_transferdigittimeout, &userXferTimer, _pvt, TM_VAL_CALL); + } + else + { + Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial); + } + + DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, buffering)")); + return true; + } + + if (_call->_flags.check(Kflags::XFER_QSIG_DIALING)) + { + DBG(FUNC, PVT_FMT(_pvt->target(), "putting digits ('%s') on transfer-to number!") % tmp); + + _call->_qsig_number += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + + Board::board(_pvt->target().device)->_timers.restart(_idx_xfer_dial); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (true, qsig buffering)")); + return true; + } + + } + catch (K3LAPI::invalid_device & err) + { + LOG(ERROR, PVT_FMT(_pvt->target(), "Unable to get device: %d!") % err.device); + } + + _call->_digits_buffer += tmp[0]; + _call->_user_xfer_buffer.erase(0, 1); + DBG(FUNC, PVT_FMT(_pvt->target(), "r (false, buffering)")); + + return false; + } + + static void userXferTimer(Board::KhompPvt * pvt) + { + DBG(FUNC, PVT_FMT(pvt->target(), "c")); + + T * call = static_cast(pvt->call()); + + try + { + ScopedPvtLock lock(pvt); + + if (!call->_user_xfer_buffer.empty()) + { + pvt->command(KHOMP_LOG, CM_DIAL_DTMF, call->_user_xfer_buffer.c_str()); + + /* clear the buffer that has been send */ + call->_user_xfer_buffer.clear(); + } + + if (!call->_qsig_number.empty()) + { + pvt->command(KHOMP_LOG, CM_SS_TRANSFER, + STG(FMT("transferred_to=\"%s\" await_connect=\"1\"") % call->_qsig_number).c_str()); + + /* clear the buffer that has been send */ + call->_qsig_number.clear(); + } + + call->_flags.clear(Kflags::XFER_DIALING); + call->_flags.clear(Kflags::XFER_QSIG_DIALING); + } + catch (ScopedLockFailed & err) + { + LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() ); + return; + } + + DBG(FUNC, PVT_FMT(pvt->target(), "r")); + } + + static switch_status_t dtmfCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) + { + char sbuf[3]; + + if(!session) + { + DBG(FUNC,D("session is NULL")) + return SWITCH_STATUS_FALSE; + } + + switch_channel_t * chan = switch_core_session_get_channel(session); + + if(!chan) + { + DBG(FUNC,D("channel is NULL")) + return SWITCH_STATUS_FALSE; + } + + switch_core_session_t *peer_session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE)); + + if(!peer_session) + { + DBG(FUNC,D("session is NULL")) + return SWITCH_STATUS_FALSE; + } + + switch (itype) + { + case SWITCH_INPUT_TYPE_DTMF: + { + switch_dtmf_t *dtmf = (switch_dtmf_t *) input; + + Board::KhompPvt * tech_pvt = static_cast< Board::KhompPvt* >(switch_core_session_get_private(peer_session)); + if(!tech_pvt) + { + DBG(FUNC,D("Init: pvt is NULL")) + switch_core_session_rwunlock(peer_session); + return SWITCH_STATUS_FALSE; + } + + char s[] = { dtmf->digit, '\0' }; + tech_pvt->sendDtmf(s); + + break; + } + default: + break; + } + + switch_core_session_rwunlock(peer_session); + return SWITCH_STATUS_SUCCESS; + } + + + static int userXferPlayback(void * pvt_ptr) + { + /* get pointer... */ + Board::KhompPvt * pvt = static_cast < Board::KhompPvt * > (pvt_ptr); + + DBG(FUNC, PVT_FMT(pvt->target(), "c")); + + try + { + ScopedPvtLock lock(pvt); + + /* get the owner */ + switch_channel_t * chan = pvt->getFSChannel(); + + /* get other side of the bridge */ + switch_core_session_t * peer_session = NULL; + switch_core_session_get_partner(pvt->session(),&peer_session); + + if(!peer_session) + { + DBG(FUNC, PVT_FMT(pvt->target(), "r (session is null)")); + return NULL; + } + + switch_channel_t * peer = switch_core_session_get_channel(peer_session); + + /* put the channel in hold */ + //switch_core_session_t *session = switch_core_session_locate(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE)); + //switch_channel_t *chan_core = switch_core_session_get_channel(session); + + const char *stream; + + if (!(stream = switch_channel_get_variable(chan, SWITCH_HOLD_MUSIC_VARIABLE))) + { + stream = "silence"; + } + + DBG(FUNC, PVT_FMT(pvt->target(), "stream=%s") % stream); + + if (stream && strcasecmp(stream, "silence")) + { + /* Freeswitch not get/put frames */ + //switch_channel_set_flag(channel, CF_HOLD); + switch_ivr_broadcast(switch_core_session_get_uuid(pvt->session()),stream, SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY); + } + + switch_core_session_rwunlock(peer_session); + lock.unlock(); + + /* kickstart my heart */ + switch_input_args_t args = {0}; + args.input_callback = dtmfCallback; + + /* wait while xfering... */ + while (true) + { + switch_ivr_collect_digits_callback(peer_session,&args,1000,0); + ScopedPvtLock lock2(pvt); + + if (!pvt->call()->_flags.check(Kflags::XFER_QSIG_DIALING)) + { + break; + } + + lock2.unlock(); + } + + //switch_channel_clear_flag(channel, CF_HOLD); + + switch_channel_stop_broadcast(chan); + switch_channel_wait_for_flag(chan, CF_BROADCAST, SWITCH_FALSE, 5000, NULL); + switch_core_session_rwunlock(pvt->session()); + switch_core_session_rwunlock(peer_session); + + //switch_ivr_unhold_uuid(switch_channel_get_variable(chan,SWITCH_SIGNAL_BOND_VARIABLE)); + } + catch (ScopedLockFailed & err) + { + LOG(ERROR, PVT_FMT(pvt->target(),"r (unable to lock %s!)") % err._msg.c_str() ); + return NULL; + } + catch (Board::KhompPvt::InvalidSwitchChannel & err) + { + LOG(ERROR, PVT_FMT(pvt->target(), "r (%s)") % err._msg.c_str() ); + return NULL; + } + + DBG(FUNC, PVT_FMT(pvt->target(), "r")); + + return NULL; + } + + bool _is_ok; + T * _call; + Board::KhompPvt * _pvt; + Thread * _xfer_thread; + Board::ChanTimer::Index _idx_xfer_dial; +}; + +/*************************** SMS **********************************************/ +struct SMS : public Application +{ + typedef std::list< switch_core_session_t *> OwnersList; + + struct SMSStatistics : public Statistics + { + SMSStatistics(): + _sms_number_incoming(0), + _sms_number_outgoing(0), + _sms_number_confirm(0), + _sms_number_broadcast(0) {}; + + void incrementIncoming() + { + _sms_number_incoming++; + } + + void incrementOutgoing() + { + _sms_number_outgoing++; + } + + void incrementConfirm() + { + _sms_number_confirm++; + } + + void incrementBroadcast() + { + _sms_number_broadcast++; + } + + std::string getDetailed() + { + std::string tmpBuffer; + + tmpBuffer.append(STG(FMT("Number of incoming SMS: \t%d\n") % _sms_number_incoming)); + tmpBuffer.append(STG(FMT("Number of outgoing SMS: \t%d\n") % _sms_number_outgoing)); + tmpBuffer.append(STG(FMT("Number of broadcast SMS: \t%d\n") % _sms_number_broadcast)); + tmpBuffer.append(STG(FMT("Number of confirm SMS: \t%d\n") % _sms_number_confirm)); + + return tmpBuffer; + } + + void clear() + { + _sms_number_incoming = 0; + _sms_number_outgoing = 0; + _sms_number_confirm = 0; + _sms_number_broadcast = 0; + } + + unsigned int _sms_number_incoming; + unsigned int _sms_number_outgoing; + unsigned int _sms_number_confirm; + unsigned int _sms_number_broadcast; + }; + + SMS(Board::KhompPvt * pvt) : + Application(pvt), + _thread(NULL), + _shutdown(false), + _can_receive(false), + _can_send(false), + _result(0), + _mutex(Globals::module_pool), + _cond(Globals::module_pool), + _buffer(8) + { + _cond.reset(); + _app_statistics = new SMSStatistics(); + } + + ~SMS() + { + stop(); + delete _app_statistics; + } + + struct ReceiveData + { + ReceiveData() {}; + + ReceiveData(const ReceiveData & o) + { + _type = o._type; + _from = o._from; + _date = o._date; + _size = o._size; + _coding = o._coding; + _serial = o._serial; + _id = o._id; + _page = o._page; + _pages = o._pages; + _sc_date = o._sc_date; + _status = o._status; + _body = o._body; + }; + + void clear(void) + { + /* reset data stuff */ + _type.clear(); + _from.clear(); + _date.clear(); + _size.clear(); + _coding.clear(); + _serial.clear(); + _id.clear(); + _page.clear(); + _pages.clear(); + _sc_date.clear(); + _status.clear(); + _body.clear(); + }; + + std::string _type; + std::string _from; + std::string _date; + std::string _size; + std::string _coding; + std::string _serial; + std::string _id; + std::string _page; + std::string _pages; + std::string _sc_date; + std::string _status; + std::string _body; + }; + + struct SendData + { + SendData(): _conf(false) {}; + + SendData(const SendData & o) + { + _dest = o._dest; + _body = o._body; + _conf = o._conf; + }; + + void clear(void) + { + /* reset data stuff */ + _dest.clear(); + _body.clear(); + _conf = false; + }; + + std::string _dest; + std::string _body; + bool _conf; + }; + + struct Request + { + /* "empty" constructor */ + Request(): _finished(NULL), _cause(NULL) {}; + + /* "real" constructor */ + Request(SendData & send_sms, volatile bool * finished, volatile KGsmCallCause * cause) + : _send_sms(send_sms), _finished(finished), _cause(cause) + {}; + + SendData _send_sms; + + volatile bool * _finished; + volatile KGsmCallCause * _cause; + }; + + bool start() + { + _pvt->call()->_flags.clear(Kflags::SMS_DOING_UPLOAD); + + _thread = threadCreate(&smsThread, (void*) this); + _thread->start(); + } + + bool stop() + { + if(!_thread) + { + return false; + } + + _shutdown = true; + _cond.signal(); + _thread->join(); + delete _thread; + _thread = NULL; + + return true; + } + + bool justAlloc(unsigned int count = 0); + bool justStart(); + + bool sendSMS(switch_core_session_t * session, const char *data); + + + bool onNewSMS(K3L_EVENT *e); + bool onSMSInfo(K3L_EVENT *e); + bool onSMSData(K3L_EVENT *e); + bool onSMSSendResult(K3L_EVENT *e); + + Thread *_thread; + bool _shutdown; + bool _can_receive; + bool _can_send; + ReceiveData _got_sms; + SendData _send_sms; + int _result; + SavedCondition _cond; + Globals::Mutex _mutex; + Ringbuffer < SMS::Request > _buffer; + OwnersList _owners; + + static int smsThread(void * sms_ptr); +}; + +/******************************************************************************/ + + +#endif /* _APPLICATIONS_H_ */ + diff --git a/src/mod/endpoints/mod_khomp/include/cli.h b/src/mod/endpoints/mod_khomp/include/cli.h new file mode 100644 index 0000000000..214e2aa2d5 --- /dev/null +++ b/src/mod/endpoints/mod_khomp/include/cli.h @@ -0,0 +1,1143 @@ +/******************************************************************************* + + KHOMP generic endpoint/channel library. + Copyright (C) 2007-2010 Khomp Ind. & Com. + + The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + "GNU Lesser General Public License 2.1" license (the “LGPL" License), in which + case the provisions of "LGPL License" are applicable instead of those above. + + If you wish to allow use of your version of this file only under the terms of + the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use your + version of this file under either the MPL or the LGPL License. + + The LGPL header follows below: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*******************************************************************************/ + +#ifndef _CLI_H_ +#define _CLI_H_ + +#include "globals.h" +#include "logger.h" + +struct Command +{ + /* print in client the usage */ + void printUsage(switch_stream_handle_t *stream) + { + if(stream) + { + printBrief(stream); + K::Logger::Logg2(C_CLI,stream, +"------------------------------ Description --------------------------------"); + K::Logger::Logg2(C_CLI,stream, +"---------------------------------------------------------------------------"); + K::Logger::Logg2(C_CLI,stream,(char*) usage.c_str()); + K::Logger::Logg2(C_CLI,stream, +"---------------------------------------------------------------------------"); + } + else + { + LOG(ERROR,FMT("Invalid stream for commmand: %s") % complete_name); + } + } + + /* print in client the brief */ + void printBrief(switch_stream_handle_t *stream) + { + if(stream) + { + K::Logger::Logg2(C_CLI,stream, +"---------------------------------------------------------------------------"); + K::Logger::Logg2(C_CLI,stream, +"-------------------------------- Brief ------------------------------------"); + K::Logger::Logg2(C_CLI,stream, +"---------------------------------------------------------------------------"); + K::Logger::Logg2(C_CLI,stream,(char*) brief.c_str()); + K::Logger::Logg2(C_CLI,stream, +"---------------------------------------------------------------------------"); + } + else + { + LOG(ERROR,FMT("Invalid stream for commmand: %s") % complete_name); + } + } + + /* pure virtual */ + virtual bool execute(int argc, char *argv[]) = 0; + + std::string complete_name; /* specify the command in console */ + std::vector options; /* extra options for command */ + std::string brief; /* brief of the command, a path */ + std::string usage; /* usage of the command, a help */ +}; + +struct Cli +{ + /* Useful definitions --------------------------------------------------- */ + typedef switch_status_t (APIFunc)(const char*, switch_core_session_t*, switch_stream_handle_t*); + typedef std::vector Commands; + + /* register our commands, but you must create the command function */ + static void registerCommands(APIFunc func,switch_loadable_module_interface_t **mod_int); + + /* delete the commands */ + static void unregisterCommands() + { + switch_console_set_complete("del khomp"); + } + + /* stream is very useful */ + static void setStream(switch_stream_handle_t *s) + { + if(!s) + { + LOG(ERROR,"Invalid stream passed"); + return; + } + + stream = s; + } + + /* gets the khomp usage */ + static void printKhompUsage() + { + if(stream) + { + K::Logger::Logg2(C_CLI,stream,(char*) _khomp_usage.c_str()); + } + else + { + LOG(ERROR,"Invalid stream for command: printKhompUsage"); + } + } + + /* is responsible for parse and execute all commands */ + static bool parseCommands(int argc, char *argv[]); + + /* The Commands --------------------------------------------------------- */ + + /* khomp summary */ + static struct _KhompSummary : public Command + { + _KhompSummary(bool on_cli_term = true): + _on_cli_term(on_cli_term) + { + complete_name = "summary"; + + options.push_back("verbose"); + options.push_back("concise"); + + brief = "Print system info."; + usage = \ +"Prints detailed info about the system like API version and \n" \ +"boards characteristics like DSPs version.\n\n" \ +"Usage: khomp summary [concise]"; + + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + bool _on_cli_term; /* indicates if message is sent to fs_cli */ + } KhompSummary; + + /* khomp show calls */ + static struct _KhompShowCalls : public Command + { + _KhompShowCalls() + { + complete_name = "show calls"; + brief = \ +"Show each Khomp channel which have more than one call state associated."; + + usage = \ +"Show each Khomp channel which have more than one call state associated.\n\n" \ +"Usage: khomp show calls [ []]"; + + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + + /* support function for _KhompShowCalls */ + void showCalls(unsigned int device, unsigned int object, std::string &buffer); + } KhompShowCalls; + + /* khomp channels disconnect */ + static struct _KhompChannelsDisconnect : public Command + { + _KhompChannelsDisconnect() + { + complete_name = "channels disconnect"; + brief = "Disconnect a(ll) channel(s)."; + usage = \ +"Disconnects channels in boards, or specific board/channel if parameter \n" \ +"is supplied.\n\n" \ +"Usage: khomp channels disconnect {all | all | }\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tchannel -- Number of the channel (start from 0).\n" \ +"e.g. khomp channels disconnect all - Disconnect all channels of all boards.\n"\ +"e.g. khomp channels disconnect 0 5 - Disconnect channel 5 of board 0."; + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + + /* support function for _KhompChannelsDisconnect */ + bool forceDisconnect(unsigned int device, unsigned int channel); + } KhompChannelsDisconnect; + + /* khomp channels unblock */ + static struct _KhompChannelsUnblock : public Command + { + _KhompChannelsUnblock() + { + complete_name = "channels unblock"; + brief = "Unblock a(ll) channel(s)."; + + usage = \ +"The board will request to the PBX or network where it is connected to \n" \ +"unblock the channel if its blocked.\n\n" \ +"Usage: khomp channels unblock {all | all | }\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tchannel -- Number of the channel (start from 0).\n" \ +"e.g. khomp channels unblock all - Unblock all channels of all boards.\n" \ +"e.g. khomp channels unblock 0 all - Unblock all channels of board 0.\n" \ +"e.g. khomp channels unblock 1 20 - Unblock channel 20 of board 1."; + + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + } KhompChannelsUnblock; + + /* khomp show statistics */ + static struct _KhompShowStatistics : public Command + { + _KhompShowStatistics() + { + complete_name = "show statistics"; + + options.push_back("verbose"); + options.push_back("detailed"); + + brief = "Shows statistics of the channels."; + + usage = \ +"Shows statistics of the channels, like number of calls incoming \n" \ +"and outgoing, status, status time.\n\n" \ +"Usage: khomp show statistics [{verbose [ []]} | \n" \ +" {detailed }]\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tchannel -- Number of the channel (start from 0).\n" \ +"e.g. khomp channels statistics - Shows general statistics \n" \ +" of all boards.\n" \ +"e.g. khomp channels statistics 0 - Shows general statistics \n" \ +" of board 0.\n" \ +"e.g. khomp channels statistics verbose - Shows general statistics \n" \ +" of all boards.\n" \ +"e.g. khomp channels statistics verbose 0 - Shows general statistics \n" \ +" of board 0.\n" \ +"e.g. khomp channels statistics detailed 0 2 - Shows detailed statistics \n" \ +" of channel 2 on board 0."; + + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + + /* support functions */ + void cliStatistics(unsigned int device); + void cliDetailedStatistics(unsigned int device, unsigned int channel); + + } KhompShowStatistics; + + /* khomp show channels */ + static struct _KhompShowChannels: public Command + { + _KhompShowChannels() + { + complete_name = "show channels"; + + options.push_back("verbose"); + options.push_back("concise"); + + brief = "Show all channels status."; + usage = \ +"List the status of each channel, both on asterisk point of view and on \n" \ +"khomp API point of view.\n\n" \ +"Usage: \n" \ +"khomp show channels [{ []} | \n" \ + "{{concise|verbose} [ []]}]\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"e.g. khomp show channels - List status of all channels of all boards.\n" \ +"e.g. khomp show channels concise 0 - List status of all channels of \n" \ +" board 0 in a concise way."; + + _commands.push_back(this); + }; + + /* support function for _KhompShowChannels */ + void showChannel(unsigned int device, bool concise, unsigned int channel); + void showChannels(unsigned int device, bool concise); + + bool execute(int argc, char *argv[]); + } KhompShowChannels; + + /* khomp show links */ + static struct _KhompShowLinks: public Command + { + _KhompShowLinks() + { + complete_name = "show links"; + + options.push_back("verbose"); + options.push_back("concise"); + options.push_back("errors"); + options.push_back("errors verbose"); + options.push_back("errors concise"); + + brief = "Show E1 link(s) status/errors counters in a concise \n" \ + "way or not."; + + usage = \ +"Prints information about the signaling, syncronization and general \n" \ +"status/the error counters of each link on the board. It prints in \n" \ +"a concise way for parsing facilities.\n\n" \ +"Usage: \n" \ +"khomp show links [[errors] [{} | {{concise|verbose} []}]]\n" \ +"e.g. khomp show links - Show all links of all boards.\n" \ +"e.g. khomp show links errors - Show error counters of all links of \n" \ +" all boards.\n" \ +"e.g. khomp show links errors 0 - Show error counters of all links of \n" \ +" board 0."; + + _commands.push_back(this); + }; + + /* support function for _KhompShowLinks */ + void showLinks(unsigned int device, bool concise); + void showErrors(unsigned int device, bool concise); + + bool execute(int argc, char *argv[]); + } KhompShowLinks; + + /* khomp clear links */ + static struct _KhompClearLinks: public Command + { + _KhompClearLinks() + { + complete_name = "clear links"; + + brief = "Clear the error counters of the links."; + + usage = \ +"Clear the error counters of the links.\n\n" \ +"Usage: khomp clear links [ []]\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tlink -- Number of the link (start from 0).\n" \ +"e.g. khomp clear links 0 -- Clear error counters of all links of board 0."; + + _commands.push_back(this); + }; + + /* support function for _KhompClearLinks */ + void clearLink(unsigned int device, unsigned int link); + + bool execute(int argc, char *argv[]); + } KhompClearLinks; + + /* khomp clear statistics */ + static struct _KhompClearStatistics: public Command + { + _KhompClearStatistics() + { + complete_name = "clear statistics"; + + brief = "Clear statistics of the channels."; + + usage = \ +"Clear statistics of the channels, like number of calls incoming \n" \ +"and outgoing, status, status time.\n\n" \ +"Usage: khomp clear statistics [ []]\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tchannel -- Number of the channel (start from 0).\n" \ +"e.g. khomp clear statistics 0 -- Clear statistics of board 0."; + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + } KhompClearStatistics; + + + /* khomp reset links */ + static struct _KhompResetLinks: public Command + { + _KhompResetLinks() + { + complete_name = "reset links"; + + brief = "Reset the specified link."; + + usage = \ +"Reset the specified link.\n\n" \ +"Usage: khomp reset links [ []]\n" \ +"\tboard -- Number of the board (start from 0).\n" \ +"\tlink -- Number of the link (start from 0).\n" \ +"e.g. khomp reset links 0 1 -- Reset link 1 of board 0."; + + _commands.push_back(this); + }; + + /* support function for _KhompResetLinks */ + void resetLink(unsigned int device, unsigned int link); + + bool execute(int argc, char *argv[]); + } KhompResetLinks; + + /* khomp sms */ + static struct _KhompSMS : public Command + { + _KhompSMS() + { + complete_name = "sms"; + brief = "Send an SMS message using a Khomp KGSM board."; + + usage = \ +"Send an SMS message using a Khomp KGSM board.\n\n" \ +"Usage: khomp sms \n" \ +"\tdevice -- Device to use (same string used in Dial for \n" \ +"\t channel allocation).\n" \ +"\tdestination -- Phone number of the destination.\n" \ +"\tmessage -- Message to send.\n" \ +"e.g. khomp sms b0 99887766 Oi, tudo bem?"; + + _commands.push_back(this); + }; + + bool execute(int argc, char *argv[]); + } KhompSMS; + + /* khomp log console */ + static struct _KhompLogConsole : public Command + { + _KhompLogConsole() + { + complete_name = "log console"; + + options.push_back("errors"); + options.push_back("warnings"); + options.push_back("messages"); + options.push_back("events"); + options.push_back("commands"); + options.push_back("audio"); + options.push_back("modem"); + options.push_back("link"); + options.push_back("cas"); + options.push_back("standard"); + options.push_back("all"); + options.push_back("no"); + options.push_back("just"); + + brief = "Enables/disables showing console messages for the channel."; + usage = \ +"Enables/disables showing channel messages, where can be:\n" \ +"\terrors -- Error messages, when something goes really \n" \ +"\t wrong. Enabled by default.\n" \ +"\twarnings -- Warnings, used when something might not be \n" \ +"\t going as expected. Enabled by default.\n" \ +"\tmessages -- Generic messages, used to indicate some \n" \ +"\t information. Enabled by default.\n" \ +"\tevents -- Show received K3L events as console \n" \ +"\t messages. Disabled by default.\n" \ +"\tcommands -- Show sent K3L commands as console \n" \ +"\t messages. Disabled by default.\n" \ +"\taudio -- Enable messages for K3L audio events. \n" \ +"\t Disabled by default (very verbose!).\n" \ +"\tmodem -- Enable messages for data received from \n" \ +"\t KGSM modems. Disabled by default.\n" \ +"\tlink -- Enable logging of link status changes. \n" \ +"\t Enabled by default.\n" \ +"\tcas -- Enable logging of MFCs and line state \n" \ +"\t changes in KPR board. Disabled by default.\n" \ +"\tstandard -- Special identifier, enable default \n" \ +"\t console messages.\n" \ +"\tall -- Special identifier, enable ALL console \n" \ +"\t messages (should not be used naively).\n\n" \ +"Usage: khomp log console \n" \ +"e.g. khomp log console standard"; + + _commands.push_back(this); + } + + bool execute(int argc, char *argv[]); + } KhompLogConsole; + + /* khomp log disk */ + static struct _KhompLogDisk : public Command + { + _KhompLogDisk() + { + complete_name = "log disk"; + + options.push_back("errors"); + options.push_back("warnings"); + options.push_back("messages"); + options.push_back("events"); + options.push_back("commands"); + options.push_back("audio"); + options.push_back("modem"); + options.push_back("link"); + options.push_back("cas"); + options.push_back("functions"); + options.push_back("threads"); + options.push_back("locks"); + options.push_back("streams"); + options.push_back("standard"); + options.push_back("debugging"); + options.push_back("all"); + options.push_back("no"); + options.push_back("just"); + + brief = "Enables/disables logging to file messages for the channel."; + usage = \ +"Enables/disables the logging of channel messages to disk, where \n" \ +"can be:\n" \ +"\terrors -- Error messages, when something goes really \n" \ +"\t wrong. Enabled by default.\n" \ +"\twarnings -- Warnings, used when something might not be \n" \ +"\t going as expected. Enabled by default.\n" \ +"\tmessages -- Generic messages, used to indicate some \n" \ +"\t information. Enabled by default.\n" \ +"\tevents -- Record received K3L events as log messages. \n" \ +"\t Disabled by default.\n" \ +"\tcommands -- Record sent K3L commands as log messages. \n" \ +"\t Disabled by default.\n" \ +"\taudio -- Enable messages for K3L audio events. \n" \ +"\t Disabled by default (very verbose!).\n" \ +"\tmodem -- Enable messages for data received from \n" \ +"\t KGSM modems. Disabled by default.\n" \ +"\tlink -- Enable logging of link status changes. \n" \ +"\t Enabled by default.\n" \ +"\tcas -- Enable logging of MFCs and line state \n" \ +"\t changes in KPR board. Disabled by default.\n" \ +"\tfunctions -- Enable debugging for functions. Disabled \n" \ +"\t by default (should not be used naively!).\n" \ +"\tthreads -- Enable debugging for threads. Disabled by \n" \ +"\t default (should not be used naively!).\n" \ +"\tlocks -- Enable debugging for locks. Disabled by \n" \ +"\t default (should not be used naively!).\n" \ +"\tstreams -- Enable debugging for streams. Disabled by \n" \ +"\t default (should not be used naively!).\n" \ +"\tstandard -- Special identifier, enable default messages.\n" \ +"\tdebugging -- Special identifier, enable debugging messages \n" \ +"\t (should not be used naively).\n" \ +"\tall -- Special identifier, enable ALL disk \n" \ +"\t messages (DO NOT USE THIS!).\n\n" \ +"Usage: khomp log disk \n" \ +"e.g. khomp log disk "; + + _commands.push_back(this); + } + + bool execute(int argc, char *argv[]); + } KhompLogDisk; + + /* khomp log trace k3l */ + static struct _KhompLogTraceK3L : public Command + { + _KhompLogTraceK3L() + { + complete_name = "log trace k3l"; + + options.push_back("on"); + options.push_back("off"); + + brief = "Set K3L tracing (debug) option."; + + usage = \ +"Sets the low-level log for K3L API. Should not be set for long time \n" \ +"periods.\n\n" \ +"Usage: khomp log trace k3l {on|off}\n" \ +"e.g. khomp log trace k3l on"; + + _commands.push_back(this); + } + + bool execute(int argc, char *argv[]); + } KhompLogTraceK3L; + + /* khomp log trace ISDN */ + static struct _KhompLogTraceISDN : public Command + { + _KhompLogTraceISDN() + { + complete_name = "log trace isdn"; + + options.push_back("q931"); + options.push_back("lapd"); + options.push_back("system"); + options.push_back("off"); + + brief = "Set ISDN signaling trace."; + + usage = \ +"Sets the low-level log for ISDN signalling. Should not be set for \n" \ +"long time periods.\n\n" \ +"Usage: khomp log trace isdn [,[,..]]\n" \ +"\twhat -- \"q931\", \"lapd\", \"system\" or \"off\" \n" \ +"\t (comma-separated values).\n" \ +"e.g. khomp log trace isdn q931,system"; + + _commands.push_back(this); + } + + bool execute(int argc, char *argv[]); + } KhompLogTraceISDN; + + /* khomp log trace R2 */ + static struct _KhompLogTraceR2 : public Command + { + _KhompLogTraceR2() + { + complete_name = "log trace r2"; + + options.push_back("on"); + options.push_back("off"); + + brief = "Set R2 signaling trace."; + + usage = \ +"Sets the low-level log monitor for R2 digital signalling. Should not \n" \ +"be set for long time periods.\n\n" \ +"Usage: khomp log trace r2 {on|off}\n" \ +"e.g. khomp log trace r2 on"; + + _commands.push_back(this); + } + + bool execute(int argc, char *argv[]); + } KhompLogTraceR2; + + /* khomp get */ + static struct _KhompGet : public Command + { + _KhompGet() + { + complete_name = "get"; + + options.push_back("echo-canceller"); + options.push_back("out-of-band-dtmfs"); + options.push_back("auto-fax-adjustment"); + options.push_back("pulse-forwarding"); + options.push_back("r2-strict-behaviour"); + options.push_back("r2-preconnect-wait"); + options.push_back("native-bridge"); + options.push_back("suppression-delay"); + options.push_back("context-fxo"); + options.push_back("context-fxo-alt"); + options.push_back("context-fxs"); + options.push_back("context-fxs-alt"); + options.push_back("context-gsm-call"); + options.push_back("context-gsm-call-alt"); + options.push_back("context-gsm-sms"); + options.push_back("context-digital"); + options.push_back("output-volume"); + options.push_back("input-volume"); + + brief = "Get configuration options in the Khomp channel."; + + usage = \ +"Usage: khomp get