Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
3b36e990
提交
3b36e990
authored
10月 02, 2013
作者:
Nathan Neulinger
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
FS-5599 implement mod_format_cdr
上级
54ed3532
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
1547 行增加
和
0 行删除
+1547
-0
Makefile
src/mod/event_handlers/mod_format_cdr/Makefile
+1
-0
format_cdr.conf.xml
.../mod_format_cdr/conf/autoload_configs/format_cdr.conf.xml
+88
-0
mod_format_cdr.2008.vcproj
.../event_handlers/mod_format_cdr/mod_format_cdr.2008.vcproj
+289
-0
mod_format_cdr.2010.vcxproj
...event_handlers/mod_format_cdr/mod_format_cdr.2010.vcxproj
+149
-0
mod_format_cdr.2012.vcxproj
...event_handlers/mod_format_cdr/mod_format_cdr.2012.vcxproj
+149
-0
mod_format_cdr.c
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.c
+811
-0
mod_format_cdr.vcproj
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.vcproj
+60
-0
没有找到文件。
src/mod/event_handlers/mod_format_cdr/Makefile
0 → 100644
浏览文件 @
3b36e990
include
../../../../build/modmake.rules
src/mod/event_handlers/mod_format_cdr/conf/autoload_configs/format_cdr.conf.xml
0 → 100644
浏览文件 @
3b36e990
<configuration
name=
"format_cdr.conf"
description=
"Multi Format CDR CURL logger"
>
<!-- You can have multiple profiles, to allow logging to both json and cdr simultaneously, or to
different paths or servers with different settings, just be sure to use different name for
each profile. -->
<profiles>
<profile
name=
"default"
>
<settings>
<!-- the format of data to send, defaults to xml -->
<!-- <param name="format" value="json|xml"/> -->
<param
name=
"format"
value=
"xml"
/>
<!-- the url to post to if blank web posting is disabled -->
<!-- <param name="url" value="http://localhost/cdr_curl/post.php"/> -->
<!-- optional: credentials to send to web server -->
<!-- <param name="cred" value="user:pass"/> -->
<!-- the total number of retries (not counting the first 'try') to post to webserver incase of failure -->
<!-- <param name="retries" value="2"/> -->
<!-- delay between retries in seconds, default is 5 seconds -->
<!-- <param name="delay" value="1"/> -->
<!-- Log via http and on disk, default is false -->
<!-- <param name="log-http-and-disk" value="true"/> -->
<!-- optional: if not present we do not log every record to disk -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank value will default to ${prefix}/logs/format_cdr -->
<param
name=
"log-dir"
value=
""
/>
<!-- optional: if not present we do log the b leg -->
<!-- true or false if we should create a cdr for the b leg of a call-->
<param
name=
"log-b-leg"
value=
"false"
/>
<!-- optional: if not present, all filenames are the uuid of the call -->
<!-- true or false if a leg files are prefixed "a_" -->
<param
name=
"prefix-a-leg"
value=
"true"
/>
<!-- encode the post data may be 'true' for url encoding, 'false' for no encoding, 'base64' for base64 encoding or 'textxml' for text/xml -->
<param
name=
"encode"
value=
"true"
/>
<!-- optional: set to true to disable Expect: 100-continue lighttpd requires this setting -->
<!--<param name="disable-100-continue" value="true"/>-->
<!-- optional: full path to the error log dir for failed web posts if not specified its the same as log-dir -->
<!-- either an absolute path, a relative path assuming ${prefix}/logs or a blank or omitted value will default to ${prefix}/logs/format_cdr -->
<!-- <param name="err-log-dir" value="/tmp"/> -->
<!-- which auhtentification scheme to use. Supported values are: basic, digest, NTLM, GSS-NEGOTIATE or "any" for automatic detection -->
<!--<param name="auth-scheme" value="basic"/>-->
<!-- optional: this will enable the CA root certificate check by libcurl to
verify that the certificate was issued by a major Certificate Authority.
note: default value is disabled. only enable if you want this! -->
<!--<param name="enable-cacert-check" value="true"/>-->
<!-- optional: verify that the server is actually the one listed in the cert -->
<!-- <param name="enable-ssl-verifyhost" value="true"/> -->
<!-- optional: these options can be used to specify custom SSL certificates
to use for HTTPS communications. Either use both options or neither.
Specify your public key with 'ssl-cert-path' and the private key with
'ssl-key-path'. If your private key has a password, specify it with
'ssl-key-password'. -->
<!-- <param name="ssl-cert-path" value="$${base_dir}/conf/certs/public_key.pem"/> -->
<!-- <param name="ssl-key-path" value="$${base_dir}/conf/certs/private_key.pem"/> -->
<!-- <param name="ssl-key-password" value="MyPrivateKeyPassword"/> -->
<!-- optional: use a custom CA certificate in PEM format to verify the peer
with. This is useful if you are acting as your own certificate authority.
note: only makes sense if used in combination with "enable-cacert-check." -->
<!-- <param name="ssl-cacert-file" value="$${base_dir}/conf/certs/cacert.pem"/> -->
<!-- optional: specify the SSL version to force HTTPS to use. Valid options are
"SSLv3" and "TLSv1". Otherwise libcurl will auto-negotiate the version. -->
<!-- <param name="ssl-version" value="TLSv1"/> -->
<!-- optional: enables cookies and stores them in the specified file. -->
<!-- <param name="cookie-file" value="/tmp/cookie-mod_format_cdr_curl.txt"/> -->
<!-- Whether to URL encode the individual JSON values. Defaults to true, set to false for standard JSON. -->
<param
name=
"encode-values"
value=
"true"
/>
</settings>
</profile>
</profiles>
</configuration>
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.2008.vcproj
0 → 100644
浏览文件 @
3b36e990
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType=
"Visual C++"
Version=
"9.00"
Name=
"mod_format_cdr"
ProjectGUID=
"{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}"
RootNamespace=
"mod_format_cdr"
Keyword=
"Win32Proj"
TargetFrameworkVersion=
"131072"
>
<Platforms>
<Platform
Name=
"Win32"
/>
<Platform
Name=
"x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name=
"Debug|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Debug|x64"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
TargetEnvironment=
"3"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
OutputFile=
"$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
TargetMachine=
"17"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Release|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
AdditionalLibraryDirectories=
""
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name=
"Release|x64"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCPreBuildEventTool"
/>
<Tool
Name=
"VCCustomBuildTool"
/>
<Tool
Name=
"VCXMLDataGeneratorTool"
/>
<Tool
Name=
"VCWebServiceProxyGeneratorTool"
/>
<Tool
Name=
"VCMIDLTool"
TargetEnvironment=
"3"
/>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCManagedResourceCompilerTool"
/>
<Tool
Name=
"VCResourceCompilerTool"
/>
<Tool
Name=
"VCPreLinkEventTool"
/>
<Tool
Name=
"VCLinkerTool"
OutputFile=
"$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"
AdditionalLibraryDirectories=
""
RandomizedBaseAddress=
"1"
DataExecutionPrevention=
"0"
TargetMachine=
"17"
/>
<Tool
Name=
"VCALinkTool"
/>
<Tool
Name=
"VCManifestTool"
/>
<Tool
Name=
"VCXDCMakeTool"
/>
<Tool
Name=
"VCBscMakeTool"
/>
<Tool
Name=
"VCFxCopTool"
/>
<Tool
Name=
"VCAppVerifierTool"
/>
<Tool
Name=
"VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=
".\mod_format_cdr.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.2010.vcxproj
0 → 100644
浏览文件 @
3b36e990
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets=
"Build"
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup
Label=
"ProjectConfigurations"
>
<ProjectConfiguration
Include=
"Debug|Win32"
>
<Configuration>
Debug
</Configuration>
<Platform>
Win32
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Debug|x64"
>
<Configuration>
Debug
</Configuration>
<Platform>
x64
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Release|Win32"
>
<Configuration>
Release
</Configuration>
<Platform>
Win32
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Release|x64"
>
<Configuration>
Release
</Configuration>
<Platform>
x64
</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup
Label=
"Globals"
>
<ProjectName>
mod_format_cdr
</ProjectName>
<ProjectGuid>
{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}
</ProjectGuid>
<RootNamespace>
mod_format_cdr
</RootNamespace>
<Keyword>
Win32Proj
</Keyword>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.Default.props"
/>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.props"
/>
<ImportGroup
Label=
"ExtensionSettings"
>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_release.props"
/>
<Import
Project=
"..\..\..\..\w32\curl.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_debug.props"
/>
<Import
Project=
"..\..\..\..\w32\curl.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_release.props"
/>
<Import
Project=
"..\..\..\..\w32\curl.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_debug.props"
/>
<Import
Project=
"..\..\..\..\w32\curl.props"
/>
</ImportGroup>
<PropertyGroup
Label=
"UserMacros"
/>
<PropertyGroup>
<_ProjectFileVersion>
10.0.30319.1
</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile
Include=
"mod_format_cdr.c"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference
Include=
"..\..\..\..\libs\win32\apr\libapr.2010.vcxproj"
>
<Project>
{f6c55d93-b927-4483-bb69-15aef3dd2dff}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference
Include=
"..\..\..\..\libs\win32\curl\curllib.2010.vcxproj"
>
<Project>
{87ee9da4-de1e-4448-8324-183c98dca588}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference
Include=
"..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj"
>
<Project>
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.targets"
/>
<ImportGroup
Label=
"ExtensionTargets"
>
</ImportGroup>
</Project>
\ No newline at end of file
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.2012.vcxproj
0 → 100644
浏览文件 @
3b36e990
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets=
"Build"
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ItemGroup
Label=
"ProjectConfigurations"
>
<ProjectConfiguration
Include=
"Debug|Win32"
>
<Configuration>
Debug
</Configuration>
<Platform>
Win32
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Debug|x64"
>
<Configuration>
Debug
</Configuration>
<Platform>
x64
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Release|Win32"
>
<Configuration>
Release
</Configuration>
<Platform>
Win32
</Platform>
</ProjectConfiguration>
<ProjectConfiguration
Include=
"Release|x64"
>
<Configuration>
Release
</Configuration>
<Platform>
x64
</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup
Label=
"Globals"
>
<ProjectName>
mod_format_cdr
</ProjectName>
<ProjectGuid>
{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}
</ProjectGuid>
<RootNamespace>
mod_format_cdr
</RootNamespace>
<Keyword>
Win32Proj
</Keyword>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.Default.props"
/>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v110
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v110
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v110
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v110
</PlatformToolset>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.props"
/>
<ImportGroup
Label=
"ExtensionSettings"
>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_release.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_debug.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_release.props"
/>
</ImportGroup>
<ImportGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
Label=
"PropertySheets"
>
<Import
Project=
"$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition=
"exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label=
"LocalAppDataPlatform"
/>
<Import
Project=
"..\..\..\..\w32\module_debug.props"
/>
</ImportGroup>
<PropertyGroup
Label=
"UserMacros"
/>
<PropertyGroup>
<_ProjectFileVersion>
10.0.30319.1
</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>
%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile
Include=
"mod_format_cdr.c"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference
Include=
"..\..\..\..\libs\win32\apr\libapr.2012.vcxproj"
>
<Project>
{f6c55d93-b927-4483-bb69-15aef3dd2dff}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference
Include=
"..\..\..\..\libs\win32\curl\curllib.2012.vcxproj"
>
<Project>
{87ee9da4-de1e-4448-8324-183c98dca588}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference
Include=
"..\..\..\..\w32\Library\FreeSwitchCore.2012.vcxproj"
>
<Project>
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.targets"
/>
<ImportGroup
Label=
"ExtensionTargets"
>
</ImportGroup>
</Project>
\ No newline at end of file
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.c
0 → 100644
浏览文件 @
3b36e990
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
*
* 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 <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Brian West <brian@freeswitch.org>
* Bret McDanel <trixter AT 0xdecafbad.com>
* Justin Cassidy <xachenant@hotmail.com>
*
* mod_format_cdr.c -- XML CDR Module to files or curl
*
*/
#include <sys/stat.h>
#include <switch.h>
#include <switch_curl.h>
#define MAX_URLS 20
#define MAX_ERR_DIRS 20
#define ENCODING_NONE 0
#define ENCODING_DEFAULT 1
#define ENCODING_BASE64 2
#define ENCODING_TEXTXML 3
#define ENCODING_APPLJSON 4
static
struct
{
switch_hash_t
*
profile_hash
;
switch_memory_pool_t
*
pool
;
switch_event_node_t
*
node
;
switch_mutex_t
*
mutex
;
uint32_t
shutdown
;
}
globals
;
struct
cdr_profile
{
char
*
name
;
char
*
format
;
char
*
cred
;
char
*
urls
[
MAX_URLS
+
1
];
int
url_count
;
int
url_index
;
switch_thread_rwlock_t
*
log_path_lock
;
char
*
base_log_dir
;
char
*
base_err_log_dir
[
MAX_ERR_DIRS
];
char
*
log_dir
;
char
*
err_log_dir
[
MAX_ERR_DIRS
];
int
err_dir_count
;
uint32_t
delay
;
uint32_t
retries
;
uint32_t
enable_cacert_check
;
char
*
ssl_cert_file
;
char
*
ssl_key_file
;
char
*
ssl_key_password
;
char
*
ssl_version
;
char
*
ssl_cacert_file
;
uint32_t
enable_ssl_verifyhost
;
int
encode
;
int
encode_values
;
int
log_http_and_disk
;
int
log_b
;
int
prefix_a
;
int
disable100continue
;
int
rotate
;
int
auth_scheme
;
int
timeout
;
switch_memory_pool_t
*
pool
;
};
typedef
struct
cdr_profile
cdr_profile_t
;
SWITCH_MODULE_LOAD_FUNCTION
(
mod_format_cdr_load
);
SWITCH_MODULE_SHUTDOWN_FUNCTION
(
mod_format_cdr_shutdown
);
SWITCH_MODULE_DEFINITION
(
mod_format_cdr
,
mod_format_cdr_load
,
mod_format_cdr_shutdown
,
NULL
);
/* this function would have access to the HTML returned by the webserver, we don't need it
* and the default curl activity is to print to stdout, something not as desirable
* so we have a dummy function here
*/
static
size_t
httpCallBack
(
char
*
buffer
,
size_t
size
,
size_t
nitems
,
void
*
outstream
)
{
return
size
*
nitems
;
}
static
switch_status_t
set_format_cdr_log_dirs
(
cdr_profile_t
*
profile
)
{
switch_time_exp_t
tm
;
char
*
path
=
NULL
;
char
date
[
80
]
=
""
;
switch_size_t
retsize
;
switch_status_t
status
=
SWITCH_STATUS_SUCCESS
,
dir_status
;
int
err_dir_index
;
switch_time_exp_lt
(
&
tm
,
switch_micro_time_now
());
switch_strftime_nocheck
(
date
,
&
retsize
,
sizeof
(
date
),
"%Y-%m-%d-%H-%M-%S"
,
&
tm
);
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Rotating log file paths
\n
"
);
if
(
!
zstr
(
profile
->
base_log_dir
))
{
if
(
profile
->
rotate
)
{
if
((
path
=
switch_mprintf
(
"%s%s%s"
,
profile
->
base_log_dir
,
SWITCH_PATH_SEPARATOR
,
date
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Rotating log file path to %s
\n
"
,
path
);
dir_status
=
SWITCH_STATUS_SUCCESS
;
if
(
switch_directory_exists
(
path
,
profile
->
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
dir_status
=
switch_dir_make
(
path
,
SWITCH_FPROT_OS_DEFAULT
,
profile
->
pool
);
}
if
(
dir_status
==
SWITCH_STATUS_SUCCESS
)
{
switch_thread_rwlock_wrlock
(
profile
->
log_path_lock
);
switch_safe_free
(
profile
->
log_dir
);
profile
->
log_dir
=
path
;
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to create new mod_format_cdr log_dir path
\n
"
);
switch_safe_free
(
path
);
status
=
SWITCH_STATUS_FALSE
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to generate new mod_format_cdr log_dir path
\n
"
);
status
=
SWITCH_STATUS_FALSE
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Setting log file path to %s
\n
"
,
profile
->
base_log_dir
);
if
((
path
=
switch_safe_strdup
(
profile
->
base_log_dir
)))
{
switch_thread_rwlock_wrlock
(
profile
->
log_path_lock
);
switch_safe_free
(
profile
->
log_dir
);
switch_dir_make_recursive
(
path
,
SWITCH_DEFAULT_DIR_PERMS
,
profile
->
pool
);
profile
->
log_dir
=
path
;
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to set log_dir path
\n
"
);
status
=
SWITCH_STATUS_FALSE
;
}
}
}
for
(
err_dir_index
=
0
;
err_dir_index
<
profile
->
err_dir_count
;
err_dir_index
++
)
{
if
(
profile
->
rotate
)
{
if
((
path
=
switch_mprintf
(
"%s%s%s"
,
profile
->
base_err_log_dir
[
err_dir_index
],
SWITCH_PATH_SEPARATOR
,
date
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Rotating err log file path to %s
\n
"
,
path
);
dir_status
=
SWITCH_STATUS_SUCCESS
;
if
(
switch_directory_exists
(
path
,
profile
->
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
dir_status
=
switch_dir_make
(
path
,
SWITCH_FPROT_OS_DEFAULT
,
profile
->
pool
);
}
if
(
dir_status
==
SWITCH_STATUS_SUCCESS
)
{
switch_thread_rwlock_wrlock
(
profile
->
log_path_lock
);
switch_safe_free
(
profile
->
err_log_dir
[
err_dir_index
]);
profile
->
err_log_dir
[
err_dir_index
]
=
path
;
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to create new mod_format_cdr err_log_dir path
\n
"
);
switch_safe_free
(
path
);
status
=
SWITCH_STATUS_FALSE
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to generate new mod_format_cdr err_log_dir path
\n
"
);
status
=
SWITCH_STATUS_FALSE
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Setting err log file path to %s
\n
"
,
profile
->
base_err_log_dir
[
err_dir_index
]);
if
((
path
=
switch_safe_strdup
(
profile
->
base_err_log_dir
[
err_dir_index
])))
{
switch_thread_rwlock_wrlock
(
profile
->
log_path_lock
);
switch_safe_free
(
profile
->
err_log_dir
[
err_dir_index
]);
switch_dir_make_recursive
(
path
,
SWITCH_DEFAULT_DIR_PERMS
,
profile
->
pool
);
profile
->
err_log_dir
[
err_dir_index
]
=
path
;
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to set err_log_dir path
\n
"
);
status
=
SWITCH_STATUS_FALSE
;
}
}
}
return
status
;
}
static
switch_status_t
my_on_reporting_cb
(
switch_core_session_t
*
session
,
cdr_profile_t
*
profile
)
{
switch_xml_t
xml_cdr
=
NULL
;
cJSON
*
json_cdr
=
NULL
;
char
*
cdr_text
=
NULL
;
char
*
dpath
=
NULL
;
char
*
path
=
NULL
;
char
*
curl_cdr_text
=
NULL
;
const
char
*
logdir
=
NULL
;
char
*
cdr_text_escaped
=
NULL
;
int
fd
=
-
1
;
uint32_t
cur_try
;
long
httpRes
;
switch_CURL
*
curl_handle
=
NULL
;
switch_curl_slist_t
*
headers
=
NULL
;
switch_curl_slist_t
*
slist
=
NULL
;
switch_channel_t
*
channel
=
switch_core_session_get_channel
(
session
);
switch_status_t
status
=
SWITCH_STATUS_FALSE
;
int
is_b
;
const
char
*
a_prefix
=
""
;
if
(
globals
.
shutdown
)
{
return
SWITCH_STATUS_SUCCESS
;
}
is_b
=
channel
&&
switch_channel_get_originator_caller_profile
(
channel
);
if
(
!
profile
->
log_b
&&
is_b
)
{
const
char
*
force_cdr
=
switch_channel_get_variable
(
channel
,
SWITCH_FORCE_PROCESS_CDR_VARIABLE
);
if
(
!
switch_true
(
force_cdr
))
{
return
SWITCH_STATUS_SUCCESS
;
}
}
if
(
!
is_b
&&
profile
->
prefix_a
)
a_prefix
=
"a_"
;
if
(
!
strcasecmp
(
profile
->
format
,
"json"
)
)
{
if
(
switch_ivr_generate_json_cdr
(
session
,
&
json_cdr
,
profile
->
encode_values
==
ENCODING_DEFAULT
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Error Generating JSON Data!
\n
"
);
return
SWITCH_STATUS_FALSE
;
}
/* build the JSON */
cdr_text
=
cJSON_PrintUnformatted
(
json_cdr
);
if
(
!
cdr_text
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"Memory Error generating JSON!
\n
"
);
goto
error
;
}
}
else
if
(
!
strcasecmp
(
profile
->
format
,
"xml"
)
)
{
if
(
switch_ivr_generate_xml_cdr
(
session
,
&
xml_cdr
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Error Generating XML Data!
\n
"
);
return
SWITCH_STATUS_FALSE
;
}
/* build the XML */
cdr_text
=
switch_xml_toxml
(
xml_cdr
,
SWITCH_TRUE
);
if
(
!
cdr_text
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"Memory Error generating XML!
\n
"
);
goto
error
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"Unhandled format for mod_format_cdr!
\n
"
);
goto
error
;
}
switch_thread_rwlock_rdlock
(
profile
->
log_path_lock
);
if
(
!
(
logdir
=
switch_channel_get_variable
(
channel
,
"format_cdr_base"
)))
{
logdir
=
profile
->
log_dir
;
}
if
(
!
zstr
(
logdir
)
&&
(
profile
->
log_http_and_disk
||
!
profile
->
url_count
))
{
dpath
=
switch_mprintf
(
"%s%s%s"
,
logdir
,
SWITCH_PATH_SEPARATOR
,
a_prefix
);
path
=
switch_mprintf
(
"%s%s%s%s.cdr.%s"
,
logdir
,
SWITCH_PATH_SEPARATOR
,
a_prefix
,
switch_core_session_get_uuid
(
session
),
profile
->
format
);
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
if
(
path
)
{
if
(
switch_directory_exists
(
dpath
,
profile
->
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_dir_make_recursive
(
dpath
,
SWITCH_FPROT_OS_DEFAULT
,
profile
->
pool
);
}
#ifdef _MSC_VER
if
((
fd
=
open
(
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
))
>
-
1
)
{
#else
if
((
fd
=
open
(
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
|
S_IWOTH
))
>
-
1
)
{
#endif
int
wrote
;
wrote
=
write
(
fd
,
cdr_text
,
(
unsigned
)
strlen
(
cdr_text
));
wrote
++
;
close
(
fd
);
fd
=
-
1
;
}
else
{
char
ebuf
[
512
]
=
{
0
};
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Error writing [%s][%s]
\n
"
,
path
,
switch_strerror_r
(
errno
,
ebuf
,
sizeof
(
ebuf
)));
}
switch_safe_free
(
path
);
switch_safe_free
(
dpath
);
}
}
else
{
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
}
/* try to post it to the web server */
if
(
profile
->
url_count
)
{
char
*
destUrl
=
NULL
;
curl_handle
=
switch_curl_easy_init
();
if
(
profile
->
encode
==
ENCODING_TEXTXML
)
{
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: text/xml"
);
}
else
if
(
profile
->
encode
==
ENCODING_APPLJSON
)
{
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: application/json"
);
}
else
if
(
profile
->
encode
)
{
switch_size_t
need_bytes
=
strlen
(
cdr_text
)
*
3
+
1
;
cdr_text_escaped
=
malloc
(
need_bytes
);
switch_assert
(
cdr_text_escaped
);
memset
(
cdr_text_escaped
,
0
,
need_bytes
);
if
(
profile
->
encode
==
ENCODING_DEFAULT
)
{
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: application/x-www-form-urlencoded"
);
switch_url_encode
(
cdr_text
,
cdr_text_escaped
,
need_bytes
);
}
else
{
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: application/x-www-form-base64-encoded"
);
switch_b64_encode
((
unsigned
char
*
)
cdr_text
,
need_bytes
/
3
,
(
unsigned
char
*
)
cdr_text_escaped
,
need_bytes
);
}
switch_safe_free
(
cdr_text
);
cdr_text
=
cdr_text_escaped
;
}
else
{
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: application/x-www-form-plaintext"
);
}
if
(
profile
->
encode
==
ENCODING_TEXTXML
)
{
curl_cdr_text
=
cdr_text
;
}
else
if
(
profile
->
encode
==
ENCODING_APPLJSON
)
{
curl_cdr_text
=
cdr_text
;
}
else
if
(
!
(
curl_cdr_text
=
switch_mprintf
(
"cdr=%s"
,
cdr_text
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"Memory Error!
\n
"
);
goto
error
;
}
if
(
!
zstr
(
profile
->
cred
))
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_HTTPAUTH
,
profile
->
auth_scheme
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_USERPWD
,
profile
->
cred
);
}
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_HTTPHEADER
,
headers
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_POST
,
1
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_NOSIGNAL
,
1
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_POSTFIELDS
,
curl_cdr_text
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_USERAGENT
,
"freeswitch-format-cdr/1.0"
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_WRITEFUNCTION
,
httpCallBack
);
if
(
profile
->
disable100continue
)
{
slist
=
switch_curl_slist_append
(
slist
,
"Expect:"
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_HTTPHEADER
,
slist
);
}
if
(
profile
->
ssl_cert_file
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSLCERT
,
profile
->
ssl_cert_file
);
}
if
(
profile
->
ssl_key_file
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSLKEY
,
profile
->
ssl_key_file
);
}
if
(
profile
->
ssl_key_password
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSLKEYPASSWD
,
profile
->
ssl_key_password
);
}
if
(
profile
->
ssl_version
)
{
if
(
!
strcasecmp
(
profile
->
ssl_version
,
"SSLv3"
))
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSLVERSION
,
CURL_SSLVERSION_SSLv3
);
}
else
if
(
!
strcasecmp
(
profile
->
ssl_version
,
"TLSv1"
))
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSLVERSION
,
CURL_SSLVERSION_TLSv1
);
}
}
if
(
profile
->
ssl_cacert_file
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_CAINFO
,
profile
->
ssl_cacert_file
);
}
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_TIMEOUT
,
profile
->
timeout
);
/* these were used for testing, optionally they may be enabled if someone desires
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level
*/
for
(
cur_try
=
0
;
cur_try
<
profile
->
retries
;
cur_try
++
)
{
if
(
cur_try
>
0
)
{
switch_yield
(
profile
->
delay
*
1000000
);
}
destUrl
=
switch_mprintf
(
"%s?uuid=%s%s"
,
profile
->
urls
[
profile
->
url_index
],
a_prefix
,
switch_core_session_get_uuid
(
session
));
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_URL
,
destUrl
);
if
(
!
strncasecmp
(
destUrl
,
"https"
,
5
))
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSL_VERIFYPEER
,
0
);
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSL_VERIFYHOST
,
0
);
}
if
(
profile
->
enable_cacert_check
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSL_VERIFYPEER
,
TRUE
);
}
if
(
profile
->
enable_ssl_verifyhost
)
{
switch_curl_easy_setopt
(
curl_handle
,
CURLOPT_SSL_VERIFYHOST
,
2
);
}
switch_curl_easy_perform
(
curl_handle
);
switch_curl_easy_getinfo
(
curl_handle
,
CURLINFO_RESPONSE_CODE
,
&
httpRes
);
switch_safe_free
(
destUrl
);
if
(
httpRes
>=
200
&&
httpRes
<=
299
)
{
goto
success
;
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Got error [%ld] posting to web server [%s]
\n
"
,
httpRes
,
profile
->
urls
[
profile
->
url_index
]);
profile
->
url_index
++
;
switch_assert
(
profile
->
url_count
<=
MAX_URLS
);
if
(
profile
->
url_index
>=
profile
->
url_count
)
{
profile
->
url_index
=
0
;
}
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Retry will be with url [%s]
\n
"
,
profile
->
urls
[
profile
->
url_index
]);
}
}
switch_curl_easy_cleanup
(
curl_handle
);
switch_curl_slist_free_all
(
headers
);
switch_curl_slist_free_all
(
slist
);
slist
=
NULL
;
headers
=
NULL
;
curl_handle
=
NULL
;
/* if we are here the web post failed for some reason */
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to post to web server, writing to file
\n
"
);
switch_thread_rwlock_rdlock
(
profile
->
log_path_lock
);
dpath
=
switch_mprintf
(
"%s%s%s"
,
profile
->
err_log_dir
,
SWITCH_PATH_SEPARATOR
,
a_prefix
);
path
=
switch_mprintf
(
"%s%s%s%s.cdr.%s"
,
profile
->
err_log_dir
,
SWITCH_PATH_SEPARATOR
,
a_prefix
,
switch_core_session_get_uuid
(
session
),
profile
->
format
);
switch_thread_rwlock_unlock
(
profile
->
log_path_lock
);
if
(
path
)
{
if
(
switch_directory_exists
(
dpath
,
profile
->
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_dir_make_recursive
(
dpath
,
SWITCH_FPROT_OS_DEFAULT
,
profile
->
pool
);
}
#ifdef _MSC_VER
if
((
fd
=
open
(
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
))
>
-
1
)
{
#else
if
((
fd
=
open
(
path
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
|
S_IWOTH
))
>
-
1
)
{
#endif
int
wrote
;
wrote
=
write
(
fd
,
cdr_text
,
(
unsigned
)
strlen
(
cdr_text
));
wrote
++
;
close
(
fd
);
fd
=
-
1
;
}
else
{
char
ebuf
[
512
]
=
{
0
};
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Error![%s]
\n
"
,
switch_strerror_r
(
errno
,
ebuf
,
sizeof
(
ebuf
)));
}
switch_safe_free
(
path
);
switch_safe_free
(
dpath
);
}
}
success:
status
=
SWITCH_STATUS_SUCCESS
;
error:
if
(
curl_handle
)
{
switch_curl_easy_cleanup
(
curl_handle
);
}
if
(
headers
)
{
switch_curl_slist_free_all
(
headers
);
}
if
(
slist
)
{
switch_curl_slist_free_all
(
slist
);
}
if
(
curl_cdr_text
!=
cdr_text
)
{
switch_safe_free
(
curl_cdr_text
);
}
switch_safe_free
(
cdr_text
);
switch_safe_free
(
path
);
switch_safe_free
(
dpath
);
if
(
xml_cdr
)
{
switch_xml_free
(
xml_cdr
);
}
if
(
json_cdr
)
{
cJSON_Delete
(
json_cdr
);
}
return
status
;
}
static
switch_status_t
my_on_reporting
(
switch_core_session_t
*
session
)
{
switch_hash_index_t
*
hi
;
void
*
val
;
switch_status_t
status
,
tmpstatus
;
status
=
SWITCH_STATUS_SUCCESS
;
for
(
hi
=
switch_hash_first
(
NULL
,
globals
.
profile_hash
);
hi
;
hi
=
switch_hash_next
(
hi
))
{
cdr_profile_t
*
profile
;
switch_hash_this
(
hi
,
NULL
,
NULL
,
&
val
);
profile
=
(
cdr_profile_t
*
)
val
;
tmpstatus
=
my_on_reporting_cb
(
session
,
profile
);
if
(
tmpstatus
!=
SWITCH_STATUS_SUCCESS
)
{
status
=
tmpstatus
;
}
}
return
status
;
}
static
void
event_handler
(
switch_event_t
*
event
)
{
switch_hash_index_t
*
hi
;
void
*
val
;
const
char
*
sig
=
switch_event_get_header
(
event
,
"Trapped-Signal"
);
if
(
sig
&&
!
strcmp
(
sig
,
"HUP"
))
{
for
(
hi
=
switch_hash_first
(
NULL
,
globals
.
profile_hash
);
hi
;
hi
=
switch_hash_next
(
hi
))
{
cdr_profile_t
*
profile
;
switch_hash_this
(
hi
,
NULL
,
NULL
,
&
val
);
profile
=
(
cdr_profile_t
*
)
val
;
if
(
profile
->
rotate
)
{
set_format_cdr_log_dirs
(
profile
);
}
}
}
}
static
switch_state_handler_table_t
state_handlers
=
{
/*.on_init */
NULL
,
/*.on_routing */
NULL
,
/*.on_execute */
NULL
,
/*.on_hangup */
NULL
,
/*.on_exchange_media */
NULL
,
/*.on_soft_execute */
NULL
,
/*.on_consume_media */
NULL
,
/*.on_hibernate */
NULL
,
/*.on_reset */
NULL
,
/*.on_park */
NULL
,
/*.on_reporting */
my_on_reporting
};
switch_status_t
mod_format_cdr_load_profile_xml
(
switch_xml_t
xprofile
)
{
switch_memory_pool_t
*
pool
=
NULL
;
cdr_profile_t
*
profile
=
NULL
;
switch_xml_t
settings
,
param
;
char
*
profile_name
=
(
char
*
)
switch_xml_attr_soft
(
xprofile
,
"name"
);
if
(
switch_core_new_memory_pool
(
&
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"OH OH no pool
\n
"
);
return
SWITCH_STATUS_TERM
;
}
profile
=
switch_core_alloc
(
pool
,
sizeof
(
cdr_profile_t
));
profile
->
pool
=
pool
;
profile
->
name
=
switch_core_strdup
(
profile
->
pool
,
profile_name
);
profile
->
log_http_and_disk
=
0
;
profile
->
log_b
=
1
;
profile
->
disable100continue
=
0
;
profile
->
auth_scheme
=
CURLAUTH_BASIC
;
switch_thread_rwlock_create
(
&
profile
->
log_path_lock
,
pool
);
if
((
settings
=
switch_xml_child
(
xprofile
,
"settings"
)))
{
for
(
param
=
switch_xml_child
(
settings
,
"param"
);
param
;
param
=
param
->
next
)
{
char
*
var
=
(
char
*
)
switch_xml_attr_soft
(
param
,
"name"
);
char
*
val
=
(
char
*
)
switch_xml_attr_soft
(
param
,
"value"
);
if
(
!
strcasecmp
(
var
,
"cred"
)
&&
!
zstr
(
val
))
{
profile
->
cred
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"format"
)
&&
!
zstr
(
val
))
{
profile
->
format
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"url"
)
&&
!
zstr
(
val
))
{
if
(
profile
->
url_count
>=
MAX_URLS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"maximum urls configured!
\n
"
);
}
else
{
profile
->
urls
[
profile
->
url_count
++
]
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
}
else
if
(
!
strcasecmp
(
var
,
"log-http-and-disk"
))
{
profile
->
log_http_and_disk
=
switch_true
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"timeout"
))
{
int
tmp
=
atoi
(
val
);
if
(
tmp
>=
0
)
{
profile
->
timeout
=
tmp
;
}
else
{
profile
->
timeout
=
0
;
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Can't set a negative timeout!
\n
"
);
}
}
else
if
(
!
strcasecmp
(
var
,
"delay"
)
&&
!
zstr
(
val
))
{
profile
->
delay
=
switch_atoui
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"log-b-leg"
))
{
profile
->
log_b
=
switch_true
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"prefix-a-leg"
))
{
profile
->
prefix_a
=
switch_true
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"disable-100-continue"
)
&&
switch_true
(
val
))
{
profile
->
disable100continue
=
1
;
}
else
if
(
!
strcasecmp
(
var
,
"encode"
)
&&
!
zstr
(
val
))
{
if
(
!
strcasecmp
(
val
,
"base64"
))
{
profile
->
encode
=
ENCODING_BASE64
;
}
else
if
(
!
strcasecmp
(
val
,
"textxml"
))
{
profile
->
encode
=
ENCODING_TEXTXML
;
}
else
if
(
!
strcasecmp
(
val
,
"appljson"
))
{
profile
->
encode
=
ENCODING_APPLJSON
;
}
else
{
profile
->
encode
=
switch_true
(
val
)
?
ENCODING_DEFAULT
:
ENCODING_NONE
;
}
}
else
if
(
!
strcasecmp
(
var
,
"retries"
)
&&
!
zstr
(
val
))
{
profile
->
retries
=
switch_atoui
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"rotate"
)
&&
!
zstr
(
val
))
{
profile
->
rotate
=
switch_true
(
val
);
}
else
if
(
!
strcasecmp
(
var
,
"log-dir"
))
{
if
(
zstr
(
val
))
{
profile
->
base_log_dir
=
switch_core_sprintf
(
profile
->
pool
,
"%s%sformat_cdr"
,
SWITCH_GLOBAL_dirs
.
log_dir
,
SWITCH_PATH_SEPARATOR
);
}
else
{
if
(
switch_is_file_path
(
val
))
{
profile
->
base_log_dir
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
{
profile
->
base_log_dir
=
switch_core_sprintf
(
profile
->
pool
,
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
log_dir
,
SWITCH_PATH_SEPARATOR
,
val
);
}
}
}
else
if
(
!
strcasecmp
(
var
,
"err-log-dir"
))
{
if
(
profile
->
err_dir_count
>=
MAX_ERR_DIRS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"maximum error directories configured!
\n
"
);
}
else
{
if
(
zstr
(
val
))
{
profile
->
base_err_log_dir
[
profile
->
err_dir_count
++
]
=
switch_core_sprintf
(
profile
->
pool
,
"%s%sformat_cdr"
,
SWITCH_GLOBAL_dirs
.
log_dir
,
SWITCH_PATH_SEPARATOR
);
}
else
{
if
(
switch_is_file_path
(
val
))
{
profile
->
base_err_log_dir
[
profile
->
err_dir_count
++
]
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
{
profile
->
base_err_log_dir
[
profile
->
err_dir_count
++
]
=
switch_core_sprintf
(
profile
->
pool
,
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
log_dir
,
SWITCH_PATH_SEPARATOR
,
val
);
}
}
}
}
else
if
(
!
strcasecmp
(
var
,
"enable-cacert-check"
)
&&
switch_true
(
val
))
{
profile
->
enable_cacert_check
=
1
;
}
else
if
(
!
strcasecmp
(
var
,
"ssl-cert-path"
))
{
profile
->
ssl_cert_file
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"ssl-key-path"
))
{
profile
->
ssl_key_file
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"ssl-key-password"
))
{
profile
->
ssl_key_password
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"ssl-version"
))
{
profile
->
ssl_version
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"ssl-cacert-file"
))
{
profile
->
ssl_cacert_file
=
switch_core_strdup
(
profile
->
pool
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"enable-ssl-verifyhost"
)
&&
switch_true
(
val
))
{
profile
->
enable_ssl_verifyhost
=
1
;
}
else
if
(
!
strcasecmp
(
var
,
"auth-scheme"
))
{
if
(
*
val
==
'='
)
{
profile
->
auth_scheme
=
0
;
val
++
;
}
if
(
!
strcasecmp
(
val
,
"basic"
))
{
profile
->
auth_scheme
|=
CURLAUTH_BASIC
;
}
else
if
(
!
strcasecmp
(
val
,
"digest"
))
{
profile
->
auth_scheme
|=
CURLAUTH_DIGEST
;
}
else
if
(
!
strcasecmp
(
val
,
"NTLM"
))
{
profile
->
auth_scheme
|=
CURLAUTH_NTLM
;
}
else
if
(
!
strcasecmp
(
val
,
"GSS-NEGOTIATE"
))
{
profile
->
auth_scheme
|=
CURLAUTH_GSSNEGOTIATE
;
}
else
if
(
!
strcasecmp
(
val
,
"any"
))
{
profile
->
auth_scheme
=
CURLAUTH_ANY
;
}
}
else
if
(
!
strcasecmp
(
var
,
"encode-values"
)
&&
!
zstr
(
val
))
{
profile
->
encode_values
=
switch_true
(
val
)
?
ENCODING_DEFAULT
:
ENCODING_NONE
;
}
}
if
(
!
profile
->
err_dir_count
)
{
if
(
!
zstr
(
profile
->
base_log_dir
))
{
profile
->
base_err_log_dir
[
profile
->
err_dir_count
++
]
=
switch_core_strdup
(
profile
->
pool
,
profile
->
base_log_dir
);
}
else
{
profile
->
base_err_log_dir
[
profile
->
err_dir_count
++
]
=
switch_core_sprintf
(
profile
->
pool
,
"%s%sformat_cdr"
,
SWITCH_GLOBAL_dirs
.
log_dir
,
SWITCH_PATH_SEPARATOR
);
}
}
}
if
(
profile
->
retries
&&
profile
->
delay
==
0
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Retries set but delay 0 setting to 5 seconds
\n
"
);
profile
->
delay
=
5
;
}
if
(
!
profile
->
format
||
(
strcasecmp
(
profile
->
format
,
"json"
)
&&
strcasecmp
(
profile
->
format
,
"xml"
))
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"No valid format_cdr format specified, defaulting to xml.
\n
"
);
profile
->
format
=
switch_core_strdup
(
profile
->
pool
,
"xml"
);
}
profile
->
retries
++
;
switch_mutex_lock
(
globals
.
mutex
);
switch_core_hash_insert
(
globals
.
profile_hash
,
profile
->
name
,
profile
);
switch_mutex_unlock
(
globals
.
mutex
);
set_format_cdr_log_dirs
(
profile
);
return
SWITCH_STATUS_SUCCESS
;
}
SWITCH_MODULE_LOAD_FUNCTION
(
mod_format_cdr_load
)
{
char
*
cf
=
"format_cdr.conf"
;
switch_xml_t
cfg
,
xml
,
xprofiles
,
xprofile
;
switch_status_t
status
=
SWITCH_STATUS_SUCCESS
;
/* test global state handlers */
switch_core_add_state_handler
(
&
state_handlers
);
*
module_interface
=
switch_loadable_module_create_module_interface
(
pool
,
modname
);
memset
(
&
globals
,
0
,
sizeof
(
globals
));
if
(
switch_event_bind_removable
(
modname
,
SWITCH_EVENT_TRAP
,
SWITCH_EVENT_SUBCLASS_ANY
,
event_handler
,
NULL
,
&
globals
.
node
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Couldn't bind!
\n
"
);
return
SWITCH_STATUS_GENERR
;
}
globals
.
pool
=
pool
;
switch_mutex_init
(
&
globals
.
mutex
,
SWITCH_MUTEX_NESTED
,
globals
.
pool
);
switch_core_hash_init
(
&
globals
.
profile_hash
,
globals
.
pool
);
/* parse the config */
if
(
!
(
xml
=
switch_xml_open_cfg
(
cf
,
&
cfg
,
NULL
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Open of %s failed
\n
"
,
cf
);
return
SWITCH_STATUS_TERM
;
}
switch_mutex_lock
(
globals
.
mutex
);
if
((
xprofiles
=
switch_xml_child
(
cfg
,
"profiles"
)))
{
for
(
xprofile
=
switch_xml_child
(
xprofiles
,
"profile"
);
xprofile
;
xprofile
=
xprofile
->
next
)
{
char
*
profile_name
=
(
char
*
)
switch_xml_attr_soft
(
xprofile
,
"name"
);
if
(
zstr
(
profile_name
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"<profile> is missing name attribute
\n
"
);
continue
;
}
mod_format_cdr_load_profile_xml
(
xprofile
);
}
}
switch_xml_free
(
xml
);
switch_mutex_unlock
(
globals
.
mutex
);
return
status
;
}
void
mod_format_cdr_profile_shutdown
(
cdr_profile_t
*
profile
)
{
int
err_dir_index
=
0
;
for
(
err_dir_index
=
0
;
err_dir_index
<
profile
->
err_dir_count
;
err_dir_index
++
)
{
switch_safe_free
(
profile
->
err_log_dir
[
err_dir_index
]);
}
switch_safe_free
(
profile
->
log_dir
);
switch_core_destroy_memory_pool
(
&
profile
->
pool
);
switch_thread_rwlock_destroy
(
profile
->
log_path_lock
);
}
SWITCH_MODULE_SHUTDOWN_FUNCTION
(
mod_format_cdr_shutdown
)
{
switch_hash_index_t
*
hi
;
void
*
val
;
globals
.
shutdown
=
1
;
switch_event_unbind
(
&
globals
.
node
);
switch_core_remove_state_handler
(
&
state_handlers
);
for
(
hi
=
switch_hash_first
(
NULL
,
globals
.
profile_hash
);
hi
;
hi
=
switch_hash_next
(
hi
))
{
cdr_profile_t
*
profile
;
switch_hash_this
(
hi
,
NULL
,
NULL
,
&
val
);
profile
=
(
cdr_profile_t
*
)
val
;
mod_format_cdr_profile_shutdown
(
profile
);
}
switch_core_hash_destroy
(
&
globals
.
profile_hash
);
switch_core_destroy_memory_pool
(
&
globals
.
pool
);
memset
(
&
globals
,
0
,
sizeof
(
globals
));
return
SWITCH_STATUS_SUCCESS
;
}
/* 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 noet:
*/
src/mod/event_handlers/mod_format_cdr/mod_format_cdr.vcproj
0 → 100644
浏览文件 @
3b36e990
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType=
"Visual C++"
Version=
"8.00"
Name=
"mod_format_cdr"
ProjectGUID=
"{08DAD348-9E0A-4A2E-97F1-F1E7E24A7836}"
RootNamespace=
"mod_format_cdr"
Keyword=
"Win32Proj"
>
<Platforms>
<Platform
Name=
"Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name=
"Debug|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_debug.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCLinkerTool"
/>
</Configuration>
<Configuration
Name=
"Release|Win32"
ConfigurationType=
"2"
InheritedPropertySheets=
"..\..\..\..\w32\module_release.vsprops;..\..\..\..\w32\curl.vsprops"
CharacterSet=
"2"
>
<Tool
Name=
"VCCLCompilerTool"
AdditionalIncludeDirectories=
""
UsePrecompiledHeader=
"0"
/>
<Tool
Name=
"VCLinkerTool"
AdditionalLibraryDirectories=
""
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath=
".\mod_format_cdr.c"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论