Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
d0cca7e2
提交
d0cca7e2
authored
12月 07, 2018
作者:
Andrey Volk
提交者:
Andrey Volk
12月 21, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
FS-11555: [mod_signalwire] Initial commit.
上级
c27206e3
隐藏空白字符变更
内嵌
并排
正在显示
22 个修改的文件
包含
1752 行增加
和
2 行删除
+1752
-2
Freeswitch.2017.sln
Freeswitch.2017.sln
+15
-0
modules.conf.in
build/modules.conf.in
+1
-0
modules.conf.most
build/modules.conf.most
+1
-0
modules.conf.xml
conf/insideout/autoload_configs/modules.conf.xml
+1
-0
modules.conf.xml
conf/minimal/autoload_configs/modules.conf.xml
+1
-0
modules.conf.xml
conf/rayo/autoload_configs/modules.conf.xml
+1
-0
modules.conf.xml
conf/sbc/autoload_configs/modules.conf.xml
+1
-0
freeswitch.xml
conf/softphone/freeswitch.xml
+1
-0
modules.conf.xml
conf/vanilla/autoload_configs/modules.conf.xml
+1
-0
configure.ac
configure.ac
+9
-0
control-modules
debian/control-modules
+5
-0
freeswitch.spec
freeswitch.spec
+16
-2
.gitignore
libs/.gitignore
+5
-0
Makefile.am
src/mod/applications/mod_signalwire/Makefile.am
+27
-0
signalwire.conf.xml
.../mod_signalwire/conf/autoload_configs/signalwire.conf.xml
+10
-0
mod_signalwire.2017.vcxproj
...d/applications/mod_signalwire/mod_signalwire.2017.vcxproj
+149
-0
mod_signalwire.c
src/mod/applications/mod_signalwire/mod_signalwire.c
+1308
-0
Setup.2017.wixproj
w32/Setup/Setup.2017.wixproj
+8
-0
libks-version.props
w32/libks-version.props
+19
-0
libks.props
w32/libks.props
+78
-0
signalwire-client-c-version.props
w32/signalwire-client-c-version.props
+19
-0
signalwire-client-c.props
w32/signalwire-client-c.props
+76
-0
没有找到文件。
Freeswitch.2017.sln
浏览文件 @
d0cca7e2
...
...
@@ -576,6 +576,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "48khz", "libs\win32\Sound_F
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "48khz music", "libs\win32\Sound_Files\48khzmusic.2017.vcxproj", "{EBD0B6B4-C5CA-46B0-BBC7-DBA71DF05D31}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_signalwire", "src\mod\applications\mod_signalwire\mod_signalwire.2017.vcxproj", "{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
...
...
@@ -2627,6 +2629,18 @@ Global
{EBD0B6B4-C5CA-46B0-BBC7-DBA71DF05D31}.Debug|x64.Build.0 = Debug|x64
{EBD0B6B4-C5CA-46B0-BBC7-DBA71DF05D31}.Release|Win32.ActiveCfg = Release|Win32
{EBD0B6B4-C5CA-46B0-BBC7-DBA71DF05D31}.Release|x64.ActiveCfg = Release|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.All|Win32.ActiveCfg = Release|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.All|Win32.Build.0 = Release|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.All|x64.ActiveCfg = Release|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.All|x64.Build.0 = Release|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Debug|Win32.ActiveCfg = Debug|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Debug|Win32.Build.0 = Debug|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Debug|x64.ActiveCfg = Debug|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Debug|x64.Build.0 = Debug|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Release|Win32.ActiveCfg = Release|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Release|Win32.Build.0 = Release|Win32
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Release|x64.ActiveCfg = Release|x64
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
...
...
@@ -2836,6 +2850,7 @@ Global
{EF62B845-A0CE-44FD-B8E6-475FE87D06C3} = {9388C266-C3FC-468A-92EF-0CBC35941412}
{8154C82D-58EE-4145-9DEC-A445A5AA3D6B} = {4F227C26-768F-46A3-8684-1D08A46FB374}
{EBD0B6B4-C5CA-46B0-BBC7-DBA71DF05D31} = {4F227C26-768F-46A3-8684-1D08A46FB374}
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}
...
...
build/modules.conf.in
浏览文件 @
d0cca7e2
...
...
@@ -39,6 +39,7 @@ applications/mod_httapi
#applications/mod_rad_auth
#applications/mod_redis
#applications/mod_rss
applications/mod_signalwire
applications/mod_sms
#applications/mod_sms_flowroute
#applications/mod_snapshot
...
...
build/modules.conf.most
浏览文件 @
d0cca7e2
...
...
@@ -38,6 +38,7 @@ applications/mod_prefix
#applications/mod_rad_auth
applications/mod_redis
applications/mod_rss
applications/mod_signalwire
applications/mod_sms
applications/mod_snapshot
applications/mod_snom
...
...
conf/insideout/autoload_configs/modules.conf.xml
浏览文件 @
d0cca7e2
...
...
@@ -37,6 +37,7 @@
<!-- <load module="mod_freetdm"/> -->
<!-- Applications -->
<!--load module="mod_signalwire"/-->
<load
module=
"mod_commands"
/>
<load
module=
"mod_conference"
/>
<load
module=
"mod_dptools"
/>
...
...
conf/minimal/autoload_configs/modules.conf.xml
浏览文件 @
d0cca7e2
...
...
@@ -17,6 +17,7 @@
<load
module=
"mod_loopback"
/>
<!-- Applications -->
<!--load module="mod_signalwire"/-->
<load
module=
"mod_commands"
/>
<load
module=
"mod_conference"
/>
<load
module=
"mod_db"
/>
...
...
conf/rayo/autoload_configs/modules.conf.xml
浏览文件 @
d0cca7e2
...
...
@@ -14,6 +14,7 @@
<load
module=
"mod_loopback"
/>
<!-- Applications -->
<!--load module="mod_signalwire"-->
<load
module=
"mod_commands"
/>
<load
module=
"mod_conference"
/>
<load
module=
"mod_dptools"
/>
...
...
conf/sbc/autoload_configs/modules.conf.xml
浏览文件 @
d0cca7e2
...
...
@@ -26,6 +26,7 @@
<!-- <load module="mod_woomera"/> -->
<!-- Applications -->
<!--load module="mod_signalwire"/-->
<load
module=
"mod_commands"
/>
<load
module=
"mod_dptools"
/>
<load
module=
"mod_expr"
/>
...
...
conf/softphone/freeswitch.xml
浏览文件 @
d0cca7e2
...
...
@@ -89,6 +89,7 @@
<load
module=
"mod_sndfile"
/>
<load
module=
"mod_tone_stream"
/>
<load
module=
"mod_local_stream"
/>
<!--load module="mod_signalwire"/-->
</modules>
</configuration>
...
...
conf/vanilla/autoload_configs/modules.conf.xml
浏览文件 @
d0cca7e2
...
...
@@ -50,6 +50,7 @@
<load
module=
"mod_verto"
/>
<!-- Applications -->
<load
module=
"mod_signalwire"
/>
<load
module=
"mod_commands"
/>
<load
module=
"mod_conference"
/>
<!-- <load module="mod_curl"/> -->
...
...
configure.ac
浏览文件 @
d0cca7e2
...
...
@@ -1498,6 +1498,14 @@ PKG_CHECK_MODULES([V8FS_STATIC], [v8-6.1_static >= 6.1.298],[
])
])
PKG_CHECK_MODULES([KS], [libks >= 1.1.0],[
AM_CONDITIONAL([HAVE_KS],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_KS],[false])])
PKG_CHECK_MODULES([SIGNALWIRE_CLIENT], [signalwire_client >= 1.0.0],[
AM_CONDITIONAL([HAVE_SIGNALWIRE_CLIENT],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_SIGNALWIRE_CLIENT],[false])])
PKG_CHECK_MODULES([AMQP], [librabbitmq >= 0.5.2],[
AM_CONDITIONAL([HAVE_AMQP],[true])],[
AC_MSG_RESULT([no]); AM_CONDITIONAL([HAVE_AMQP],[false])])
...
...
@@ -1853,6 +1861,7 @@ AC_CONFIG_FILES([Makefile
src/mod/applications/mod_redis/Makefile
src/mod/applications/mod_rss/Makefile
src/mod/applications/mod_skel/Makefile
src/mod/applications/mod_signalwire/Makefile
src/mod/applications/mod_sms/Makefile
src/mod/applications/mod_sms_flowroute/Makefile
src/mod/applications/mod_snapshot/Makefile
...
...
debian/control-modules
浏览文件 @
d0cca7e2
...
...
@@ -206,6 +206,11 @@ Module: applications/mod_skel
Description: Adds mod_skel
Adds mod_skel.
Module: applications/mod_signalwire
Description: mod_signalwire
Adds mod_signalwire.
Build-Depends: libks, signalwire-client-c
Module: applications/mod_sms
Description: Astract SMS
This module provides an abstract facility for interfacing with SMS
...
...
freeswitch.spec
浏览文件 @
d0cca7e2
...
...
@@ -3,7 +3,7 @@
# spec file for package freeswitch
#
# includes module(s): freeswitch-devel freeswitch-codec-passthru-amr freeswitch-codec-passthru-amrwb freeswitch-codec-passthru-g729
# freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-perl freeswitch-python freeswitch-v8
# freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-perl freeswitch-python freeswitch-v8
freeswitch-signalwire
# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-hu freeswitch-lang-ru freeswitch-freetdm
# and others
#
...
...
@@ -536,6 +536,14 @@ Requires: %{name} = %{version}-%{release}
Provides FreeSWITCH mod_rss, edisrse and read an XML based RSS feed, then read
the entries aloud via a TTS engine
%package application-signalwire
Summary: FreeSWITCH mod_signalwire
Group: System/Libraries
Requires: %{name} = %{version}-%{release}
%description application-signalwire
Provides FreeSWITCH mod_signalwire
%package application-sms
Summary: FreeSWITCH mod_sms
Group: System/Libraries
...
...
@@ -1373,6 +1381,7 @@ Requires: freeswitch-application-memcache
Requires: freeswitch-application-nibblebill
Requires: freeswitch-application-redis
Requires: freeswitch-application-rss
Requires: freeswitch-application-signalwire
Requires: freeswitch-application-sms
Requires: freeswitch-application-snapshot
Requires: freeswitch-application-snom
...
...
@@ -1458,7 +1467,7 @@ APPLICATION_MODULES_FR="applications/mod_fifo applications/mod_fsk applications/
applications/mod_memcache applications/mod_mongo applications/mod_nibblebill applications/mod_rad_auth \
applications/mod_redis applications/mod_rss "
APPLICATION_MODULES_SZ="applications/mod_sms applications/mod_snapshot applications/mod_snom applications/mod_soundtouch \
APPLICATION_MODULES_SZ="applications/mod_s
ignalwire applications/mod_s
ms applications/mod_snapshot applications/mod_snom applications/mod_soundtouch \
applications/mod_spandsp applications/mod_spy applications/mod_stress \
applications/mod_valet_parking applications/mod_translate applications/mod_voicemail \
applications/mod_voicemail_ivr applications/mod_video_filter"
...
...
@@ -2115,6 +2124,9 @@ fi
%files application-rss
%{MODINSTDIR}/mod_rss.so*
%files application-signalwire
%{MODINSTDIR}/mod_signalwire.so*
%files application-sms
%{MODINSTDIR}/mod_sms.so*
...
...
@@ -2541,6 +2553,8 @@ fi
#
######################################################################################################################
%changelog
* Tue Dec 11 2018 - Andrey Volk
- add mod_signalwire
* Sun Mar 13 2016 - Matthew Vale
- add perl and python ESL language module packages
* Thu Jul 09 2015 - Artur Zaprzała
...
...
libs/.gitignore
浏览文件 @
d0cca7e2
...
...
@@ -858,3 +858,8 @@ libsndfile-*/
libsndfile-*
opencv-*/
opencv-*
libks-*/
libks*
signalwire-client-c-*/
signalwire-client-c-*
src/mod/applications/mod_signalwire/Makefile.am
0 → 100644
浏览文件 @
d0cca7e2
include
$(top_srcdir)/build/modmake.rulesam
MODNAME
=
mod_signalwire
if
HAVE_KS
if
HAVE_SIGNALWIRE_CLIENT
mod_LTLIBRARIES
=
mod_signalwire.la
mod_signalwire_la_SOURCES
=
mod_signalwire.c
mod_signalwire_la_CFLAGS
=
$(AM_CFLAGS)
mod_signalwire_la_CFLAGS
+=
$(KS_CFLAGS)
$(SIGNALWIRE_CLIENT_CFLAGS)
mod_signalwire_la_LIBADD
=
$(switch_builddir)
/libfreeswitch.la
mod_signalwire_la_LDFLAGS
=
-avoid-version
-module
-no-undefined
-shared
$(KS_LIBS)
$(SIGNALWIRE_CLIENT_LIBS)
else
install
:
error
all
:
error
error
:
$
(
error You must
install
signalwire-client-c to build mod_signalwire
)
endif
else
install
:
error
all
:
error
error
:
$
(
error You must
install
libks to build mod_signalwire
)
endif
src/mod/applications/mod_signalwire/conf/autoload_configs/signalwire.conf.xml
0 → 100644
浏览文件 @
d0cca7e2
<configuration
name=
"signalwire.conf"
description=
"SignalWire"
>
<settings>
<!-- on/off/file-path -->
<!--param name="kslog" value="on"/-->
<!--param name="blade-bootstrap" value="blade://switchblade:2100"/-->
<!--param name="adoption-service" value="https://adopt.signalwire.com/adoption"/-->
<!--param name="stun-server" value="stun.freeswitch.org"/-->
<!-- <authentication></authentication> -->
</settings>
</configuration>
src/mod/applications/mod_signalwire/mod_signalwire.2017.vcxproj
0 → 100644
浏览文件 @
d0cca7e2
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets=
"Build"
ToolsVersion=
"15.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_signalwire
</ProjectName>
<RootNamespace>
mod_signalwire
</RootNamespace>
<Keyword>
Win32Proj
</Keyword>
<ProjectGuid>
{B19AE6FC-BFFF-428D-B483-3BBEAECCC618}
</ProjectGuid>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.Default.props"
/>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v141
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v141
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v141
</PlatformToolset>
</PropertyGroup>
<PropertyGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
Label=
"Configuration"
>
<ConfigurationType>
DynamicLibrary
</ConfigurationType>
<CharacterSet>
MultiByte
</CharacterSet>
<PlatformToolset>
v141
</PlatformToolset>
</PropertyGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.props"
/>
<Import
Project=
"$(SolutionDir)\w32\libks.props"
Condition=
" '$(libksPropsImported)' == '' "
/>
<Import
Project=
"$(SolutionDir)\w32\signalwire-client-c.props"
Condition=
" '$(signalwire-client-cPropsImported)' == '' "
/>
<Import
Project=
"$(SolutionDir)\w32\openssl.props"
Condition=
" '$(OpensslPropsImported)' == '' "
/>
<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>
<ClCompile>
<AdditionalIncludeDirectories>
.;%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<PreprocessorDefinitions>
_DEBUG;DEBUG;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<PreprocessorDefinitions>
_DEBUG;DEBUG;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|Win32'"
>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<PreprocessorDefinitions>
NDEBUG;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup
Condition=
"'$(Configuration)|$(Platform)'=='Release|x64'"
>
<Midl>
<TargetEnvironment>
X64
</TargetEnvironment>
</Midl>
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<PreprocessorDefinitions>
NDEBUG;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<RandomizedBaseAddress>
false
</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>
MachineX64
</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile
Include=
"mod_signalwire.c"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference
Include=
"..\..\..\..\w32\Library\FreeSwitchCore.2017.vcxproj"
>
<Project>
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
</Project>
<ReferenceOutputAssembly>
false
</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import
Project=
"$(VCTargetsPath)\Microsoft.Cpp.targets"
/>
<ImportGroup
Label=
"ExtensionTargets"
>
</ImportGroup>
</Project>
src/mod/applications/mod_signalwire/mod_signalwire.c
0 → 100644
浏览文件 @
d0cca7e2
/*
* mod_signalwire.c -- SignalWire module
*
* Copyright (c) 2018 SignalWire, Inc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <switch.h>
#include <switch_curl.h>
#include <switch_stun.h>
#include <signalwire-client-c/client.h>
#ifndef WIN32
#include <sys/utsname.h>
#endif
#define SW_KS_JSON_PRINT(_h, _j) do { \
char *_json = ks_json_print(_j); \
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ALERT, "--- %s ---\n%s\n---\n", _h, _json); \
ks_json_free(&_json); \
} while (0)
static
int
debug_level
=
7
;
static
int
signalwire_gateway_exists
(
void
);
/* Prototypes */
SWITCH_MODULE_SHUTDOWN_FUNCTION
(
mod_signalwire_shutdown
);
SWITCH_MODULE_LOAD_FUNCTION
(
mod_signalwire_load
);
SWITCH_MODULE_RUNTIME_FUNCTION
(
mod_signalwire_runtime
);
/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
* Defines a switch_loadable_module_function_table_t and a static const char[] modname
*/
SWITCH_MODULE_DEFINITION
(
mod_signalwire
,
mod_signalwire_load
,
mod_signalwire_shutdown
,
mod_signalwire_runtime
);
typedef
enum
{
SW_STATE_ADOPTION
,
SW_STATE_OFFLINE
,
SW_STATE_ONLINE
,
SW_STATE_CONFIGURE
,
SW_STATE_START_PROFILE
,
SW_STATE_REGISTER
,
SW_STATE_READY
,
}
sw_state_t
;
static
struct
{
int
ssl_verify
;
ks_bool_t
shutdown
;
ks_bool_t
restarting
;
swclt_config_t
*
config
;
char
blade_bootstrap
[
1024
];
char
adoption_service
[
1024
];
char
stun_server
[
1024
];
char
adoption_token
[
64
];
ks_size_t
adoption_backoff
;
ks_time_t
adoption_next
;
char
adoption_data_local_ip
[
256
];
char
adoption_data_external_ip
[
256
];
char
adoption_data_uname
[
1024
];
char
relay_connector_id
[
256
];
swclt_sess_t
signalwire_session
;
swclt_hmon_t
signalwire_session_monitor
;
sw_state_t
state
;
ks_bool_t
profile_update
;
ks_bool_t
profile_reload
;
ks_bool_t
signalwire_reconnected
;
switch_xml_t
signalwire_profile
;
char
signalwire_profile_md5
[
SWITCH_MD5_DIGEST_STRING_SIZE
];
ks_bool_t
kslog_on
;
switch_mutex_t
*
mutex
;
// general mutex for this mod
char
gateway_ip
[
80
];
char
gateway_port
[
10
];
}
globals
;
static
void
mod_signalwire_kslogger
(
const
char
*
file
,
const
char
*
func
,
int
line
,
int
level
,
const
char
*
fmt
,
...)
{
const
char
*
fp
;
va_list
ap
;
char
buf
[
32768
];
if
(
level
>
debug_level
)
return
;
fp
=
switch_cut_path
(
file
);
va_start
(
ap
,
fmt
);
vsnprintf
(
buf
,
sizeof
(
buf
)
-
1
,
fmt
,
ap
);
buf
[
sizeof
(
buf
)
-
1
]
=
'\0'
;
va_end
(
ap
);
switch_log_printf
(
SWITCH_CHANNEL_ID_LOG
,
fp
,
func
,
line
,
NULL
,
level
,
"%s
\n
"
,
buf
);
}
static
switch_status_t
switch_find_available_port
(
switch_port_t
*
port
,
const
char
*
ip
,
int
type
)
{
switch_status_t
ret
=
SWITCH_STATUS_SUCCESS
;
switch_memory_pool_t
*
pool
=
NULL
;
switch_sockaddr_t
*
addr
=
NULL
;
switch_socket_t
*
sock
=
NULL
;
switch_bool_t
found
=
SWITCH_FALSE
;
if
((
ret
=
switch_core_new_memory_pool
(
&
pool
))
!=
SWITCH_STATUS_SUCCESS
)
{
goto
done
;
}
while
(
!
found
)
{
if
((
ret
=
switch_sockaddr_info_get
(
&
addr
,
ip
,
SWITCH_UNSPEC
,
*
port
,
0
,
pool
))
!=
SWITCH_STATUS_SUCCESS
)
{
goto
done
;
}
if
((
ret
=
switch_socket_create
(
&
sock
,
switch_sockaddr_get_family
(
addr
),
type
,
0
,
pool
))
!=
SWITCH_STATUS_SUCCESS
)
{
goto
done
;
}
if
(
!
(
found
=
(
switch_socket_bind
(
sock
,
addr
)
==
SWITCH_STATUS_SUCCESS
)))
{
*
port
=
*
port
+
1
;
}
switch_socket_close
(
sock
);
}
done:
if
(
pool
)
switch_core_destroy_memory_pool
(
&
pool
);
return
ret
;
}
struct
response_data
{
char
*
data
;
size_t
size
;
};
static
size_t
response_data_handler
(
void
*
contents
,
size_t
size
,
size_t
nmemb
,
void
*
userp
)
{
size_t
received
=
size
*
nmemb
;
struct
response_data
*
rd
=
(
struct
response_data
*
)
userp
;
if
(
!
rd
->
data
)
rd
->
data
=
ks_pool_alloc
(
NULL
,
received
+
1
);
else
rd
->
data
=
ks_pool_resize
(
rd
->
data
,
rd
->
size
+
received
+
1
);
memcpy
(
rd
->
data
+
rd
->
size
,
contents
,
received
);
rd
->
size
+=
received
;
rd
->
data
[
rd
->
size
]
=
0
;
return
received
;
}
static
void
save_sip_config
(
const
char
*
config
)
{
char
confpath
[
1024
];
FILE
*
fp
=
NULL
;
switch_snprintf
(
confpath
,
sizeof
(
confpath
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"signalwire-conf.dat"
);
fp
=
fopen
(
confpath
,
"w"
);
if
(
!
fp
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to open %s to save SignalWire SIP configuration
\n
"
,
confpath
);
return
;
}
fputs
(
config
,
fp
);
fclose
(
fp
);
}
static
void
load_sip_config
(
void
)
{
char
confpath
[
1024
];
char
data
[
32767
]
=
{
0
};
FILE
*
fp
=
NULL
;
switch_snprintf
(
confpath
,
sizeof
(
confpath
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"signalwire-conf.dat"
);
if
(
!
(
fp
=
fopen
(
confpath
,
"r"
)))
return
;
if
(
!
fread
(
data
,
1
,
sizeof
(
data
),
fp
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to read SignalWire SIP configuration from %s
\n
"
,
confpath
);
}
fclose
(
fp
);
if
(
!
zstr_buf
(
data
))
{
switch_md5_string
(
globals
.
signalwire_profile_md5
,
(
void
*
)
data
,
strlen
(
data
));
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"saved profile MD5 =
\"
%s
\"\n
"
,
globals
.
signalwire_profile_md5
);
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"saved profile =
\"
%s
\"\n
"
,
(
char
*
)
data
);
globals
.
signalwire_profile
=
switch_xml_parse_str_dynamic
((
char
*
)
data
,
SWITCH_TRUE
);
}
}
static
ks_status_t
load_credentials_from_json
(
ks_json_t
*
json
)
{
ks_status_t
status
=
KS_STATUS_SUCCESS
;
ks_json_t
*
authentication
=
NULL
;
const
char
*
authentication_str
=
NULL
;
const
char
*
bootstrap
=
NULL
;
const
char
*
relay_connector_id
=
NULL
;
if
((
bootstrap
=
ks_json_get_object_cstr
(
json
,
"bootstrap"
))
==
NULL
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Unable to connect to SignalWire: missing bootstrap URL
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
if
((
relay_connector_id
=
ks_json_get_object_cstr
(
json
,
"relay_connector_id"
))
==
NULL
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Unable to connect to SignalWire: missing relay_connector_id
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
if
((
authentication
=
ks_json_get_object_item
(
json
,
"authentication"
))
==
NULL
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Unable to connect to SignalWire: missing authentication
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
// update the internal connection target, which is normally assigned in swclt_sess_create()
if
(
swclt_sess_target_set
(
globals
.
signalwire_session
,
bootstrap
)
!=
KS_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to connect to SignalWire at %s
\n
"
,
bootstrap
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
// update the relay_connector_id passed to profile configuration
strncpy
(
globals
.
relay_connector_id
,
relay_connector_id
,
sizeof
(
globals
.
relay_connector_id
)
-
1
);
strncpy
(
globals
.
blade_bootstrap
,
bootstrap
,
sizeof
(
globals
.
blade_bootstrap
)
-
1
);
// got adopted, update the client config authentication
authentication_str
=
ks_json_pprint_unformatted
(
NULL
,
authentication
);
swclt_config_set_authentication
(
globals
.
config
,
authentication_str
);
ks_pool_free
(
&
authentication_str
);
done:
return
status
;
}
static
ks_status_t
mod_signalwire_adoption_post
(
void
)
{
ks_status_t
status
=
KS_STATUS_SUCCESS
;
switch_memory_pool_t
*
pool
=
NULL
;
switch_CURL
*
curl
=
NULL
;
switch_curl_slist_t
*
headers
=
NULL
;
char
url
[
1024
];
char
errbuf
[
CURL_ERROR_SIZE
];
CURLcode
res
;
long
rescode
;
ks_json_t
*
json
=
ks_json_create_object
();
struct
response_data
rd
=
{
0
};
char
*
jsonstr
=
NULL
;
// Determine and cache adoption data values that are heavier to figure out
if
(
!
globals
.
adoption_data_local_ip
[
0
])
{
switch_find_local_ip
(
globals
.
adoption_data_local_ip
,
sizeof
(
globals
.
adoption_data_local_ip
),
NULL
,
AF_INET
);
}
if
(
!
globals
.
adoption_data_external_ip
[
0
])
{
switch_port_t
local_port
=
6050
;
char
*
error
=
NULL
;
char
*
external_ip
;
switch_port_t
external_port
;
if
(
switch_core_new_memory_pool
(
&
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"SignalWire adoption failed: could not allocate memory pool
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
if
(
switch_find_available_port
(
&
local_port
,
globals
.
adoption_data_local_ip
,
SOCK_STREAM
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire adoption failed: could not get available local port
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
external_ip
=
globals
.
adoption_data_local_ip
;
external_port
=
local_port
;
if
(
switch_stun_lookup
(
&
external_ip
,
&
external_port
,
globals
.
stun_server
,
SWITCH_STUN_DEFAULT_PORT
,
&
error
,
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire adoption failed: stun [%s] lookup error: %s
\n
"
,
globals
.
stun_server
,
error
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
strncpy
(
globals
.
adoption_data_external_ip
,
external_ip
,
sizeof
(
globals
.
adoption_data_external_ip
));
}
if
(
!
globals
.
adoption_data_uname
[
0
])
{
#ifndef WIN32
struct
utsname
buf
;
if
(
uname
(
&
buf
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire adoption failed: could not get uname
\n
"
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
switch_snprintf
(
globals
.
adoption_data_uname
,
sizeof
(
globals
.
adoption_data_uname
),
"%s %s %s %s %s"
,
buf
.
sysname
,
buf
.
nodename
,
buf
.
release
,
buf
.
version
,
buf
.
machine
);
#else
// @todo set globals.adoption_data_uname from GetVersion Win32API
#endif
}
ks_json_add_string_to_object
(
json
,
"client_uuid"
,
globals
.
adoption_token
);
ks_json_add_string_to_object
(
json
,
"hostname"
,
switch_core_get_hostname
());
ks_json_add_string_to_object
(
json
,
"ip"
,
globals
.
adoption_data_local_ip
);
ks_json_add_string_to_object
(
json
,
"ext_ip"
,
globals
.
adoption_data_external_ip
);
ks_json_add_string_to_object
(
json
,
"version"
,
switch_version_full
());
ks_json_add_string_to_object
(
json
,
"uname"
,
globals
.
adoption_data_uname
);
jsonstr
=
ks_json_print_unformatted
(
json
);
ks_json_delete
(
&
json
);
switch_snprintf
(
url
,
sizeof
(
url
),
"%s/%s"
,
globals
.
adoption_service
,
globals
.
adoption_token
);
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG10
,
"Checking %s for SignalWire adoption of this FreeSWITCH
\n
"
,
url
);
curl
=
switch_curl_easy_init
();
headers
=
switch_curl_slist_append
(
headers
,
"Accept: application/json"
);
headers
=
switch_curl_slist_append
(
headers
,
"Accept-Charset: utf-8"
);
headers
=
switch_curl_slist_append
(
headers
,
"Content-Type: application/json"
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_CONNECTTIMEOUT
,
5
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_TIMEOUT
,
5
);
if
(
!
strncasecmp
(
url
,
"https"
,
5
))
{
switch_curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYPEER
,
globals
.
ssl_verify
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_SSL_VERIFYHOST
,
globals
.
ssl_verify
);
}
switch_curl_easy_setopt
(
curl
,
CURLOPT_URL
,
url
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_HTTPHEADER
,
headers
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_USERAGENT
,
"mod_signalwire/1"
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_POSTFIELDS
,
jsonstr
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_ERRORBUFFER
,
errbuf
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_WRITEDATA
,
(
void
*
)
&
rd
);
switch_curl_easy_setopt
(
curl
,
CURLOPT_WRITEFUNCTION
,
response_data_handler
);
if
((
res
=
switch_curl_easy_perform
(
curl
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Curl Result %d, Error: %s
\n
"
,
res
,
errbuf
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
switch_curl_easy_getinfo
(
curl
,
CURLINFO_RESPONSE_CODE
,
&
rescode
);
if
(
rescode
==
404
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_NOTICE
,
"Go to https://signalwire.com to set up your Connector now! Enter connection token %s
\n
"
,
globals
.
adoption_token
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
if
(
rescode
!=
200
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire adoption failed with HTTP code %ld, %s
\n
"
,
rescode
,
rd
.
data
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
json
=
ks_json_parse
(
rd
.
data
);
if
(
!
json
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Received bad SignalWire adoption response
\n
%s
\n
"
,
rd
.
data
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
if
((
status
=
load_credentials_from_json
(
json
))
!=
KS_STATUS_SUCCESS
)
{
goto
done
;
}
ks_json_delete
(
&
json
);
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire adoption of this FreeSWITCH completed
\n
"
);
// write out the data to save it for reloading in the future
{
char
authpath
[
1024
];
FILE
*
fp
=
NULL
;
switch_snprintf
(
authpath
,
sizeof
(
authpath
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"adoption-auth.dat"
);
fp
=
fopen
(
authpath
,
"w"
);
if
(
!
fp
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to open %s to save SignalWire creds
\n
"
,
authpath
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
fputs
(
rd
.
data
,
fp
);
fclose
(
fp
);
}
globals
.
state
=
SW_STATE_OFFLINE
;
swclt_sess_connect
(
globals
.
signalwire_session
);
done:
if
(
rd
.
data
)
ks_pool_free
(
&
rd
.
data
);
if
(
jsonstr
)
ks_json_free_ex
((
void
**
)
&
jsonstr
);
if
(
json
)
ks_json_delete
(
&
json
);
if
(
curl
)
{
curl_easy_cleanup
(
curl
);
if
(
headers
)
curl_slist_free_all
(
headers
);
}
if
(
pool
)
switch_core_destroy_memory_pool
(
&
pool
);
return
status
;
}
#define SIGNALWIRE_SYNTAX "token | adoption | adopted | reload | update | debug <level> | kslog <on|off|logfile e.g. /tmp/ks.log>"
SWITCH_STANDARD_API
(
mod_signalwire_api_function
)
{
int
argc
=
0
;
char
*
argv
[
2
]
=
{
0
};
char
*
buf
=
NULL
;
if
(
!
cmd
||
!
(
buf
=
strdup
(
cmd
)))
{
stream
->
write_function
(
stream
,
"-USAGE: signalwire %s
\n
"
,
SIGNALWIRE_SYNTAX
);
return
SWITCH_STATUS_SUCCESS
;
}
if
((
argc
=
switch_separate_string
(
buf
,
' '
,
argv
,
(
sizeof
(
argv
)
/
sizeof
(
argv
[
0
])))))
{
if
(
!
strcmp
(
argv
[
0
],
"token"
))
{
if
(
globals
.
adoption_token
[
0
])
{
stream
->
write_function
(
stream
,
" _____ _ ___ ___
\n
"
" / ___/(_)___ _____ ____ _/ / | / (_)_______
\n
"
"
\\
__
\\
/ / __ `/ __
\\
/ __ `/ /| | /| / / / ___/ _
\\\n
"
" ___/ / / /_/ / / / / /_/ / / | |/ |/ / / / / __/
\n
"
" /____/_/
\\
__, /_/ /_/
\\
__,_/_/ |__/|__/_/_/
\\
___/
\n
"
" /____/
\n
"
"
\n
/=====================================================================
\\\n
"
"| Connection Token: %s |
\n
"
"
\\
=====================================================================/
\n
"
" Go to https://signalwire.com to set up your Connector now!
\n
"
,
globals
.
adoption_token
);
}
else
{
stream
->
write_function
(
stream
,
"-ERR connection token not available
\n
"
);
}
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"adoption"
))
{
if
(
globals
.
state
==
SW_STATE_ADOPTION
)
{
globals
.
adoption_next
=
ks_time_now
();
stream
->
write_function
(
stream
,
"+OK
\n
"
);
}
else
{
stream
->
write_function
(
stream
,
"-ERR adoption not currently pending
\n
"
);
}
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"adopted"
))
{
stream
->
write_function
(
stream
,
"+OK %s
\n
"
,
globals
.
state
==
SW_STATE_ADOPTION
?
"Not Adopted"
:
"Adopted"
);
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"debug"
))
{
if
(
argv
[
1
])
{
debug_level
=
atoi
(
argv
[
1
]);
}
stream
->
write_function
(
stream
,
"+OK debug %d
\n
"
,
debug_level
);
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"kslog"
))
{
if
(
argv
[
1
])
{
if
(
!
strcmp
(
argv
[
1
],
"on"
))
{
ks_global_set_logger
(
mod_signalwire_kslogger
);
}
else
if
(
!
strcmp
(
argv
[
1
],
"off"
))
{
ks_global_set_logger
(
NULL
);
}
}
stream
->
write_function
(
stream
,
"+OK %s
\n
"
,
argv
[
1
]);
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"reload"
))
{
globals
.
profile_reload
=
KS_TRUE
;
stream
->
write_function
(
stream
,
"+OK
\n
"
);
goto
done
;
}
else
if
(
!
strcmp
(
argv
[
0
],
"update"
))
{
globals
.
profile_update
=
KS_TRUE
;
stream
->
write_function
(
stream
,
"+OK
\n
"
);
goto
done
;
}
}
stream
->
write_function
(
stream
,
"-USAGE: signalwire %s
\n
"
,
SIGNALWIRE_SYNTAX
);
done
:
switch_safe_free
(
buf
);
return
SWITCH_STATUS_SUCCESS
;
}
static
void
mod_signalwire_session_state_handler
(
swclt_sess_t
sess
,
swclt_hstate_change_t
*
state_change_info
,
const
char
*
cb_data
)
{
SWCLT_HSTATE
new_state
=
state_change_info
->
new_state
;
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire Session State Change: %s
\n
"
,
swclt_hstate_describe_change
(
state_change_info
));
if
(
new_state
==
SWCLT_HSTATE_ONLINE
)
{
// Connected with NEW or RESTORED session
globals
.
signalwire_reconnected
=
KS_TRUE
;
}
else
if
(
new_state
==
SWCLT_HSTATE_OFFLINE
)
{
// Disconnected
}
}
static
void
__on_provisioning_events
(
swclt_sess_t
sess
,
blade_broadcast_rqu_t
*
rqu
,
void
*
cb_data
)
{
if
(
!
strcmp
(
rqu
->
event
,
"update"
))
{
globals
.
profile_update
=
KS_TRUE
;
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire SIP profile update requested
\n
"
);
}
}
static
switch_xml_t
xml_config_handler
(
const
char
*
section
,
const
char
*
tag_name
,
const
char
*
key_name
,
const
char
*
key_value
,
switch_event_t
*
params
,
void
*
user_data
)
{
char
*
profileName
=
NULL
;
char
*
reconfigValue
=
NULL
;
switch_xml_t
signalwire_profile_dup
=
NULL
;
if
(
!
section
||
strcmp
(
section
,
"configuration"
))
return
NULL
;
if
(
!
key_name
||
strcmp
(
key_name
,
"name"
))
return
NULL
;
if
(
!
key_value
||
strcmp
(
key_value
,
"sofia.conf"
))
return
NULL
;
if
(
!
params
)
return
NULL
;
profileName
=
switch_event_get_header
(
params
,
"profile"
);
if
(
!
profileName
||
strcmp
(
profileName
,
"signalwire"
))
return
NULL
;
reconfigValue
=
switch_event_get_header
(
params
,
"reconfig"
);
if
(
!
reconfigValue
||
strcmp
(
reconfigValue
,
"true"
))
return
NULL
;
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Received XML lookup for SignalWire SIP profile
\n
"
);
if
(
globals
.
signalwire_profile
)
{
signalwire_profile_dup
=
switch_xml_dup
(
globals
.
signalwire_profile
);
}
return
signalwire_profile_dup
;
}
static
switch_status_t
mod_signalwire_load_or_generate_token
(
void
)
{
switch_status_t
status
=
SWITCH_STATUS_SUCCESS
;
char
tokenpath
[
1024
];
switch_snprintf
(
tokenpath
,
sizeof
(
tokenpath
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"adoption-token.dat"
);
if
(
switch_file_exists
(
tokenpath
,
NULL
)
!=
SWITCH_STATUS_SUCCESS
)
{
// generate first time uuid
ks_uuid_t
uuid
;
const
char
*
token
;
FILE
*
fp
=
fopen
(
tokenpath
,
"w"
);
if
(
!
fp
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to open %s to save SignalWire connection token
\n
"
,
tokenpath
);
status
=
SWITCH_STATUS_TERM
;
goto
done
;
}
ks_uuid
(
&
uuid
);
token
=
ks_uuid_str
(
NULL
,
&
uuid
);
fputs
(
token
,
fp
);
fclose
(
fp
);
strncpy
(
globals
.
adoption_token
,
token
,
sizeof
(
globals
.
adoption_token
)
-
1
);
ks_pool_free
(
&
token
);
}
else
{
char
token
[
64
];
FILE
*
fp
=
fopen
(
tokenpath
,
"r"
);
if
(
!
fp
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to open %s to read SignalWire connection token
\n
"
,
tokenpath
);
status
=
SWITCH_STATUS_TERM
;
goto
done
;
}
if
(
!
fgets
(
token
,
sizeof
(
token
),
fp
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to read SignalWire connection token from %s
\n
"
,
tokenpath
);
fclose
(
fp
);
status
=
SWITCH_STATUS_TERM
;
goto
done
;
}
fclose
(
fp
);
// trim newline markers in case they exist, only want the token
for
(
size_t
len
=
strlen
(
token
);
len
>
0
&&
(
token
[
len
-
1
]
==
'\r'
||
token
[
len
-
1
]
==
'\n'
);
--
len
)
{
token
[
len
-
1
]
=
'\0'
;
}
strncpy
(
globals
.
adoption_token
,
token
,
sizeof
(
globals
.
adoption_token
)
-
1
);
}
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"
\n
/=====================================================================
\\\n
"
"| Connection Token: %s |
\n
"
"
\\
=====================================================================/
\n
"
" Go to https://signalwire.com to set up your Connector now!
\n
"
,
globals
.
adoption_token
);
done
:
return
status
;
}
static
switch_status_t
load_config
()
{
char
*
cf
=
"signalwire.conf"
;
switch_xml_t
cfg
,
xml
;
const
char
*
data
;
globals
.
ssl_verify
=
1
;
switch_set_string
(
globals
.
blade_bootstrap
,
"edge.<space>.signalwire.com/api/relay/wss"
);
switch_set_string
(
globals
.
adoption_service
,
"https://adopt.signalwire.com/adoption"
);
switch_set_string
(
globals
.
stun_server
,
"stun.freeswitch.org"
);
if
(
!
(
xml
=
switch_xml_open_cfg
(
cf
,
&
cfg
,
NULL
)))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG1
,
"open of %s failed
\n
"
,
cf
);
// don't need the config
}
else
{
switch_xml_t
settings
,
param
,
tmp
;
if
((
settings
=
switch_xml_child
(
cfg
,
"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
,
"kslog"
)
&&
!
ks_zstr
(
val
))
{
if
(
!
strcmp
(
val
,
"off"
))
{
globals
.
kslog_on
=
KS_FALSE
;
}
else
if
(
!
strcmp
(
val
,
"on"
))
{
globals
.
kslog_on
=
KS_TRUE
;
}
}
else
if
(
!
strcasecmp
(
var
,
"blade-bootstrap"
)
&&
!
ks_zstr
(
val
))
{
switch_set_string
(
globals
.
blade_bootstrap
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"adoption-service"
)
&&
!
ks_zstr
(
val
))
{
switch_set_string
(
globals
.
adoption_service
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"stun-server"
)
&&
!
ks_zstr
(
val
))
{
switch_set_string
(
globals
.
stun_server
,
val
);
}
else
if
(
!
strcasecmp
(
var
,
"ssl-verify"
))
{
globals
.
ssl_verify
=
switch_true
(
val
)
?
1
:
0
;
}
}
if
((
tmp
=
switch_xml_child
(
settings
,
"authentication"
)))
{
const
char
*
txt
=
switch_xml_txt
(
tmp
);
if
(
!
ks_zstr
(
txt
))
{
swclt_config_set_authentication
(
globals
.
config
,
txt
);
}
}
}
switch_xml_free
(
xml
);
}
if
((
data
=
getenv
(
"SW_BLADE_BOOTSTRAP"
)))
{
switch_set_string
(
globals
.
blade_bootstrap
,
data
);
}
if
((
data
=
getenv
(
"SW_ADOPTION_SERVICE"
)))
{
strncpy
(
globals
.
adoption_service
,
data
,
sizeof
(
globals
.
adoption_service
));
}
swclt_config_load_from_env
(
globals
.
config
);
return
SWITCH_STATUS_SUCCESS
;
}
static
ks_status_t
load_credentials
(
void
)
{
ks_status_t
status
=
KS_STATUS_SUCCESS
;
char
authpath
[
1024
];
char
data
[
2048
];
FILE
*
fp
=
NULL
;
ks_json_t
*
json
=
NULL
;
switch_snprintf
(
authpath
,
sizeof
(
authpath
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"adoption-auth.dat"
);
if
(
!
(
fp
=
fopen
(
authpath
,
"r"
)))
goto
done
;
if
(
!
fgets
(
data
,
sizeof
(
data
),
fp
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to read SignalWire authentication data from %s
\n
"
,
authpath
);
fclose
(
fp
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
fclose
(
fp
);
json
=
ks_json_parse
(
data
);
if
(
!
json
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Unable to parse SignalWire authentication data from %s
\n
"
,
authpath
);
status
=
KS_STATUS_FAIL
;
goto
done
;
}
status
=
load_credentials_from_json
(
json
);
ks_json_delete
(
&
json
);
done
:
return
status
;
}
static
void
mod_signalwire_session_auth_failed_handler
(
swclt_sess_t
sess
)
{
char
path
[
1024
];
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire authentication failed
\n
"
);
switch_snprintf
(
path
,
sizeof
(
path
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"adoption-auth.dat"
);
unlink
(
path
);
switch_snprintf
(
path
,
sizeof
(
path
),
"%s%s%s"
,
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_PATH_SEPARATOR
,
"signalwire-conf.dat"
);
unlink
(
path
);
globals
.
restarting
=
KS_TRUE
;
globals
.
adoption_backoff
=
0
;
globals
.
adoption_next
=
0
;
globals
.
state
=
SW_STATE_ADOPTION
;
}
/* Dialplan INTERFACE */
SWITCH_STANDARD_DIALPLAN
(
dialplan_hunt
)
{
switch_caller_extension_t
*
extension
=
NULL
;
switch_channel_t
*
channel
=
switch_core_session_get_channel
(
session
);
const
char
*
network_ip
=
switch_channel_get_variable
(
channel
,
"sip_network_ip"
);
const
char
*
network_port
=
switch_channel_get_variable
(
channel
,
"sip_network_port"
);
if
(
!
caller_profile
)
{
if
(
!
(
caller_profile
=
switch_channel_get_caller_profile
(
channel
)))
{
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_ERROR
,
"Error obtaining caller profile!
\n
"
);
goto
done
;
}
}
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_INFO
,
"Processing %s <%s>->%s in context %s
\n
"
,
caller_profile
->
caller_id_name
,
caller_profile
->
caller_id_number
,
caller_profile
->
destination_number
,
caller_profile
->
context
);
if
((
extension
=
switch_caller_extension_new
(
session
,
"signalwire"
,
caller_profile
->
destination_number
))
==
NULL
)
{
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_CRIT
,
"Memory Error!
\n
"
);
goto
done
;
}
switch_log_printf
(
SWITCH_CHANNEL_SESSION_LOG
(
session
),
SWITCH_LOG_DEBUG
,
"call from %s:%s
\n
"
,
network_ip
,
network_port
);
switch_mutex_lock
(
globals
.
mutex
);
if
(
network_ip
&&
!
zstr_buf
(
globals
.
gateway_ip
)
&&
!
strcmp
(
globals
.
gateway_ip
,
network_ip
))
{
// good to go
char
transfer_to
[
1024
];
switch_snprintf
(
transfer_to
,
sizeof
(
transfer_to
),
"%s %s %s"
,
caller_profile
->
destination_number
,
"XML"
,
caller_profile
->
context
);
switch_caller_extension_add_application
(
session
,
extension
,
"transfer"
,
transfer_to
);
}
else
{
switch_caller_extension_add_application
(
session
,
extension
,
"respond"
,
"500"
);
}
switch_mutex_unlock
(
globals
.
mutex
);
done
:
return
extension
;
}
/**
* Module load or unload callback from core
* @param event the event
*/
static
void
on_module_load_unload
(
switch_event_t
*
event
)
{
const
char
*
type
=
switch_event_get_header
(
event
,
"type"
);
const
char
*
name
=
switch_event_get_header
(
event
,
"name"
);
if
(
!
zstr
(
type
)
&&
!
zstr
(
name
)
&&
!
strcmp
(
type
,
"endpoint"
)
&&
!
strcmp
(
name
,
"sofia"
))
{
globals
.
profile_reload
=
KS_TRUE
;
}
}
/**
* Sofia sofia::gateway_state change callback
* @param event the event
*/
static
void
on_sofia_gateway_state
(
switch_event_t
*
event
)
{
const
char
*
ip
=
switch_event_get_header
(
event
,
"Register-Network-IP"
);
const
char
*
port
=
switch_event_get_header
(
event
,
"Register-Network-Port"
);
const
char
*
state
=
switch_event_get_header
(
event
,
"State"
);
const
char
*
gateway
=
switch_event_get_header
(
event
,
"Gateway"
);
if
(
!
ip
||
!
port
||
!
state
||
!
gateway
)
{
return
;
}
if
(
!
strcmp
(
gateway
,
"signalwire"
))
{
switch_mutex_lock
(
globals
.
mutex
);
if
(
!
strcmp
(
state
,
"REGED"
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"SignalWire SIP Gateway registered to %s:%s
\n
"
,
ip
,
port
);
switch_set_string
(
globals
.
gateway_ip
,
ip
);
switch_set_string
(
globals
.
gateway_port
,
port
);
}
else
if
(
!
strcmp
(
state
,
"NOREG"
))
{
globals
.
gateway_ip
[
0
]
=
'\0'
;
globals
.
gateway_port
[
0
]
=
'\0'
;
}
switch_mutex_unlock
(
globals
.
mutex
);
}
}
/* Macro expands to: switch_status_t mod_signalwire_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
SWITCH_MODULE_LOAD_FUNCTION
(
mod_signalwire_load
)
{
switch_api_interface_t
*
api_interface
=
NULL
;
switch_dialplan_interface_t
*
dialplan_interface
;
const
char
*
kslog_env
=
NULL
;
switch_status_t
status
=
SWITCH_STATUS_SUCCESS
;
memset
(
&
globals
,
0
,
sizeof
(
globals
));
kslog_env
=
getenv
(
"KSLOG"
);
if
(
kslog_env
&&
kslog_env
[
0
]
&&
kslog_env
[
0
]
!=
'0'
)
globals
.
kslog_on
=
KS_TRUE
;
/* connect my internal structure to the blank pointer passed to me */
*
module_interface
=
switch_loadable_module_create_module_interface
(
pool
,
modname
);
ks_global_set_logger
(
mod_signalwire_kslogger
);
SWITCH_ADD_API
(
api_interface
,
"signalwire"
,
"SignalWire API"
,
mod_signalwire_api_function
,
SIGNALWIRE_SYNTAX
);
switch_console_set_complete
(
"add signalwire debug"
);
switch_console_set_complete
(
"add signalwire debug 1"
);
switch_console_set_complete
(
"add signalwire debug 2"
);
switch_console_set_complete
(
"add signalwire debug 3"
);
switch_console_set_complete
(
"add signalwire debug 4"
);
switch_console_set_complete
(
"add signalwire debug 5"
);
switch_console_set_complete
(
"add signalwire debug 6"
);
switch_console_set_complete
(
"add signalwire debug 7"
);
switch_console_set_complete
(
"add signalwire kslog"
);
switch_console_set_complete
(
"add signalwire kslog on"
);
switch_console_set_complete
(
"add signalwire kslog off"
);
switch_console_set_complete
(
"add signalwire token"
);
switch_console_set_complete
(
"add signalwire adoption"
);
switch_console_set_complete
(
"add signalwire adopted"
);
switch_console_set_complete
(
"add signalwire update"
);
switch_console_set_complete
(
"add signalwire reload"
);
switch_xml_bind_search_function
(
xml_config_handler
,
SWITCH_XML_SECTION_CONFIG
,
NULL
);
ks_ssl_init_skip
(
KS_TRUE
);
swclt_init
(
KS_LOG_LEVEL_DEBUG
);
if
(
globals
.
kslog_on
==
KS_FALSE
)
{
ks_global_set_logger
(
NULL
);
}
else
{
ks_global_set_logger
(
mod_signalwire_kslogger
);
}
// Configuration
swclt_config_create
(
&
globals
.
config
);
load_config
();
switch_mutex_init
(
&
globals
.
mutex
,
SWITCH_MUTEX_NESTED
,
pool
);
switch_event_bind
(
"mod_signalwire"
,
SWITCH_EVENT_MODULE_LOAD
,
NULL
,
on_module_load_unload
,
NULL
);
switch_event_bind
(
"mod_signalwire"
,
SWITCH_EVENT_MODULE_UNLOAD
,
NULL
,
on_module_load_unload
,
NULL
);
switch_event_bind
(
"mod_signalwire"
,
SWITCH_EVENT_CUSTOM
,
"sofia::gateway_state"
,
on_sofia_gateway_state
,
NULL
);
SWITCH_ADD_DIALPLAN
(
dialplan_interface
,
"signalwire"
,
dialplan_hunt
);
// Load credentials if they exist from a prior adoption
load_credentials
();
// SignalWire
swclt_sess_create
(
&
globals
.
signalwire_session
,
globals
.
blade_bootstrap
,
globals
.
config
);
swclt_sess_set_auth_failed_cb
(
globals
.
signalwire_session
,
mod_signalwire_session_auth_failed_handler
);
if
(
!
globals
.
signalwire_session
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"signalwire_session create error
\n
"
);
switch_goto_status
(
SWITCH_STATUS_TERM
,
err
);
}
swclt_hmon_register
(
&
globals
.
signalwire_session_monitor
,
globals
.
signalwire_session
,
mod_signalwire_session_state_handler
,
NULL
);
// @todo register nodestore callbacks here if needed
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CONSOLE
,
"Welcome to
\n
"
" _____ _ ___ ___
\n
"
" / ___/(_)___ _____ ____ _/ / | / (_)_______
\n
"
"
\\
__
\\
/ / __ `/ __
\\
/ __ `/ /| | /| / / / ___/ _
\\\n
"
" ___/ / / /_/ / / / / /_/ / / | |/ |/ / / / / __/
\n
"
" /____/_/
\\
__, /_/ /_/
\\
__,_/_/ |__/|__/_/_/
\\
___/
\n
"
" /____/
\n
"
);
// storage_dir was missing in clean install
switch_dir_make_recursive
(
SWITCH_GLOBAL_dirs
.
storage_dir
,
SWITCH_DEFAULT_DIR_PERMS
,
pool
);
if
((
status
=
mod_signalwire_load_or_generate_token
())
!=
SWITCH_STATUS_SUCCESS
)
{
goto
err
;
}
if
(
swclt_sess_has_authentication
(
globals
.
signalwire_session
))
{
// Load cached profile if we already have one. We'll still connect to SignalWire and
// fetch a new profile in the background.
load_sip_config
();
if
(
globals
.
signalwire_profile
)
{
globals
.
state
=
SW_STATE_START_PROFILE
;
}
else
{
globals
.
state
=
SW_STATE_OFFLINE
;
}
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CONSOLE
,
"Connecting to SignalWire
\n
"
);
swclt_sess_connect
(
globals
.
signalwire_session
);
}
else
{
globals
.
state
=
SW_STATE_ADOPTION
;
}
goto
done
;
err
:
if
(
globals
.
signalwire_session
)
ks_handle_destroy
(
&
globals
.
signalwire_session
);
swclt_config_destroy
(
&
globals
.
config
);
ks_global_set_logger
(
NULL
);
done
:
return
status
;
}
/*
Called when the system shuts down
Macro expands to: switch_status_t mod_signalwire_shutdown() */
SWITCH_MODULE_SHUTDOWN_FUNCTION
(
mod_signalwire_shutdown
)
{
/* Cleanup dynamically allocated config settings */
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Disconnecting from SignalWire
\n
"
);
switch_event_unbind_callback
(
on_module_load_unload
);
switch_event_unbind_callback
(
on_sofia_gateway_state
);
// stop things that might try to use blade or kafka while they are shutting down
globals
.
shutdown
=
KS_TRUE
;
swclt_sess_disconnect
(
globals
.
signalwire_session
);
while
(
swclt_hstate_current_get
(
globals
.
signalwire_session
)
==
SWCLT_HSTATE_ONLINE
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Sleeping for pending disconnect
\n
"
);
ks_sleep_ms
(
1000
);
}
//signalwire_dialplan_shutdown();
// @todo signalwire profile unbinding and unloading
switch_xml_unbind_search_function_ptr
(
xml_config_handler
);
// kill signalwire, so nothing more can come into the system
ks_handle_destroy
(
&
globals
.
signalwire_session
);
// cleanup config
swclt_config_destroy
(
&
globals
.
config
);
// shutdown libblade (but not libks?)
swclt_shutdown
();
return
SWITCH_STATUS_SUCCESS
;
}
static
void
mod_signalwire_state_adoption
(
void
)
{
// keep trying to check adoption token for authentication
if
(
ks_time_now
()
>=
globals
.
adoption_next
)
{
// Use a very very simple backoff algorithm, every time we try, backoff another minute
// so that after first try we wait 1 minute, after next try we wait 2 minutes, at third
// try we are waiting 3 minutes, upto a max backoff of 15 minutes between adoption checks
if
(
globals
.
adoption_backoff
<
15
)
globals
.
adoption_backoff
++
;
globals
.
adoption_next
=
ks_time_now
()
+
(
globals
.
adoption_backoff
*
60
*
KS_USEC_PER_SEC
);
if
(
mod_signalwire_adoption_post
()
!=
KS_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Next SignalWire adoption check in %"
SWITCH_SIZE_T_FMT
" minutes
\n
"
,
globals
.
adoption_backoff
);
}
}
if
(
globals
.
signalwire_reconnected
)
{
// OK to continue as is
globals
.
signalwire_reconnected
=
KS_FALSE
;
}
}
static
void
mod_signalwire_state_offline
(
void
)
{
if
(
globals
.
signalwire_reconnected
)
{
globals
.
signalwire_reconnected
=
KS_FALSE
;
globals
.
state
=
SW_STATE_ONLINE
;
}
}
static
void
mod_signalwire_state_online
(
void
)
{
globals
.
signalwire_reconnected
=
KS_FALSE
;
if
(
!
swclt_sess_provisioning_setup
(
globals
.
signalwire_session
,
__on_provisioning_events
,
NULL
))
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Connected to SignalWire
\n
"
);
globals
.
state
=
SW_STATE_CONFIGURE
;
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Failed to connect to SignalWire
\n
"
);
ks_sleep_ms
(
4000
);
globals
.
state
=
SW_STATE_OFFLINE
;
globals
.
restarting
=
KS_TRUE
;
}
}
static
void
mod_signalwire_state_configure
(
void
)
{
switch_memory_pool_t
*
pool
=
NULL
;
char
local_ip
[
256
];
switch_port_t
local_port
=
6050
;
char
local_endpoint
[
256
];
char
*
external_ip
;
switch_port_t
external_port
;
char
external_endpoint
[
256
];
char
*
error
=
NULL
;
swclt_cmd_t
cmd
;
if
(
globals
.
signalwire_reconnected
)
{
globals
.
signalwire_reconnected
=
KS_FALSE
;
globals
.
state
=
SW_STATE_ONLINE
;
}
// already restarting/updating...
globals
.
profile_reload
=
KS_FALSE
;
globals
.
profile_update
=
KS_FALSE
;
if
(
switch_core_new_memory_pool
(
&
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_CRIT
,
"SignalWire configure failed: could not allocate memory pool
\n
"
);
goto
done
;
}
switch_find_local_ip
(
local_ip
,
sizeof
(
local_ip
),
NULL
,
AF_INET
);
if
(
switch_find_available_port
(
&
local_port
,
local_ip
,
SOCK_STREAM
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire configure failed: could not get available local port
\n
"
);
ks_sleep_ms
(
4000
);
goto
done
;
}
snprintf
(
local_endpoint
,
sizeof
(
local_endpoint
),
"%s:%u"
,
local_ip
,
local_port
);
external_ip
=
local_ip
;
external_port
=
local_port
;
if
(
switch_stun_lookup
(
&
external_ip
,
&
external_port
,
globals
.
stun_server
,
SWITCH_STUN_DEFAULT_PORT
,
&
error
,
pool
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"SignalWire configure failed: stun [%s] lookup error: %s
\n
"
,
globals
.
stun_server
,
error
);
ks_sleep_ms
(
4000
);
goto
done
;
}
snprintf
(
external_endpoint
,
sizeof
(
external_endpoint
),
"%s:%u"
,
external_ip
,
external_port
);
if
(
!
swclt_sess_provisioning_configure
(
globals
.
signalwire_session
,
"freeswitch"
,
local_endpoint
,
external_endpoint
,
globals
.
relay_connector_id
,
&
cmd
))
{
SWCLT_CMD_TYPE
cmd_type
;
swclt_cmd_type
(
cmd
,
&
cmd_type
);
if
(
cmd_type
==
SWCLT_CMD_TYPE_RESULT
)
{
const
ks_json_t
*
result
;
signalwire_provisioning_configure_response_t
*
configure_res
;
swclt_cmd_result
(
cmd
,
&
result
);
result
=
ks_json_get_object_item
(
result
,
"result"
);
if
(
!
SIGNALWIRE_PROVISIONING_CONFIGURE_RESPONSE_PARSE
(
ks_handle_pool
(
cmd
),
result
,
&
configure_res
))
{
const
ks_json_t
*
configuration
=
configure_res
->
configuration
;
const
char
*
configuration_profile
=
ks_json_get_object_cstr
(
configuration
,
"profile"
);
if
(
globals
.
signalwire_profile
)
{
switch_xml_free
(
globals
.
signalwire_profile
);
globals
.
signalwire_profile
=
NULL
;
}
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"
\"
%s
\"\n
"
,
configuration_profile
);
globals
.
signalwire_profile
=
switch_xml_parse_str_dynamic
((
char
*
)
configuration_profile
,
SWITCH_TRUE
);
if
(
!
globals
.
signalwire_profile
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_ERROR
,
"Failed to parse configuration profile
\n
"
);
}
else
{
char
digest
[
SWITCH_MD5_DIGEST_STRING_SIZE
]
=
{
0
};
switch_md5_string
(
digest
,
(
void
*
)
configuration_profile
,
strlen
(
configuration_profile
));
save_sip_config
(
configuration_profile
);
if
(
!
signalwire_gateway_exists
()
||
zstr_buf
(
globals
.
signalwire_profile_md5
)
||
strcmp
(
globals
.
signalwire_profile_md5
,
digest
))
{
// not registered or new profile - update md5 and load it
strcpy
(
globals
.
signalwire_profile_md5
,
digest
);
globals
.
state
=
SW_STATE_START_PROFILE
;
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"profile MD5 =
\"
%s
\"\n
"
,
globals
.
signalwire_profile_md5
);
}
else
{
// already registered
globals
.
state
=
SW_STATE_READY
;
}
}
}
}
}
ks_handle_destroy
(
&
cmd
);
if
(
globals
.
state
==
SW_STATE_CONFIGURE
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Failed to receive valid configuration from SignalWire
\n
"
);
ks_sleep_ms
(
4000
);
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Received configuration from SignalWire
\n
"
);
}
done
:
if
(
pool
)
switch_core_destroy_memory_pool
(
&
pool
);
}
static
int
signalwire_gateway_exists
(
void
)
{
int
exists
=
0
;
switch_stream_handle_t
stream
=
{
0
};
SWITCH_STANDARD_STREAM
(
stream
);
if
(
switch_api_execute
(
"sofia"
,
"profile signalwire gwlist"
,
NULL
,
&
stream
)
==
SWITCH_STATUS_SUCCESS
&&
stream
.
data
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"gwlist =
\"
%s
\"\n
"
,
(
char
*
)
stream
.
data
);
exists
=
(
strstr
((
char
*
)
stream
.
data
,
"Invalid Profile"
)
==
NULL
)
&&
(
strstr
((
char
*
)
stream
.
data
,
"signalwire"
)
!=
NULL
);
}
switch_safe_free
(
stream
.
data
);
return
exists
;
}
static
int
signalwire_profile_is_started
(
void
)
{
int
started
=
0
;
switch_stream_handle_t
stream
=
{
0
};
SWITCH_STANDARD_STREAM
(
stream
);
if
(
switch_api_execute
(
"sofia"
,
"status profile signalwire"
,
NULL
,
&
stream
)
==
SWITCH_STATUS_SUCCESS
&&
stream
.
data
)
{
started
=
(
strstr
((
char
*
)
stream
.
data
,
"Invalid Profile"
)
==
NULL
)
&&
(
strstr
((
char
*
)
stream
.
data
,
"signalwire"
)
!=
NULL
);
}
switch_safe_free
(
stream
.
data
);
return
started
;
}
static
int
signalwire_profile_rescan
(
void
)
{
int
success
=
0
;
switch_stream_handle_t
stream
=
{
0
};
SWITCH_STANDARD_STREAM
(
stream
);
if
(
switch_api_execute
(
"sofia"
,
"profile signalwire rescan"
,
NULL
,
&
stream
)
==
SWITCH_STATUS_SUCCESS
)
{
success
=
signalwire_profile_is_started
();
}
switch_safe_free
(
stream
.
data
);
return
success
;
}
static
int
signalwire_profile_start
(
void
)
{
int
success
=
0
;
switch_stream_handle_t
stream
=
{
0
};
SWITCH_STANDARD_STREAM
(
stream
);
if
(
switch_api_execute
(
"sofia"
,
"profile signalwire start"
,
NULL
,
&
stream
)
==
SWITCH_STATUS_SUCCESS
)
{
success
=
signalwire_profile_is_started
();
}
switch_safe_free
(
stream
.
data
);
return
success
;
}
static
void
signalwire_profile_killgw
(
void
)
{
switch_stream_handle_t
stream
=
{
0
};
SWITCH_STANDARD_STREAM
(
stream
);
switch_api_execute
(
"sofia"
,
"profile signalwire killgw signalwire"
,
NULL
,
&
stream
);
switch_safe_free
(
stream
.
data
);
}
static
void
mod_signalwire_state_start_profile
(
void
)
{
if
(
globals
.
profile_update
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire SIP profile update initiated
\n
"
);
globals
.
state
=
SW_STATE_CONFIGURE
;
globals
.
profile_update
=
KS_FALSE
;
return
;
}
globals
.
profile_reload
=
KS_FALSE
;
// already here
// ignore SignalWire reconnections until register is attempted
if
(
switch_loadable_module_exists
(
"mod_sofia"
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Waiting for mod_sofia to load
\n
"
);
}
else
if
(
signalwire_profile_is_started
())
{
// kill gateway if already up and rescan the profile
if
(
signalwire_gateway_exists
())
{
signalwire_profile_killgw
();
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"SignalWire SIP gateway killed
\n
"
);
}
if
(
signalwire_profile_rescan
())
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"SignalWire SIP profile rescanned
\n
"
);
globals
.
state
=
SW_STATE_REGISTER
;
}
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Starting SignalWire SIP profile
\n
"
);
signalwire_profile_start
();
// assume success - it gets checked in next state
globals
.
state
=
SW_STATE_REGISTER
;
}
}
static
void
mod_signalwire_state_register
(
void
)
{
if
(
globals
.
profile_update
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire SIP profile update initiated
\n
"
);
globals
.
state
=
SW_STATE_CONFIGURE
;
globals
.
profile_update
=
KS_FALSE
;
return
;
}
else
if
(
globals
.
profile_reload
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire SIP profile reload initiated
\n
"
);
globals
.
state
=
SW_STATE_START_PROFILE
;
globals
.
profile_reload
=
KS_FALSE
;
return
;
}
// ignore SignalWire reconnections until register is attempted
if
(
switch_loadable_module_exists
(
"mod_sofia"
)
!=
SWITCH_STATUS_SUCCESS
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Waiting for mod_sofia to load
\n
"
);
globals
.
state
=
SW_STATE_START_PROFILE
;
}
else
if
(
signalwire_gateway_exists
()
||
signalwire_profile_rescan
())
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"SignalWire SIP gateway started
\n
"
);
globals
.
state
=
SW_STATE_READY
;
}
else
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_WARNING
,
"Failed to start SignalWire SIP gateway
\n
"
);
globals
.
state
=
SW_STATE_CONFIGURE
;
ks_sleep_ms
(
5000
);
}
}
static
void
mod_signalwire_state_ready
()
{
if
(
globals
.
profile_update
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"Signalwire SIP profile update initiated
\n
"
);
globals
.
state
=
SW_STATE_CONFIGURE
;
globals
.
profile_update
=
KS_FALSE
;
}
else
if
(
globals
.
profile_reload
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_INFO
,
"SignalWire SIP profile reload initiated
\n
"
);
globals
.
state
=
SW_STATE_START_PROFILE
;
globals
.
profile_reload
=
KS_FALSE
;
}
else
if
(
globals
.
signalwire_reconnected
)
{
globals
.
signalwire_reconnected
=
KS_FALSE
;
globals
.
state
=
SW_STATE_ONLINE
;
}
}
SWITCH_MODULE_RUNTIME_FUNCTION
(
mod_signalwire_runtime
)
{
while
(
!
globals
.
shutdown
)
{
if
(
globals
.
restarting
)
{
swclt_sess_disconnect
(
globals
.
signalwire_session
);
while
(
swclt_hstate_current_get
(
globals
.
signalwire_session
)
==
SWCLT_HSTATE_ONLINE
)
{
switch_log_printf
(
SWITCH_CHANNEL_LOG
,
SWITCH_LOG_DEBUG
,
"Sleeping for pending disconnect
\n
"
);
ks_sleep_ms
(
1000
);
}
// kill signalwire, so nothing more can come into the system
ks_handle_destroy
(
&
globals
.
signalwire_session
);
// Create a new session and start over
swclt_sess_create
(
&
globals
.
signalwire_session
,
globals
.
blade_bootstrap
,
globals
.
config
);
swclt_sess_set_auth_failed_cb
(
globals
.
signalwire_session
,
mod_signalwire_session_auth_failed_handler
);
swclt_hmon_register
(
&
globals
.
signalwire_session_monitor
,
globals
.
signalwire_session
,
mod_signalwire_session_state_handler
,
NULL
);
globals
.
restarting
=
KS_FALSE
;
continue
;
}
switch
(
globals
.
state
)
{
case
SW_STATE_ADOPTION
:
// waiting for adoption to occur
mod_signalwire_state_adoption
();
break
;
case
SW_STATE_OFFLINE
:
// waiting for session to go online
mod_signalwire_state_offline
();
break
;
case
SW_STATE_ONLINE
:
// provisioning service setup
mod_signalwire_state_online
();
break
;
case
SW_STATE_CONFIGURE
:
// provisioning configuration
mod_signalwire_state_configure
();
break
;
case
SW_STATE_START_PROFILE
:
mod_signalwire_state_start_profile
();
break
;
case
SW_STATE_REGISTER
:
mod_signalwire_state_register
();
break
;
case
SW_STATE_READY
:
// ready for runtime
mod_signalwire_state_ready
();
break
;
default
:
break
;
}
ks_sleep_ms
(
1000
);
}
return
SWITCH_STATUS_TERM
;
}
/* 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
*/
w32/Setup/Setup.2017.wixproj
浏览文件 @
d0cca7e2
...
...
@@ -293,6 +293,14 @@
<RefProjectOutputGroups>
Binaries;Content;Satellites
</RefProjectOutputGroups>
<RefTargetDir>
INSTALLFOLDER
</RefTargetDir>
</ProjectReference>
<ProjectReference
Include=
"..\..\src\mod\applications\mod_signalwire\mod_signalwire.2017.vcxproj"
>
<Name>
mod_signalwire
</Name>
<Project>
{b19ae6fc-bfff-428d-b483-3bbeaeccc618}
</Project>
<Private>
True
</Private>
<DoNotHarvest>
True
</DoNotHarvest>
<RefProjectOutputGroups>
Binaries;Content;Satellites
</RefProjectOutputGroups>
<RefTargetDir>
INSTALLFOLDER
</RefTargetDir>
</ProjectReference>
<ProjectReference
Include=
"..\..\src\mod\applications\mod_sms\mod_sms.2017.vcxproj"
>
<Name>
mod_sms
</Name>
<Project>
{2469b306-b027-4ff2-8815-c9c1ea2cae79}
</Project>
...
...
w32/libks-version.props
0 → 100644
浏览文件 @
d0cca7e2
<?xml version="1.0" encoding="utf-8"?>
<Project
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ImportGroup
Label=
"PropertySheets"
>
<Import
Project=
"basedir.props"
Condition=
" '$(BaseDirImported)' == ''"
/>
</ImportGroup>
<PropertyGroup
Label=
"UserMacros"
>
<libksVersion>
0.1.1
</libksVersion>
</PropertyGroup>
<PropertyGroup>
<libksVersionImported>
true
</libksVersionImported>
</PropertyGroup>
<PropertyGroup
/>
<ItemDefinitionGroup
/>
<ItemGroup>
<BuildMacro
Include=
"libksVersion"
>
<Value>
$(libksVersion)
</Value>
</BuildMacro>
</ItemGroup>
</Project>
w32/libks.props
0 → 100644
浏览文件 @
d0cca7e2
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets=
"Build"
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ImportGroup
Label=
"PropertySheets"
>
<Import
Project=
"libks-version.props"
Condition=
" '$(libksVersionImported)' == ''"
/>
<Import
Project=
"downloadpackage.task"
Condition=
" '$(downloadpackagetask_Imported)' == '' "
/>
</ImportGroup>
<PropertyGroup>
<libksPropsImported>
true
</libksPropsImported>
</PropertyGroup>
<PropertyGroup
Label=
"UserMacros"
>
<libksDir>
$(BaseDir)libs\libks-$(libksVersion)
</libksDir>
</PropertyGroup>
<!--
Download Target.
Name must be unique.
By design, targets are executed only once per project.
Usage:
package: URI
expectfileordirectory: Skips the download and extraction if exists
outputfolder: Folder to store a downloaded file.
By default "$(BaseDir)libs", if empty
outputfilename: If not empty, overrides filename from URI.
.exe files don't get extracted
extractto: Folder to extract an archive to
-->
<Target
Name=
"libksBinariesDownloadTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"7za"
>
<DownloadPackageTask
package=
"http://files.freeswitch.org/windows/packages/libks/$(libksVersion)/libks-$(libksVersion)-binaries-$(Platform.ToLower())-$(Configuration.ToLower()).zip"
expectfileordirectory=
"$(libksDir)\binaries\$(Platform)\$(Configuration)\ks.dll"
outputfolder=
""
outputfilename=
""
extractto=
"$(BaseDir)libs\"
/>
</Target>
<Target
Name=
"libksHeadersDownloadTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"7za"
>
<DownloadPackageTask
package=
"http://files.freeswitch.org/windows/packages/libks/$(libksVersion)/libks-$(libksVersion)-headers.zip"
expectfileordirectory=
"$(libksDir)\src\include\libks\ks.h"
outputfolder=
""
outputfilename=
""
extractto=
"$(BaseDir)libs\"
/>
</Target>
<Target
Name=
"libkscopyTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"libksBinariesDownloadTarget"
>
<Message
Text=
"Copying libks libraries to the freeswitch output folder."
Importance=
"High"
/>
<ItemGroup>
<libksFiles
Include=
"$(libksDir)\binaries\$(Platform)\$(Configuration)\*.dll"
/>
</ItemGroup>
<Copy
Condition=
"!exists('$(BaseDir)\$(Platform)\$(Configuration)\ks.dll')"
SourceFiles=
"@(libksFiles)"
DestinationFiles=
"@(libksFiles->'$(BaseDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension)')"
/>
</Target>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>
$(libksDir)\src\include;%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PreprocessorDefinitions>
__PRETTY_FUNCTION__=__FUNCSIG__;WIN32;_WINDOWS;SWCLT_VERSION_MAJOR=1;SWCLT_VERSION_MINOR=0;SWCLT_VERSION_REVISION=0;_WIN32_WINNT=0x0600;_WINSOCK_DEPRECATED_NO_WARNINGS=1;WIN32_LEAN_AND_MEAN=1;KS_PLAT_WIN=1;NOMAXMIN=1;_CRT_SECURE_NO_WARNINGS=1;SWCLT_EXPORTS;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
$(libksDir)\binaries\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<AdditionalDependencies>
ks.lib;%(AdditionalDependencies)
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
w32/signalwire-client-c-version.props
0 → 100644
浏览文件 @
d0cca7e2
<?xml version="1.0" encoding="utf-8"?>
<Project
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ImportGroup
Label=
"PropertySheets"
>
<Import
Project=
"basedir.props"
Condition=
" '$(BaseDirImported)' == ''"
/>
</ImportGroup>
<PropertyGroup
Label=
"UserMacros"
>
<signalwire-client-cVersion>
1.0.0
</signalwire-client-cVersion>
</PropertyGroup>
<PropertyGroup>
<signalwire-client-cVersionImported>
true
</signalwire-client-cVersionImported>
</PropertyGroup>
<PropertyGroup
/>
<ItemDefinitionGroup
/>
<ItemGroup>
<BuildMacro
Include=
"signalwire-client-cVersion"
>
<Value>
$(signalwire-client-cVersion)
</Value>
</BuildMacro>
</ItemGroup>
</Project>
w32/signalwire-client-c.props
0 → 100644
浏览文件 @
d0cca7e2
<?xml version="1.0" encoding="utf-8"?>
<Project
DefaultTargets=
"Build"
ToolsVersion=
"4.0"
xmlns=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
<ImportGroup
Label=
"PropertySheets"
>
<Import
Project=
"signalwire-client-c-version.props"
Condition=
" '$(signalwire-client-cVersionImported)' == ''"
/>
</ImportGroup>
<PropertyGroup>
<signalwire-client-cPropsImported>
true
</signalwire-client-cPropsImported>
</PropertyGroup>
<PropertyGroup
Label=
"UserMacros"
>
<signalwire-client-cDir>
$(BaseDir)libs\signalwire-client-c-$(signalwire-client-cVersion)
</signalwire-client-cDir>
</PropertyGroup>
<!--
Download Target.
Name must be unique.
By design, targets are executed only once per project.
Usage:
package: URI
expectfileordirectory: Skips the download and extraction if exists
outputfolder: Folder to store a downloaded file.
By default "$(BaseDir)libs", if empty
outputfilename: If not empty, overrides filename from URI.
.exe files don't get extracted
extractto: Folder to extract an archive to
-->
<Target
Name=
"signalwire-client-cBinariesDownloadTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"7za"
>
<DownloadPackageTask
package=
"http://files.freeswitch.org/windows/packages/signalwire-client-c/$(signalwire-client-cVersion)/signalwire-client-c-$(signalwire-client-cVersion)-binaries-$(Platform.ToLower())-$(Configuration.ToLower()).zip"
expectfileordirectory=
"$(signalwire-client-cDir)\binaries\$(Platform)\$(Configuration)\signalwire_client.dll"
outputfolder=
""
outputfilename=
""
extractto=
"$(BaseDir)libs\"
/>
</Target>
<Target
Name=
"signalwire-client-cHeadersDownloadTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"7za"
>
<DownloadPackageTask
package=
"http://files.freeswitch.org/windows/packages/signalwire-client-c/$(signalwire-client-cVersion)/signalwire-client-c-$(signalwire-client-cVersion)-headers.zip"
expectfileordirectory=
"$(signalwire-client-cDir)\include\signalwire-client-c\client.h"
outputfolder=
""
outputfilename=
""
extractto=
"$(BaseDir)libs\"
/>
</Target>
<Target
Name=
"signalwire-client-ccopyTarget"
BeforeTargets=
"CustomBuild"
DependsOnTargets=
"signalwire-client-cBinariesDownloadTarget"
>
<Message
Text=
"Copying signalwire-client-c libraries to the freeswitch output folder."
Importance=
"High"
/>
<ItemGroup>
<signalwire-client-cFiles
Include=
"$(signalwire-client-cDir)\binaries\$(Platform)\$(Configuration)\*.dll"
/>
</ItemGroup>
<Copy
Condition=
"!exists('$(BaseDir)\$(Platform)\$(Configuration)\signalwire_client.dll')"
SourceFiles=
"@(signalwire-client-cFiles)"
DestinationFiles=
"@(signalwire-client-cFiles->'$(BaseDir)\$(Platform)\$(Configuration)\%(Filename)%(Extension)')"
/>
</Target>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>
$(signalwire-client-cDir)\include;%(AdditionalIncludeDirectories)
</AdditionalIncludeDirectories>
<PreprocessorDefinitions>
%(PreprocessorDefinitions)
</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>
$(signalwire-client-cDir)\binaries\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)
</AdditionalLibraryDirectories>
<AdditionalDependencies>
signalwire_client.lib;%(AdditionalDependencies)
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论