Initial commit of mod_v8

This commit is contained in:
Peter Olsson 2014-01-14 11:04:03 +01:00
parent cc8a8c5198
commit b762332669
56 changed files with 11155 additions and 4 deletions

3
.gitignore vendored
View File

@ -169,6 +169,9 @@ Release/
/src/mod/say/mod_say_nl/Makefile
/src/mod/say/mod_say_th/Makefile
/src/mod/say/mod_say_zh/Makefile
/src/mod/languages/mod_v8/Makefile
/src/mod/languages/mod_v8/Makefile.in
/src/mod/languages/mod_v8/mod_v8.log
BuildLog.htm

View File

@ -87,6 +87,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "autoload_configs", "autoloa
conf\vanilla\autoload_configs\spidermonkey.conf.xml = conf\vanilla\autoload_configs\spidermonkey.conf.xml
conf\vanilla\autoload_configs\switch.conf.xml = conf\vanilla\autoload_configs\switch.conf.xml
conf\vanilla\autoload_configs\syslog.conf.xml = conf\vanilla\autoload_configs\syslog.conf.xml
conf\vanilla\autoload_configs\v8.conf.xml = conf\vanilla\autoload_configs\v8.conf.xml
conf\vanilla\autoload_configs\voicemail.conf.xml = conf\vanilla\autoload_configs\voicemail.conf.xml
conf\vanilla\autoload_configs\wanpipe.conf.xml = conf\vanilla\autoload_configs\wanpipe.conf.xml
conf\vanilla\autoload_configs\woomera.conf.xml = conf\vanilla\autoload_configs\woomera.conf.xml
@ -195,6 +196,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libteletone", "libs\libtele
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_spidermonkey", "src\mod\languages\mod_spidermonkey\mod_spidermonkey.2012.vcxproj", "{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_v8", "src\mod\languages\mod_v8\mod_v8.2012.vcxproj", "{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_v8_skel", "src\mod\languages\mod_v8\mod_v8_skel.2012.vcxproj", "{8B754330-A434-4791-97E5-1EE67060BAC0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_cepstral", "src\mod\asr_tts\mod_cepstral\mod_cepstral.2012.vcxproj", "{692F6330-4D87-4C82-81DF-40DB5892636E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_ilbc", "src\mod\codecs\mod_ilbc\mod_ilbc.2012.vcxproj", "{D3EC0AFF-76FC-4210-A825-9A17410660A3}"
@ -577,6 +582,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcbt", "libs\win32\libcbt
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "make_cielab_luts", "libs\spandsp\src\msvc\make_cielab_luts.2012.vcxproj", "{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download V8", "libs\win32\Download V8.2012.vcxproj", "{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libv8", "libs\win32\v8\libv8.2012.vcxproj", "{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Download OPUS", "libs\win32\Download OPUS.2012.vcxproj", "{092124C9-09ED-43C7-BD6D-4AE5D6B3C547}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "opus", "opus", "{ED2CA8B5-8E91-4296-A120-02BB0B674652}"
@ -839,6 +848,38 @@ Global
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64.Build.0 = Release|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x64 Setup.ActiveCfg = Release|x64
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F}.Release|x86 Setup.ActiveCfg = Release|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|Win32.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|x64.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|x64.Build.0 = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|x64 Setup.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|x64 Setup.Build.0 = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.All|x86 Setup.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|Win32.ActiveCfg = Debug|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|Win32.Build.0 = Debug|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|x64.ActiveCfg = Debug|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|x64.Build.0 = Debug|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|x64 Setup.ActiveCfg = Debug|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|Win32.ActiveCfg = Release|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|Win32.Build.0 = Release|Win32
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|x64.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|x64.Build.0 = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|x64 Setup.ActiveCfg = Release|x64
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}.Release|x86 Setup.ActiveCfg = Release|Win32
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|Win32.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|x64.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|x64.Build.0 = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|x64 Setup.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|x64 Setup.Build.0 = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.All|x86 Setup.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.Debug|Win32.ActiveCfg = Debug|Win32
{8B754330-A434-4791-97E5-1EE67060BAC0}.Debug|x64.ActiveCfg = Debug|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.Debug|x64 Setup.ActiveCfg = Debug|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{8B754330-A434-4791-97E5-1EE67060BAC0}.Release|Win32.ActiveCfg = Release|Win32
{8B754330-A434-4791-97E5-1EE67060BAC0}.Release|x64.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.Release|x64 Setup.ActiveCfg = Release|x64
{8B754330-A434-4791-97E5-1EE67060BAC0}.Release|x86 Setup.ActiveCfg = Release|Win32
{692F6330-4D87-4C82-81DF-40DB5892636E}.All|Win32.ActiveCfg = Release|x64
{692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.ActiveCfg = Release|x64
{692F6330-4D87-4C82-81DF-40DB5892636E}.All|x64.Build.0 = Release|x64
@ -3838,6 +3879,41 @@ Global
{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64.Build.0 = All|Win32
{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x64 Setup.ActiveCfg = All|Win32
{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981}.Release|x86 Setup.ActiveCfg = All|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.All|Win32.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.All|Win32.Build.0 = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.All|x64.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.All|x64 Setup.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.All|x86 Setup.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|Win32.ActiveCfg = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|Win32.Build.0 = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|x64.ActiveCfg = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|x64.Build.0 = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|x64 Setup.ActiveCfg = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|Win32.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|Win32.Build.0 = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|x64.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|x64.Build.0 = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|x64 Setup.ActiveCfg = Release|Win32
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}.Release|x86 Setup.ActiveCfg = Release|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|Win32.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|x64.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|x64.Build.0 = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|x64 Setup.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|x64 Setup.Build.0 = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.All|x86 Setup.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|Win32.ActiveCfg = Debug|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|Win32.Build.0 = Debug|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|x64.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|x64.Build.0 = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|x64 Setup.ActiveCfg = Debug|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Debug|x86 Setup.ActiveCfg = Debug|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|Win32.ActiveCfg = Release|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|Win32.Build.0 = Release|Win32
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|x64.ActiveCfg = Release|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|x64.Build.0 = Release|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|x64 Setup.ActiveCfg = Release|x64
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}.Release|x86 Setup.ActiveCfg = Release|Win32
{092124C9-09ED-43C7-BD6D-4AE5D6B3C547}.All|Win32.ActiveCfg = Release|Win32
{092124C9-09ED-43C7-BD6D-4AE5D6B3C547}.All|Win32.Build.0 = Release|Win32
{092124C9-09ED-43C7-BD6D-4AE5D6B3C547}.All|x64.ActiveCfg = Release|Win32
@ -4098,10 +4174,13 @@ Global
{2386B892-35F5-46CF-A0F0-10394D2FBF9B} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{77BC1DD2-C9A1-44D7-BFFA-1320370CACB9} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{85F0CF8C-C7AB-48F6-BA19-CC94CF87F981} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{ED2CA8B5-8E91-4296-A120-02BB0B674652} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{EDDB8AB9-C53E-44C0-A620-0E86C2CBD5D5} = {EB910B0D-F27D-4B62-B67B-DE834C99AC5B}
{EC3E5C7F-EE09-47E2-80FE-546363D14A98} = {B8F5B47B-8568-46EB-B320-64C17D2A98BC}
{1AD3F51E-BBB6-4090-BA39-9DFAB1EF1F5F} = {0C808854-54D1-4230-BFF5-77B5FD905000}
{9B9D2551-D6BD-4F20-8BE5-DE30E154A064} = {0C808854-54D1-4230-BFF5-77B5FD905000}
{8B754330-A434-4791-97E5-1EE67060BAC0} = {0C808854-54D1-4230-BFF5-77B5FD905000}
{ACFFF684-4D19-4D48-AF12-88EA1D778BDF} = {0C808854-54D1-4230-BFF5-77B5FD905000}
{8F992C49-6C51-412F-B2A3-34EAB708EB65} = {0C808854-54D1-4230-BFF5-77B5FD905000}
{0A6B5EA5-6E9B-4A51-931F-ED25AA87B4DF} = {0C808854-54D1-4230-BFF5-77B5FD905000}
@ -4139,6 +4218,7 @@ Global
{B808178B-82F0-4CF4-A2B1-921939FA24D0} = {C120A020-773F-4EA3-923F-B67AF28B750D}
{D578E676-7EC8-4548-BD8B-845C635F14AD} = {C120A020-773F-4EA3-923F-B67AF28B750D}
{652AD5F7-8488-489F-AAD0-7FBE064703B6} = {C120A020-773F-4EA3-923F-B67AF28B750D}
{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF} = {C120A020-773F-4EA3-923F-B67AF28B750D}
{092124C9-09ED-43C7-BD6D-4AE5D6B3C547} = {C120A020-773F-4EA3-923F-B67AF28B750D}
{988CACF7-3FCB-4992-BE69-77872AE67DC8} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}
{5BC072DB-3826-48EA-AF34-FE32AA01E83B} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}

View File

@ -119,6 +119,7 @@ languages/mod_lua
#languages/mod_perl
#languages/mod_python
#languages/mod_spidermonkey
languages/mod_v8
#languages/mod_yaml
loggers/mod_console
loggers/mod_logfile

View File

@ -0,0 +1,5 @@
<configuration name="v8.conf" description="Google V8 JavaScript Plug-Ins">
<modules>
<!-- <load module="mod_v8_skel"/> -->
</modules>
</configuration>

View File

@ -79,7 +79,8 @@
<!-- Timers -->
<!-- Languages -->
<load module="mod_spidermonkey"/>
<!-- <load module="mod_spidermonkey"/> -->
<load module="mod_v8"/>
<!-- <load module="mod_perl"/> -->
<!-- <load module="mod_python"/> -->
<!-- <load module="mod_java"/> -->

View File

@ -0,0 +1,5 @@
<configuration name="v8.conf" description="Google V8 JavaScript Plug-Ins">
<modules>
<!-- <load module="mod_v8_skel"/> -->
</modules>
</configuration>

View File

@ -110,6 +110,7 @@
<!-- Languages -->
<!-- <load module="mod_spidermonkey"/> -->
<load module="mod_v8"/>
<!-- <load module="mod_perl"/> -->
<!-- <load module="mod_python"/> -->
<!-- <load module="mod_java"/> -->

View File

@ -0,0 +1,5 @@
<configuration name="v8.conf" description="Google V8 JavaScript Plug-Ins">
<modules>
<!-- <load module="mod_v8_skel"/> -->
</modules>
</configuration>

View File

@ -1162,6 +1162,7 @@ AC_CONFIG_FILES([Makefile
src/mod/legacy/languages/mod_lua/Makefile
src/mod/languages/mod_python/Makefile
src/mod/languages/mod_spidermonkey/Makefile
src/mod/languages/mod_v8/Makefile
src/mod/event_handlers/mod_erlang_event/Makefile
src/include/switch_am_config.h
build/getsounds.sh

1
debian/util.sh vendored
View File

@ -115,6 +115,7 @@ getlibs () {
getlib http://files.freeswitch.org/downloads/libs/lame-3.98.4.tar.gz
getlib http://files.freeswitch.org/downloads/libs/libshout-2.2.2.tar.gz
getlib http://files.freeswitch.org/downloads/libs/mpg123-1.13.2.tar.gz
getlib http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2
# cleanup mongo
(
cd mongo-cxx-driver-v1.8

View File

@ -38,6 +38,7 @@ that much better:
Juan Jose Comellas <juanjo@comellas.org> - Patch to switch_utils for arg parsing.
Dale Thatcher <freeswitch at dalethatcher dot com> - Additions to mod_conference.
Simon Perreault & Marc Blanchet from Viagenie.ca - IPv6 Support.
Peter Olsson <peter@olssononline.se> - mod_v8, and other various patches.
A big THANK YOU goes to:

View File

@ -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-spidermonkey
# freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-perl freeswitch-python freeswitch-spidermonkey freeswitch-v8
# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-hu freeswitch-lang-ru freeswitch-freetdm
#
# Initial Version Copyright (C) 2007 Peter Nixon and Michal Bielicki, All Rights Reserved.
@ -127,6 +127,7 @@ Source9: http://files.freeswitch.org/downloads/libs/communicator_semi_6000_20080
Source10: http://files.freeswitch.org/downloads/libs/libmemcached-0.32.tar.gz
Source11: http://files.freeswitch.org/downloads/libs/json-c-0.9.tar.gz
Source12: http://files.freeswitch.org/downloads/libs/opus-1.1.tar.gz
Source13: http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2
Prefix: %{prefix}
@ -1102,10 +1103,17 @@ Requires: python
%package spidermonkey
Summary: JavaScript support for the FreeSWITCH open source telephony platform
Group: System/Libraries
Requires: %{name} = %{version}-%{release}
Requires: %{name} = %{version}-%{release}
%description spidermonkey
%package v8
Summary: JavaScript support for the FreeSWITCH open source telephony platform, using Google V8 JavaScript engine
Group: System/Libraries
Requires: %{name} = %{version}-%{release}
%description v8
######################################################################################################################
# FreeSWITCH Say Modules
######################################################################################################################
@ -1421,7 +1429,7 @@ FORMATS_MODULES+=" formats/mod_ssml"
# Embedded Languages
#
######################################################################################################################
LANGUAGES_MODULES="languages/mod_lua languages/mod_perl languages/mod_python languages/mod_spidermonkey"
LANGUAGES_MODULES="languages/mod_lua languages/mod_perl languages/mod_python languages/mod_spidermonkey languages/mod_v8"
######################################################################################################################
#
@ -2302,6 +2310,15 @@ fi
%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/spidermonkey.conf.xml
%files v8
%defattr(-,freeswitch,daemon)
%{MODINSTDIR}/mod_v8*.so*
%{LIBDIR}/libv8.so
%{LIBDIR}/libicui18n.so
%{LIBDIR}/libicuuc.so
%dir %attr(0750, freeswitch, daemon) %{sysconfdir}/autoload_configs
%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/v8.conf.xml
######################################################################################################################
#
# Language Modules
@ -2427,6 +2444,8 @@ fi
#
######################################################################################################################
%changelog
* Mon Jan 13 2014 - peter@olssononline.se
- Add mod_v8
* Mon Dec 09 2013 - crienzo@grasshopper.com
- Add mod_ssml, mod_rayo
- Fix build on master

1
libs/.gitignore vendored
View File

@ -980,6 +980,7 @@ opal
/zeromq-*/
/jpeg-8d/
/v8-*/
# build products we should remove
!/apr-util/xml/expat/conftools/config.guess

View File

@ -0,0 +1,82 @@
<?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="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>Download V8</ProjectName>
<ProjectGuid>{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}</ProjectGuid>
<RootNamespace>Download V8</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)\w32\extdll.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" />
</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" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(PlatformName)\V8\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(PlatformName)\V8\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<CustomBuild Include="cleancount">
<FileType>Document</FileType>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Downloading V8.</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">if not exist "$(ProjectDir)..\v8-3.24.14" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2 "$(ProjectDir).."
if not exist "$(ProjectDir)..\v8-3.24.14\third_party\cygwin" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/v8-3.24.14-win.tar.bz2 "$(ProjectDir).."
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\v8-3.24.14;%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Downloading V8.</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">if not exist "$(ProjectDir)..\v8-3.24.14" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/v8-3.24.14.tar.bz2 "$(ProjectDir).."
if not exist "$(ProjectDir)..\v8-3.24.14\third_party\cygwin" cscript /nologo "$(ProjectDir)util.vbs" GetUnzip http://files.freeswitch.org/downloads/libs/v8-3.24.14-win.tar.bz2 "$(ProjectDir).."
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\v8-3.24.14;%(Outputs)</Outputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,59 @@
@ECHO OFF
IF "%1" == "" GOTO Fail
IF "%2" == "" GOTO Fail
IF "%3" == "" GOTO Fail
cd "%3"
SET /P LAST_BUILD_INFO=<last_build
IF "%1-%2" == "%LAST_BUILD_INFO%" (
ECHO V8 is already built!
SET COPY_FILES_ONLY=1
)
SET LIB_DEST_DIR=
IF "%1" == "x64" (
IF NOT "%COPY_FILES_ONLY%" == "1" .\third_party\python_26\python.exe build\gyp_v8 -Dtarget_arch=x64 -Dcomponent=shared_library
IF NOT ERRORLEVEL 0 GOTO Fail
SET LIB_DEST_DIR=..\..\x64\%2\
)
IF "%1" == "x86" (
IF NOT "%COPY_FILES_ONLY%" == "1" .\third_party\python_26\python.exe build\gyp_v8 -Dcomponent=shared_library
IF NOT ERRORLEVEL 0 GOTO Fail
SET LIB_DEST_DIR=..\..\Win32\%2\
)
IF "%LIB_DEST_DIR%" == "" GOTO Fail
IF "%COPY_FILES_ONLY%" == "1" GOTO CopyFiles
devenv.com /clean %2 tools\gyp\v8.sln
IF NOT ERRORLEVEL 0 GOTO Fail
devenv.com /build %2 tools\gyp\v8.sln
IF NOT ERRORLEVEL 0 GOTO Fail
:CopyFiles
REM xcopy /C /F /R /Y .\build\%2\icudt.dll %LIB_DEST_DIR%
REM IF NOT ERRORLEVEL 0 GOTO Fail
xcopy /C /F /R /Y .\build\%2\icui18n.dll %LIB_DEST_DIR%
IF NOT ERRORLEVEL 0 GOTO Fail
xcopy /C /F /R /Y .\build\%2\icuuc.dll %LIB_DEST_DIR%
IF NOT ERRORLEVEL 0 GOTO Fail
xcopy /C /F /R /Y .\build\%2\v8.dll %LIB_DEST_DIR%
IF NOT ERRORLEVEL 0 GOTO Fail
ECHO %1-%2> last_build
exit
:Fail
exit /b 1

View File

@ -0,0 +1,144 @@
<?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>libv8</ProjectName>
<ProjectGuid>{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}</ProjectGuid>
<RootNamespace>libv8</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v110</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)\w32\extdll.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" />
</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" />
</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" />
</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" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(PlatformName)\V8\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(PlatformName)\V8\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(PlatformName)\V8\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(PlatformName)\V8\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<BuildLog>
<Path>$(IntDir)BuildLog $(ProjectName).htm</Path>
</BuildLog>
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<CustomBuild Include="cleancount">
<FileType>Document</FileType>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Google V8</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)build-v8.bat x86 Release "$(ProjectDir)..\..\v8-3.24.14"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\..\v8-3.24.14;%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Google V8</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)build-v8.bat x86 Debug "$(ProjectDir)..\..\v8-3.24.14"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\..\v8-3.24.14;%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Building Google V8</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)build-v8.bat x64 Release "$(ProjectDir)..\..\v8-3.24.14"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)..\..\v8-3.24.14;%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Building Google V8</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)build-v8.bat x64 Debug "$(ProjectDir)..\..\v8-3.24.14"
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)..\..\v8-3.24.14;%(Outputs)</Outputs>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Download V8.2012.vcxproj">
<Project>{13077E43-E5DF-4EF6-9EB1-2A0B22E8DFAF}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,59 @@
include $(top_srcdir)/build/modmake.rulesam
V8=v8-3.24.14
V8_DIR=$(switch_srcdir)/libs/$(V8)
V8_BUILDDIR=$(switch_builddir)/libs/$(V8)
V8SO=$(V8_DIR)/out/native/lib.target/libv8.so
CURL_DIR=$(switch_srcdir)/libs/curl
CURL_BUILDDIR=$(switch_builddir)/libs/curl
CURLLA=${switch_builddir}/libs/curl/lib/libcurl.la
MODNAME=mod_v8
AM_CFLAGS += -I. -I./include -I$(V8_DIR)/include
AM_CPPFLAGS += -I. -I./include -I$(V8_DIR)/include
AM_LIBADD = $(switch_builddir)/libfreeswitch.la -lv8 -licuuc -licui18n
AM_LDFLAGS += -avoid-version -module -no-undefined -shared
AM_LDFLAGS += -L$(V8_DIR)/out/native/lib.target
BUILT_SOURCES = $(V8SO) $(LIBCURL_DEPS)
if HAVE_ODBC
AM_CFLAGS += -DHAVE_ODBC $(ODBC_INC_FLAGS)
AM_CPPFLAGS += -DHAVE_ODBC $(ODBC_INC_FLAGS)
AM_LDFLAGS += -DHAVE_ODBC
endif
mod_LTLIBRARIES = mod_v8.la
mod_v8_la_SOURCES = mod_v8.cpp ./src/fscoredb.cpp ./src/fscurl.cpp ./src/fsdtmf.cpp ./src/fsevent.cpp ./src/fsfileio.cpp ./src/fsglobal.cpp ./src/fsodbc.cpp ./src/fspcre.cpp ./src/fsrequest.cpp ./src/fssession.cpp ./src/fssocket.cpp ./src/fsteletone.cpp ./src/fsxml.cpp ./src/fsfile.cpp ./src/jsbase.cpp ./src/jsmain.cpp
mod_v8_la_CFLAGS = $(AM_CFLAGS) $(LIBCURL_CPPFLAGS) -I$(switch_srcdir)/libs/libteletone/src
mod_v8_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBCURL_CPPFLAGS) -I$(switch_srcdir)/libs/libteletone/src
mod_v8_la_LIBADD = $(AM_LIBADD)
mod_v8_la_LDFLAGS = $(AM_LDFLAGS) $(LIBCURL)
#mod_LTLIBRARIES += mod_v8_skel.la
#mod_v8_skel_la_SOURCES = mod_v8_skel.cpp
#mod_v8_skel_la_CFLAGS = $(AM_CFLAGS) -DJSMOD_IMPORT
#mod_v8_skel_la_CPPFLAGS = $(AM_CPPFLAGS) -DJSMOD_IMPORT
#mod_v8_skel_la_LIBADD = $(AM_LIBADD)
#mod_v8_skel_la_LDFLAGS = $(AM_LDFLAGS)
$(SOURCES): $(BUILT_SOURCES)
$(V8_DIR):
$(GETLIB) $(V8).tar.bz2
$(V8SO): $(V8_DIR)
cd $(V8_BUILDDIR) && $(MAKE) library=shared native
$(CURLLA):
@cd $(CURL_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
install-exec-local: $(DESTDIR)$(libdir)/libv8.so
$(DESTDIR)$(libdir)/libv8.so: $(V8SO)
rm -f $(DESTDIR)$(libdir)/libv8.so && cp -a $(V8_DIR)/out/native/lib.target/libv8.so $(DESTDIR)$(libdir)/libv8.so
rm -f $(DESTDIR)$(libdir)/libicuuc.so && cp -a $(V8_DIR)/out/native/lib.target/libicuuc.so $(DESTDIR)$(libdir)/libicuuc.so
rm -f $(DESTDIR)$(libdir)/libicui18n.so && cp -a $(V8_DIR)/out/native/lib.target/libicui18n.so $(DESTDIR)$(libdir)/libicui18n.so

View File

@ -0,0 +1,5 @@
<configuration name="v8.conf" description="Google V8 JavaScript Plug-Ins">
<modules>
<!-- <load module="mod_v8_skel"/> -->
</modules>
</configuration>

View File

@ -0,0 +1,89 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fscoredb.hpp -- JavaScript CoreDB class header
*
*/
#ifndef FS_COREDB_H
#define FS_COREDB_H
#include "mod_v8.h"
/* Macros for easier V8 callback definitions */
#define JS_COREDB_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSCoreDB)
#define JS_COREDB_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSCoreDB)
#define JS_COREDB_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSCoreDB)
#define JS_COREDB_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSCoreDB)
#define JS_COREDB_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSCoreDB)
#define JS_COREDB_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSCoreDB)
class FSCoreDB : public JSBase
{
private:
switch_memory_pool_t *_pool;
switch_core_db_t *_db;
switch_core_db_stmt_t *_stmt;
const char *_dbname;
v8::Persistent<v8::Function> _callback;
void Init();
void DoClose();
void StepEx(const v8::FunctionCallbackInfo<v8::Value>& info, int stepSuccessCode);
static int Callback(void *pArg, int argc, char **argv, char **columnNames);
public:
FSCoreDB(JSMain *owner) : JSBase(owner) { Init(); }
FSCoreDB(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSCoreDB(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_COREDB_FUNCTION_DEF(Exec);
JS_COREDB_FUNCTION_DEF(Close);
JS_COREDB_FUNCTION_DEF(Next);
JS_COREDB_FUNCTION_DEF(Step);
JS_COREDB_FUNCTION_DEF(Fetch);
JS_COREDB_FUNCTION_DEF(Prepare);
JS_COREDB_FUNCTION_DEF(BindText);
JS_COREDB_FUNCTION_DEF(BindInt);
JS_COREDB_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_COREDB_H */
/* 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:
*/

View File

@ -0,0 +1,79 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fscurl.hpp -- JavaScript CURL class header
*
*/
#ifndef FS_CURL_H
#define FS_CURL_H
#include "mod_v8.h"
#include <switch_curl.h>
/* Macros for easier V8 callback definitions */
#define JS_CURL_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSCURL)
#define JS_CURL_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSCURL)
#define JS_CURL_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSCURL)
#define JS_CURL_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSCURL)
#define JS_CURL_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSCURL)
#define JS_CURL_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSCURL)
class FSCURL : public JSBase
{
private:
switch_CURL *_curl_handle;
v8::Persistent<v8::Function> _function;
v8::Persistent<v8::Object> _user_data;
v8::Persistent<v8::Value> _ret;
void Init(void);
static size_t FileCallback(void *ptr, size_t size, size_t nmemb, void *data);
public:
FSCURL(JSMain *owner) : JSBase(owner) { Init(); }
FSCURL(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSCURL(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_CURL_FUNCTION_DEF(Run);
};
#endif /* FS_CURL_H */
/* 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:
*/

View File

@ -0,0 +1,74 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsdtmf.hpp -- JavaScript DTMF class header
*
*/
#ifndef FS_DTMF_H
#define FS_DTMF_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_DTMF_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSDTMF)
#define JS_DTMF_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSDTMF)
#define JS_DTMF_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSDTMF)
#define JS_DTMF_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSDTMF)
#define JS_DTMF_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSDTMF)
#define JS_DTMF_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSDTMF)
class FSDTMF : public JSBase
{
private:
switch_dtmf_t *_dtmf;
public:
FSDTMF(JSMain *owner) : JSBase(owner) { _dtmf = NULL; }
FSDTMF(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { _dtmf = NULL; }
virtual ~FSDTMF(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
static v8::Handle<v8::Object> New(switch_dtmf_t *dtmf, const char *name, JSMain *js);
JS_DTMF_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_DTMF_H */
/* 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:
*/

View File

@ -0,0 +1,93 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsevent.hpp -- JavaScript Event class header
*
*/
#ifndef FS_EVENT_H
#define FS_EVENT_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_EVENT_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSEvent)
#define JS_EVENT_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSEvent)
#define JS_EVENT_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSEvent)
#define JS_EVENT_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSEvent)
#define JS_EVENT_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSEvent)
#define JS_EVENT_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSEvent)
#define JS_EVENT_GET_PROPERTY_IMPL_STATIC(method_name) JS_GET_PROPERTY_IMPL_STATIC(method_name, FSEvent)
#define JS_EVENT_SET_PROPERTY_IMPL_STATIC(method_name) JS_SET_PROPERTY_IMPL_STATIC(method_name, FSEvent)
#define JS_EVENT_FUNCTION_IMPL_STATIC(method_name) JS_FUNCTION_IMPL_STATIC(method_name, FSEvent)
class FSEvent : public JSBase
{
private:
switch_event_t *_event;
int _freed;
void Init();
public:
FSEvent(JSMain *owner) : JSBase(owner) { Init(); }
FSEvent(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSEvent(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
void SetEvent(switch_event_t *event, int freed = 0);
switch_event_t **GetEvent();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
static v8::Handle<v8::Object> New(switch_event_t *event, const char *name, JSMain *js);
JS_EVENT_FUNCTION_DEF(AddHeader);
JS_EVENT_FUNCTION_DEF(GetHeader);
JS_EVENT_FUNCTION_DEF(AddBody);
JS_EVENT_FUNCTION_DEF(GetBody);
JS_EVENT_FUNCTION_DEF(GetType);
JS_EVENT_FUNCTION_DEF(Serialize);
JS_EVENT_FUNCTION_DEF(ChatExecute);
JS_FUNCTION_DEF_STATIC(Fire); // This will also destroy the C++ object
JS_FUNCTION_DEF_STATIC(Destroy); // This will also destroy the C++ object
JS_EVENT_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_EVENT_H */
/* 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:
*/

View File

@ -0,0 +1,111 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsfile.hpp -- JavaScript File class header
*
*/
#ifndef FS_FILE_H
#define FS_FILE_H
#include "mod_v8.h"
/* Macros for easier V8 callback definitions */
#define JS_FILE_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSFile)
#define JS_FILE_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSFile)
#define JS_FILE_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSFile)
#define JS_FILE_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSFile)
#define JS_FILE_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSFile)
#define JS_FILE_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSFile)
class FSFile : public JSBase
{
private:
void Init();
public:
FSFile(JSMain *owner) : JSBase(owner) { }
FSFile(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { }
virtual ~FSFile(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_FILE_FUNCTION_DEF(Close);
JS_FILE_FUNCTION_DEF(CopyTo);
JS_FILE_FUNCTION_DEF(Flush);
JS_FILE_FUNCTION_DEF(List);
JS_FILE_FUNCTION_DEF(MkDir);
JS_FILE_FUNCTION_DEF(Open);
JS_FILE_FUNCTION_DEF(Read);
JS_FILE_FUNCTION_DEF(ReadAll);
JS_FILE_FUNCTION_DEF(ReadLn);
JS_FILE_FUNCTION_DEF(Remove);
JS_FILE_FUNCTION_DEF(RenameTo);
JS_FILE_FUNCTION_DEF(Seek);
JS_FILE_FUNCTION_DEF(ToString);
JS_FILE_FUNCTION_DEF(ToURL);
JS_FILE_FUNCTION_DEF(Write);
JS_FILE_FUNCTION_DEF(WriteAll);
JS_FILE_FUNCTION_DEF(WriteLn);
JS_FILE_GET_PROPERTY_DEF(GetPropCanAppend);
JS_FILE_GET_PROPERTY_DEF(GetPropCanRead);
JS_FILE_GET_PROPERTY_DEF(GetPropCanReplace);
JS_FILE_GET_PROPERTY_DEF(GetPropCanWrite);
JS_FILE_GET_PROPERTY_DEF(GetPropCreationTime);
JS_FILE_GET_PROPERTY_DEF(GetPropExists);
JS_FILE_GET_PROPERTY_DEF(GetPropHasAutoFlush);
JS_FILE_GET_PROPERTY_DEF(GetPropHasRandomAccess);
JS_FILE_GET_PROPERTY_DEF(GetPropIsDirectory);
JS_FILE_GET_PROPERTY_DEF(GetPropIsFile);
JS_FILE_GET_PROPERTY_DEF(GetPropIsNative);
JS_FILE_GET_PROPERTY_DEF(GetPropIsOpen);
JS_FILE_GET_PROPERTY_DEF(GetPropLastModified);
JS_FILE_GET_PROPERTY_DEF(GetPropLength);
JS_FILE_GET_PROPERTY_DEF(GetPropMode);
JS_FILE_GET_PROPERTY_DEF(GetPropName);
JS_FILE_GET_PROPERTY_DEF(GetPropParent);
JS_FILE_GET_PROPERTY_DEF(GetPropPath);
JS_FILE_GET_PROPERTY_DEF(GetPropPosition);
JS_FILE_SET_PROPERTY_DEF(SetPropPosition);
JS_FILE_GET_PROPERTY_DEF(GetPropSize);
JS_FILE_GET_PROPERTY_DEF(GetPropType);
};
#endif /* FS_FILE_H */
/* 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:
*/

View File

@ -0,0 +1,84 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsfileio.hpp -- JavaScript FileIO class header
*
*/
#ifndef FS_FILEIO_H
#define FS_FILEIO_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_FILEIO_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSFileIO)
#define JS_FILEIO_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSFileIO)
#define JS_FILEIO_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSFileIO)
#define JS_FILEIO_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSFileIO)
#define JS_FILEIO_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSFileIO)
#define JS_FILEIO_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSFileIO)
class FSFileIO : public JSBase
{
private:
char *_path;
unsigned int _flags;
switch_file_t *_fd;
switch_memory_pool_t *_pool;
char *_buf;
switch_size_t _buflen;
int32_t _bufsize;
void Init();
public:
FSFileIO(JSMain *owner) : JSBase(owner) { Init(); }
FSFileIO(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSFileIO(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_FILEIO_FUNCTION_DEF(Read);
JS_FILEIO_FUNCTION_DEF(Write);
JS_FILEIO_FUNCTION_DEF(GetData);
JS_FILEIO_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_FILEIO_H */
/* 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:
*/

View File

@ -0,0 +1,79 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsglobal.hpp -- JavaScript Global functions
*
*/
#ifndef FS_GLOBAL_H
#define FS_GLOBAL_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_GLOBAL_FUNCTION_IMPL_STATIC(method_name) JS_FUNCTION_IMPL_STATIC(method_name, FSGlobal)
/* All globally available functions (not related to objects) */
class FSGlobal
{
private:
static size_t HashCallback(void *ptr, size_t size, size_t nmemb, void *data);
static size_t FileCallback(void *ptr, size_t size, size_t nmemb, void *data);
static size_t FetchUrlCallback(void *ptr, size_t size, size_t nmemb, void *data);
public:
static const js_function_t *GetFunctionDefinitions();
/* Methods available from JavaScript */
JS_FUNCTION_DEF_STATIC(Log);
JS_FUNCTION_DEF_STATIC(GlobalGet);
JS_FUNCTION_DEF_STATIC(GlobalSet);
JS_FUNCTION_DEF_STATIC(Exit);
JS_FUNCTION_DEF_STATIC(Include);
JS_FUNCTION_DEF_STATIC(Bridge);
JS_FUNCTION_DEF_STATIC(Email);
JS_FUNCTION_DEF_STATIC(ApiExecute);
JS_FUNCTION_DEF_STATIC(Use);
JS_FUNCTION_DEF_STATIC(Sleep);
JS_FUNCTION_DEF_STATIC(FileDelete);
JS_FUNCTION_DEF_STATIC(System);
JS_FUNCTION_DEF_STATIC(FetchURL);
JS_FUNCTION_DEF_STATIC(FetchURLHash);
JS_FUNCTION_DEF_STATIC(FetchURLFile);
};
#endif /* FS_GLOBAL_H */
/* 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:
*/

View File

@ -0,0 +1,114 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsodbc.hpp -- JavaScript ODBC class header
*
*/
#ifndef FS_ODBC_H
#define FS_ODBC_H
#include "mod_v8.h"
#if defined(WIN32) && !defined(HAVE_ODBC)
#define HAVE_ODBC
#endif
#ifdef HAVE_ODBC
#include <sql.h>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4201)
#include <sqlext.h>
#pragma warning(pop)
#else
#include <sqlext.h>
#endif
#include <sqltypes.h>
/* Macros for easier V8 callback definitions */
#define JS_ODBC_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSODBC)
#define JS_ODBC_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSODBC)
#define JS_ODBC_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSODBC)
#define JS_ODBC_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSODBC)
#define JS_ODBC_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSODBC)
#define JS_ODBC_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSODBC)
#define JS_ODBC_GET_PROPERTY_IMPL_STATIC(method_name) JS_GET_PROPERTY_IMPL_STATIC(method_name, FSODBC)
#define JS_ODBC_SET_PROPERTY_IMPL_STATIC(method_name) JS_SET_PROPERTY_IMPL_STATIC(method_name, FSODBC)
#define JS_ODBC_FUNCTION_IMPL_STATIC(method_name) JS_FUNCTION_IMPL_STATIC(method_name, FSODBC)
class FSODBC : public JSBase
{
private:
switch_odbc_handle_t *_handle;
SQLHSTMT _stmt;
SQLCHAR *_colbuf;
int32_t _cblen;
std::string _dsn;
void Init();
public:
FSODBC(JSMain *owner) : JSBase(owner) { Init(); }
FSODBC(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSODBC(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
static FSODBC *New(char *dsn, char *username, char *password, const v8::FunctionCallbackInfo<v8::Value>& info);
switch_odbc_status_t Connect();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_ODBC_FUNCTION_DEF(Connect);
JS_ODBC_FUNCTION_DEF(Disconnect);
JS_ODBC_FUNCTION_DEF(Exec);
JS_ODBC_FUNCTION_DEF(Execute);
JS_ODBC_FUNCTION_DEF(NumRows);
JS_ODBC_FUNCTION_DEF(NumCols);
JS_ODBC_FUNCTION_DEF(NextRow);
JS_ODBC_FUNCTION_DEF(GetData);
JS_FUNCTION_DEF_STATIC(Close); // This will also destroy the C++ object
JS_ODBC_GET_PROPERTY_DEF(GetProperty);
};
#endif /* HAVE_ODBC */
#endif /* FS_ODBC_H */
/* 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:
*/

View File

@ -0,0 +1,81 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fspcre.hpp -- JavaScript PCRE class header
*
*/
#ifndef FS_PCRE_H
#define FS_PCRE_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_PCRE_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSPCRE)
#define JS_PCRE_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSPCRE)
#define JS_PCRE_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSPCRE)
#define JS_PCRE_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSPCRE)
#define JS_PCRE_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSPCRE)
#define JS_PCRE_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSPCRE)
class FSPCRE : public JSBase
{
private:
switch_regex_t *_re;
char *_str;
int _proceed;
int _ovector[30];
int _freed;
void Init();
public:
FSPCRE(JSMain *owner) : JSBase(owner) { Init(); }
FSPCRE(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSPCRE(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_PCRE_FUNCTION_DEF(Compile);
JS_PCRE_FUNCTION_DEF(Substitute);
JS_PCRE_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_PCRE_H */
/* 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:
*/

View File

@ -0,0 +1,81 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsrequest.hpp -- JavaScript Request class header
*
*/
#ifndef FS_REQUEST_H
#define FS_REQUEST_H
#include "javascript.hpp"
#include <switch.h>
/* Macros for easier V8 callback definitions */
#define JS_REQUEST_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSRequest)
#define JS_REQUEST_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSRequest)
#define JS_REQUEST_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSRequest)
#define JS_REQUEST_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSRequest)
#define JS_REQUEST_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSRequest)
#define JS_REQUEST_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSRequest)
class FSRequest : public JSBase
{
private:
const char *_cmd;
switch_stream_handle_t *_stream;
void Init();
public:
FSRequest(JSMain *owner) : JSBase(owner) { Init(); }
FSRequest(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSRequest(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
void Init(const char *cmd, switch_stream_handle_t *stream);
/* Methods available from JavaScript */
JS_REQUEST_FUNCTION_DEF(Write);
JS_REQUEST_FUNCTION_DEF(GetHeader);
JS_REQUEST_FUNCTION_DEF(AddHeader);
JS_REQUEST_FUNCTION_DEF(DumpEnv);
JS_REQUEST_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_REQUEST_H */
/* 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:
*/

View File

@ -0,0 +1,165 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fssession.hpp -- JavaScript Session class header
*
*/
#ifndef FS_SESSION_H
#define FS_SESSION_H
#include "javascript.hpp"
#include <switch.h>
typedef struct {
switch_speech_handle_t sh;
switch_codec_t codec;
int speaking;
} js_session_speech_t;
typedef enum {
S_HUP = (1 << 0),
} session_flag_t;
/* Macros for easier V8 callback definitions */
#define JS_SESSION_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSSession)
#define JS_SESSION_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSSession)
#define JS_SESSION_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSSession)
#define JS_SESSION_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSSession)
#define JS_SESSION_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSSession)
#define JS_SESSION_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSSession)
class FSSession : public JSBase
{
private:
switch_core_session_t *_session; // The FS session
unsigned int flags; // Flags related to this session
switch_call_cause_t _cause; // Hangup cause
v8::Persistent<v8::Function> _on_hangup;// Hangup hook
int _stack_depth;
switch_channel_state_t _hook_state;
char *_destination_number;
char *_dialplan;
char *_caller_id_name;
char *_caller_id_number;
char *_network_addr;
char *_ani;
char *_aniii;
char *_rdnis;
char *_context;
char *_username;
int _check_state;
js_session_speech_t *_speech;
void Init(void);
switch_status_t InitSpeechEngine(const char *engine, const char *voice);
void DestroySpeechEngine();
static switch_status_t CommonCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen);
static switch_status_t StreamInputCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen);
static switch_status_t RecordInputCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen);
static bool CheckHangupHook(FSSession *obj, bool *ret);
static switch_status_t HangupHook(switch_core_session_t *session);
public:
FSSession(JSMain *owner) : JSBase(owner) { Init(); }
FSSession(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSSession(void);
virtual std::string GetJSClassName();
static const js_class_definition_t *GetClassDefinition();
switch_core_session_t *GetSession();
void Init(switch_core_session_t *session, unsigned int flags);
static switch_status_t CollectInputCallback(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen);
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_SESSION_FUNCTION_DEF(Originate);
JS_SESSION_FUNCTION_DEF(SetCallerdata);
JS_SESSION_FUNCTION_DEF(SetHangupHook);
JS_SESSION_FUNCTION_DEF(SetAutoHangup);
JS_SESSION_FUNCTION_DEF(SayPhrase);
JS_SESSION_FUNCTION_DEF(StreamFile);
JS_SESSION_FUNCTION_DEF(CollectInput);
JS_SESSION_FUNCTION_DEF(RecordFile);
JS_SESSION_FUNCTION_DEF(FlushEvents);
JS_SESSION_FUNCTION_DEF(FlushDigits);
JS_SESSION_FUNCTION_DEF(Speak);
JS_SESSION_FUNCTION_DEF(SetVariable);
JS_SESSION_FUNCTION_DEF(GetVariable);
JS_SESSION_FUNCTION_DEF(GetDigits);
JS_SESSION_FUNCTION_DEF(Answer);
JS_SESSION_FUNCTION_DEF(PreAnswer);
JS_SESSION_FUNCTION_DEF(GenerateXmlCdr);
JS_SESSION_FUNCTION_DEF(Ready);
JS_SESSION_FUNCTION_DEF(Answered);
JS_SESSION_FUNCTION_DEF(MediaReady);
JS_SESSION_FUNCTION_DEF(RingReady);
JS_SESSION_FUNCTION_DEF(WaitForAnswer);
JS_SESSION_FUNCTION_DEF(WaitForMedia);
JS_SESSION_FUNCTION_DEF(GetEvent);
JS_SESSION_FUNCTION_DEF(SendEvent);
JS_SESSION_FUNCTION_DEF(Hangup);
JS_SESSION_FUNCTION_DEF(Execute);
JS_SESSION_FUNCTION_DEF(Detach);
JS_SESSION_FUNCTION_DEF(Sleep);
JS_SESSION_FUNCTION_DEF(Bridge);
JS_SESSION_GET_PROPERTY_DEF(GetProperty);
};
class FSInputCallbackState
{
public:
FSSession *session_state;
char code_buffer[1024];
size_t code_buffer_len;
char ret_buffer[1024];
int ret_buffer_len;
int digit_count;
v8::Persistent<v8::Function> function;
v8::Persistent<v8::Value> arg;
v8::Persistent<v8::Value> ret;
void *extra;
FSSession *jss_a;
FSSession *jss_b;
v8::Persistent<v8::Object> session_obj_a;
v8::Persistent<v8::Object> session_obj_b;
FSInputCallbackState(void);
~FSInputCallbackState(void);
};
#endif /* FS_SESSION_H */
/* 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:
*/

View File

@ -0,0 +1,83 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fssocket.hpp -- JavaScript Socket class header
*
*/
#ifndef FS_SOCKET_H
#define FS_SOCKET_H
#include "mod_v8.h"
/* Macros for easier V8 callback definitions */
#define JS_SOCKET_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSSocket)
#define JS_SOCKET_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSSocket)
#define JS_SOCKET_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSSocket)
#define JS_SOCKET_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSSocket)
#define JS_SOCKET_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSSocket)
#define JS_SOCKET_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSSocket)
class FSSocket : public JSBase
{
private:
switch_socket_t *_socket;
switch_memory_pool_t *_pool;
char *_read_buffer;
switch_size_t _buffer_size;
int _state;
void Init();
public:
FSSocket(JSMain *owner) : JSBase(owner) { Init(); }
FSSocket(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSSocket(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_SOCKET_FUNCTION_DEF(Connect);
JS_SOCKET_FUNCTION_DEF(Close);
JS_SOCKET_FUNCTION_DEF(Send);
JS_SOCKET_FUNCTION_DEF(ReadBytes);
JS_SOCKET_FUNCTION_DEF(Read);
JS_SOCKET_GET_PROPERTY_DEF(GetProperty);
};
#endif /* FS_SOCKET_H */
/* 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:
*/

View File

@ -0,0 +1,89 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsteletone.hpp -- JavaScript TeleTone class header
*
*/
#ifndef FS_TELETONE_H
#define FS_TELETONE_H
#include "mod_v8.h"
#include <libteletone.h>
/* Macros for easier V8 callback definitions */
#define JS_TELETONE_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSTeleTone)
#define JS_TELETONE_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSTeleTone)
#define JS_TELETONE_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSTeleTone)
#define JS_TELETONE_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSTeleTone)
#define JS_TELETONE_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSTeleTone)
#define JS_TELETONE_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSTeleTone)
class FSTeleTone : public JSBase
{
private:
teletone_generation_session_t _ts;
switch_core_session_t *_session;
switch_codec_t _codec;
switch_buffer_t *_audio_buffer;
switch_memory_pool_t *_pool;
switch_timer_t *_timer;
switch_timer_t _timer_base;
v8::Persistent<v8::Function> _function;
v8::Persistent<v8::Value> _arg;
unsigned int flags;
void Init();
public:
FSTeleTone(JSMain *owner) : JSBase(owner) { Init(); }
FSTeleTone(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSTeleTone(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
static int Handler(teletone_generation_session_t *ts, teletone_tone_map_t *map);
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_TELETONE_FUNCTION_DEF(Generate);
JS_TELETONE_FUNCTION_DEF(OnDTMF);
JS_TELETONE_FUNCTION_DEF(AddTone);
JS_TELETONE_GET_PROPERTY_DEF(GetNameProperty);
};
#endif /* FS_TELETONE_H */
/* 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:
*/

View File

@ -0,0 +1,96 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsxml.hpp -- JavaScript XML class header
*
*/
#ifndef FS_XML_H
#define FS_XML_H
#include "mod_v8.h"
/* Macros for easier V8 callback definitions */
#define JS_XML_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSXML)
#define JS_XML_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSXML)
#define JS_XML_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSXML)
#define JS_XML_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSXML)
#define JS_XML_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSXML)
#define JS_XML_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSXML)
#define JS_XML_IMPL_STATIC(method_name) JS_FUNCTION_IMPL_STATIC(method_name, FSXML)
class FSXML : public JSBase
{
private:
switch_xml_t _xml;
v8::Persistent<v8::Object> _rootJSObject; /* Always keep a reference to the root, so JS doesn't try to clean it up in GC */
FSXML *_rootObject;
switch_hash_t *_obj_hash;
switch_memory_pool_t *_pool;
void Init();
void InitRootObject();
v8::Handle<v8::Value> GetJSObjFromXMLObj(const switch_xml_t xml, const v8::FunctionCallbackInfo<v8::Value>& info);
void StoreObjectInHash(switch_xml_t xml, FSXML *obj);
FSXML *FindObjectInHash(switch_xml_t xml);
void DeleteObjectInHash(switch_xml_t xml);
void DestroyHash();
public:
FSXML(JSMain *owner) : JSBase(owner) { Init(); }
FSXML(const v8::FunctionCallbackInfo<v8::Value>& info) : JSBase(info) { Init(); }
virtual ~FSXML(void);
virtual std::string GetJSClassName();
static const v8_mod_interface_t *GetModuleInterface();
/* Methods available from JavaScript */
static void *Construct(const v8::FunctionCallbackInfo<v8::Value>& info);
JS_XML_FUNCTION_DEF(GetChild);
JS_XML_FUNCTION_DEF(AddChild);
JS_XML_FUNCTION_DEF(Next);
JS_XML_FUNCTION_DEF(GetAttribute);
JS_XML_FUNCTION_DEF(SetAttribute);
JS_FUNCTION_DEF_STATIC(Remove);
JS_XML_FUNCTION_DEF(Copy);
JS_XML_FUNCTION_DEF(Serialize);
JS_XML_GET_PROPERTY_DEF(GetNameProperty);
JS_XML_GET_PROPERTY_DEF(GetDataProperty);
JS_XML_SET_PROPERTY_DEF(SetDataProperty);
JS_XML_GET_PROPERTY_DEF(GetXmlErrorProperty);
};
#endif /* FS_XML_H */
/* 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:
*/

View File

@ -0,0 +1,356 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* javascript.hpp -- Header file for main JavaScript classes
*
*/
#ifndef V8_JAVASCRIPT_H
#define V8_JAVASCRIPT_H
#include <stdint.h>
#include <v8.h>
#include <string>
#include <vector>
#include <set>
#include <assert.h>
/* Enable this define enable V8 debugging protocol, this is not yet working */
//#define V8_ENABLE_DEBUGGING
/*
* Enable this define to force a GC after the script has finished execution.
* This is only to help debug memory leaks, and should not be needed for anything else
*/
//#define V8_FORCE_GC_AFTER_EXECUTION
/* Macro for easy V8 "get property" callback definition */
#define JS_GET_PROPERTY_DEF(method_name, class_name) \
static void method_name(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)\
{\
JS_CHECK_SCRIPT_STATE();\
class_name *obj = JSBase::GetInstance<class_name>(info.Holder());\
if (obj) {\
obj->method_name##Impl(property, info);\
} else {\
int line;\
char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\
v8::String::Utf8Value str(info.Holder());\
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\
free(file);\
info.GetReturnValue().Set(false);\
}\
}\
void method_name##Impl(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
/* Macro for easy V8 "set property" callback definition */
#define JS_SET_PROPERTY_DEF(method_name, class_name) \
static void method_name(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)\
{\
JS_CHECK_SCRIPT_STATE();\
class_name *obj = JSBase::GetInstance<class_name>(info.Holder());\
if (obj) {\
obj->method_name##Impl(property, value, info);\
} else {\
int line;\
char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\
v8::String::Utf8Value str(info.Holder());\
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\
free(file);\
info.GetReturnValue().Set(false);\
}\
}\
void method_name##Impl(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
/* Macro for easy V8 "function" callback definition */
#define JS_FUNCTION_DEF(method_name, class_name) \
static void method_name(const v8::FunctionCallbackInfo<v8::Value>& info)\
{\
JS_CHECK_SCRIPT_STATE();\
class_name *obj = JSBase::GetInstance<class_name>(info.Holder());\
if (obj) {\
obj->method_name##Impl(info);\
} else {\
int line;\
char *file = JSMain::GetStackInfo(info.GetIsolate(), &line);\
v8::String::Utf8Value str(info.Holder());\
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "mod_v8", line, NULL, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling %s\n", *str ? *str : "[unknown]", #class_name "::" #method_name "()");\
free(file);\
info.GetReturnValue().Set(false);\
}\
}\
void method_name##Impl(const v8::FunctionCallbackInfo<v8::Value>& info)
/* Macros for V8 callback implementations */
#define JS_GET_PROPERTY_IMPL(method_name, class_name) void class_name::method_name##Impl(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
#define JS_SET_PROPERTY_IMPL(method_name, class_name) void class_name::method_name##Impl(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
#define JS_FUNCTION_IMPL(method_name, class_name) void class_name::method_name##Impl(const v8::FunctionCallbackInfo<v8::Value>& info)
/* Macros for V8 callback definitions (class static version) */
#define JS_GET_PROPERTY_DEF_STATIC(method_name) static void method_name(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
#define JS_SET_PROPERTY_DEF_STATIC(method_name) static void method_name(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
#define JS_FUNCTION_DEF_STATIC(method_name) static void method_name(const v8::FunctionCallbackInfo<v8::Value>& info)
/* Macros for V8 callback implementations (class static version) */
#define JS_GET_PROPERTY_IMPL_STATIC(method_name, class_name) void class_name::method_name(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
#define JS_SET_PROPERTY_IMPL_STATIC(method_name, class_name) void class_name::method_name(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
#define JS_FUNCTION_IMPL_STATIC(method_name, class_name) void class_name::method_name(const v8::FunctionCallbackInfo<v8::Value>& info)
/* Macro for basic script state check (to know if the script is being terminated), should be called before calling any callback actual code */
#define JS_CHECK_SCRIPT_STATE() \
if (v8::V8::IsExecutionTerminating(info.GetIsolate())) return;\
if (JSMain::GetScriptInstanceFromIsolate(info.GetIsolate()) && JSMain::GetScriptInstanceFromIsolate(info.GetIsolate())->GetForcedTermination()) return
/* strdup function for all platforms */
#ifdef NDEBUG
#if (_MSC_VER >= 1500) // VC9+
#define js_strdup(ptr, s) (void)( (!!(ptr = _strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#else
#define js_strdup(ptr, s) (void)( (!!(ptr = strdup(s))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%d", __FILE__, __LINE__),abort(), 0), ptr)
#endif
#else
#if (_MSC_VER >= 1500) // VC9+
#define js_strdup(ptr, s) (void)(assert(((ptr) = _strdup(s))),ptr);__analysis_assume( ptr )
#else
#define js_strdup(ptr, s) (void)(assert(((ptr) = strdup((s)))),ptr)
#endif
#endif
/* Makes sure to return a valid char pointer */
#define js_safe_str(s) (s ? s : "")
/* JS Constructor callback definition */
typedef void * void_pointer_t;
typedef void_pointer_t (*ConstructorCallback)(const v8::FunctionCallbackInfo<v8::Value>& info);
/* JS Function definition */
typedef struct {
const char *name; /* Name of the function */
v8::FunctionCallback func; /* Function callback */
} js_function_t;
/* JS Property definition */
typedef struct {
const char *name; /* Name of the property */
v8::AccessorGetterCallback get; /* The property getter */
v8::AccessorSetterCallback set; /* The property setter */
} js_property_t;
/* JS Class definition */
typedef struct {
const char *name; /* The name of the class */
ConstructorCallback constructor; /* The constructor definition */
const js_function_t *functions; /* An array of function definitions */
const js_property_t *properties; /* An array of property definitions */
} js_class_definition_t;
/* Import/export definitions (used by extra loadable modules) */
#ifdef WIN32
/* WIN32 */
#ifdef JSMOD_IMPORT
#define JSMOD_EXPORT __declspec(dllimport)
#else
#define JSMOD_EXPORT __declspec(dllexport)
#endif
#else
/* Not WIN32 */
#ifdef JSMOD_IMPORT
#define JSMOD_EXPORT
#else
#if (HAVE_VISIBILITY != 1)
#define JSMOD_EXPORT
#else
#define JSMOD_EXPORT __attribute__ ((visibility("default")))
#endif
#endif
#endif
/* JSMain class prototype */
class JSMOD_EXPORT JSMain;
/* Base class used by all C++ classes implemented in JS */
class JSMOD_EXPORT JSBase
{
private:
v8::Persistent<v8::Object> *persistentHandle; /* The persistent handle of the JavaScript object for this instance */
bool autoDestroy; /* flag to tell if this instance should be auto destroyed during JavaScript GC */
JSMain *js; /* The "owner" of this instance */
/* The callback that happens when the V8 GC cleans up object instances */
static void WeakCallback(const v8::WeakCallbackData<v8::Object, JSBase>& data);
/* Internal basic constructor when creating a new instance from JS. It will call the actual user code inside */
static void CreateInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
/* Store a C++ instance to a JS object's private data */
static void AddInstance(v8::Isolate *isolate, const v8::Handle<v8::Object>& handle, const v8::Handle<v8::External>& object, bool autoDestroy);
public:
JSBase(JSMain *owner);
JSBase(const v8::FunctionCallbackInfo<v8::Value>& info);
virtual ~JSBase(void);
/* Returns the JS object related to the C++ instance */
v8::Handle<v8::Object> GetJavaScriptObject();
/* Register a C++ class inside V8 (must be called within a entered isolate, and context) */
static void Register(v8::Isolate *isolate, const js_class_definition_t *desc);
/* Register an existing C++ class instance inside V8 (must be called within a entered isolate, and context) */
void RegisterInstance(v8::Isolate *isolate, std::string name, bool autoDestroy);
/* Get a JSBase instance from JavaScript callback arguments */
template <typename T> static T *GetInstance(const v8::FunctionCallbackInfo<v8::Value>& info)
{
v8::HandleScope scope(info.GetIsolate());
return GetInstance<T>(info.Holder());
}
/* Get a JSBase instance from a JavaScript object */
template <typename T> static T *GetInstance(const v8::Local<v8::Object>& self)
{
v8::Local<v8::Value> val = self->GetInternalField(0);
if (!val.IsEmpty() && val->IsExternal()) {
v8::Local<v8::External> wrap = v8::Local<v8::External>::Cast(val);
JSBase *ptr = static_cast<JSBase*>(wrap->Value());
return dynamic_cast<T*>(ptr); /* If we're trying to cast to the wrong type, dynamic_cast will return NULL */
} else {
return NULL;
}
}
/* Get a JavaScript function from a JavaScript argument (can be either a string or the actual function) */
static v8::Handle<v8::Function> GetFunctionFromArg(v8::Isolate *isolate, const v8::Local<v8::Value>& arg);
/* Default JS setter callback, to be used for read only values */
static void DefaultSetProperty(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);
/* Get the name of the JavaScript class - must be overridden by the actual implementation */
virtual std::string GetJSClassName() = 0;
/* Get the JavaScript class instance that owns this instance */
JSMain *GetOwner();
/* Get the JavaScript isolate that's active for the current context */
v8::Isolate *GetIsolate();
/* Get autoDestroy variable */
bool GetAutoDestroy();
};
/* Definition of the class registration method */
typedef void (*JSExtenderRegisterMethod)(js_class_definition_t *class_definition);
/* The struct holding a C++ class instance, to be used in JS */
typedef struct {
JSBase *obj; /* The class instance to be used in JS */
char *name; /* The name of the instance within JS */
bool auto_destroy; /* Flag to know if the instance should be auto destroyed when not needed by JS anymore */
} registered_instance_t;
/* Main class for executing a V8 JavaScript */
class JSMOD_EXPORT JSMain
{
private:
v8::Isolate* isolate; /* The V8 isolate for this script instance */
std::vector<const js_class_definition_t *> *extenderClasses;/* List holding C++ classes to be registered in JS on execution */
std::vector<js_function_t *> *extenderFunctions; /* List holding C++ functions to be registered in JS on execution */
std::vector<registered_instance_t*> *extenderInstances; /* List holding C++ class instances to be registered in JS on execution */
std::set<JSBase *> *activeInstances; /* List holding all active instances right now (in a running script) */
bool forcedTermination; /* Is set to true if script is triggering a forced termination of the script */
char *forcedTerminationMessage; /* The message given during forced termination */
int forcedTerminationLineNumber; /* The JS line number that called the exit function */
char *forcedTerminationScriptFile; /* The JS script file that called the exit function */
/* Internal Log function accessable from JS - used just for testing */
static void Log(const v8::FunctionCallbackInfo<v8::Value>& args);
public:
JSMain(void);
~JSMain(void);
void AddJSExtenderFunction(v8::FunctionCallback func, const std::string& name); /* Add a C++ function to be registered when running the script */
void AddJSExtenderClass(const js_class_definition_t *method); /* Add a C++ class to be registered when running the script */
void AddJSExtenderInstance(JSBase *instance, const std::string& objectName, bool autoDestroy); /* Add a C++ class instance to be registered when running the script */
static JSMain *GetScriptInstanceFromIsolate(v8::Isolate* isolate); /* Get the JavaScript C++ instance from a V8 isolate */
v8::Isolate *GetIsolate(); /* Get the V8 isolate from the current instance */
const std::string ExecuteScript(const std::string& filename, bool *resultIsError);
const std::string ExecuteString(const std::string& scriptData, const std::string& fileName, bool *resultIsError);
static void Initialize(); /* Initialize the V8 engine */
static void Dispose(); /* Deinitialize the V8 engine */
static void Include(const v8::FunctionCallbackInfo<v8::Value>& args); /* Adds functionality to include another JavaScript from the running script */
static void Version(const v8::FunctionCallbackInfo<v8::Value>& args); /* Internal Version function accessable from JS - used to get the current V( version */
static const std::string GetExceptionInfo(v8::Isolate* isolate, v8::TryCatch* try_catch); /* Get the exception information from a V8 TryCatch instance */
const std::vector<const js_class_definition_t *>& GetExtenderClasses() const;/* Returns the list of class definitions */
const std::vector<js_function_t *>& GetExtenderFunctions() const; /* Returns the list of function definitions */
const std::vector<registered_instance_t*>& GetExtenderInstances() const; /* Returns the list of class instance definitions */
/* Methods to keep track of all created C++ instances within JS */
void AddActiveInstance(JSBase *obj);
void RemoveActiveInstance(JSBase *obj);
void DisposeActiveInstances();
static bool FileExists(const char *file);
static const std::string LoadFileToString(const std::string& filename);
/* Data related to forced script termination */
bool GetForcedTermination(void);
void ResetForcedTermination(void);
const char *GetForcedTerminationMessage(void);
const char *GetForcedTerminationScriptFile(void);
int GetForcedTerminationLineNumber(void);
/* Method to force termination of a script */
static void ExitScript(v8::Isolate *isolate, const char *msg);
/* Get the filename and line number of the current JS stack */
static char *GetStackInfo(v8::Isolate *isolate, int *lineNumber);
};
#ifdef V8_ENABLE_DEBUGGING
void V8DispatchDebugMessages();
#endif
#endif /* V8_JAVASCRIPT_H */
/* 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:
*/

View File

@ -0,0 +1,225 @@
<?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_v8</ProjectName>
<ProjectGuid>{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}</ProjectGuid>
<RootNamespace>mod_v8</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" />
<Import Project="..\..\..\..\w32\v8.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\v8.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\v8.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\v8.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<ImportLibrary>$(Platform)\$(Configuration)\$(ProjectName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
</ClCompile>
<Link>
<ImportLibrary>$(Platform)\$(Configuration)\$(ProjectName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<ImportLibrary>$(Platform)\$(Configuration)\$(ProjectName).lib</ImportLibrary>
<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>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<ImportLibrary>$(Platform)\$(Configuration)\$(ProjectName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include=".\src\jsmain.cpp" />
<ClCompile Include=".\src\jsbase.cpp" />
<ClCompile Include=".\src\fscoredb.cpp" />
<ClCompile Include=".\src\fscurl.cpp" />
<ClCompile Include=".\src\fsdtmf.cpp" />
<ClCompile Include=".\src\fsevent.cpp" />
<ClCompile Include=".\src\fsfileio.cpp" />
<ClCompile Include=".\src\fsodbc.cpp" />
<ClCompile Include=".\src\fspcre.cpp" />
<ClCompile Include=".\src\fsrequest.cpp" />
<ClCompile Include=".\src\fssession.cpp" />
<ClCompile Include=".\src\fssocket.cpp" />
<ClCompile Include=".\src\fsglobal.cpp" />
<ClCompile Include=".\src\fsteletone.cpp" />
<ClCompile Include="mod_v8.cpp" />
<ClCompile Include="src\fsfile.cpp" />
<ClCompile Include="src\fsxml.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include=".\include\javascript.hpp" />
<ClInclude Include=".\include\fscoredb.hpp" />
<ClInclude Include=".\include\fscurl.hpp" />
<ClInclude Include=".\include\fsdtmf.hpp" />
<ClInclude Include=".\include\fsevent.hpp" />
<ClInclude Include=".\include\fsfileio.hpp" />
<ClInclude Include=".\include\fsodbc.hpp" />
<ClInclude Include=".\include\fspcre.hpp" />
<ClInclude Include=".\include\fsrequest.hpp" />
<ClInclude Include=".\include\fssession.hpp" />
<ClInclude Include=".\include\fssocket.hpp" />
<ClInclude Include=".\include\fsglobal.hpp" />
<ClInclude Include=".\include\fsteletone.hpp" />
<ClInclude Include="include\fsfile.hpp" />
<ClInclude Include="include\fsxml.hpp" />
<ClInclude Include="mod_v8.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\libteletone\libteletone.2012.vcxproj">
<Project>{89385c74-5860-4174-9caf-a39e7c48909c}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\libs\win32\v8\libv8.2012.vcxproj">
<Project>{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}</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>

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="mod_v8.cpp" />
<ClCompile Include=".\src\jsmain.cpp">
<Filter>BaseClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\jsbase.cpp">
<Filter>BaseClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fscoredb.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fscurl.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsdtmf.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsevent.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include="src\fsfile.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsfileio.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsglobal.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsodbc.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fspcre.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsrequest.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fssession.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fssocket.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include=".\src\fsteletone.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
<ClCompile Include="src\fsxml.cpp">
<Filter>FSClasses</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mod_v8.h" />
<ClInclude Include=".\include\javascript.hpp">
<Filter>BaseClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fscoredb.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fscurl.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsdtmf.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsevent.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include="include\fsfile.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsfileio.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsglobal.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsodbc.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fspcre.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsrequest.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fssession.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fssocket.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include=".\include\fsteletone.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
<ClInclude Include="include\fsxml.hpp">
<Filter>FSClasses\include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="BaseClasses">
<UniqueIdentifier>{57f55a0b-1790-4632-95e6-19acbe9015d3}</UniqueIdentifier>
</Filter>
<Filter Include="FSClasses">
<UniqueIdentifier>{dcda9b2f-890a-4820-84e3-4bbcf8f0b62c}</UniqueIdentifier>
</Filter>
<Filter Include="FSClasses\include">
<UniqueIdentifier>{ed9652cf-79bd-4567-9a98-1ed5077d5805}</UniqueIdentifier>
</Filter>
<Filter Include="BaseClasses\include">
<UniqueIdentifier>{3efc073f-f052-4e3d-921c-8d6b6a5a7215}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -0,0 +1,779 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 ported from 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* mod_v8.cpp -- JavaScript FreeSWITCH module
*
*/
/*
* This module executes JavaScript using Google's V8 JavaScript engine.
*
* It extends the available JavaScript classes with the following FS related classes;
* CoreDB Adds features to access the core DB (SQLite) in FreeSWITCH. (on request only)
* CURL Adds some extra methods for CURL access. (on request only)
* DTMF Object that holds information about a DTMF event.
* Event Object that holds information about a FreeSWITCH event.
* File Class to reflect the Spidermonkey built-in class "File". Not yet implemented! (on request only)
* FileIO Simple class for basic file IO.
* ODBC Adds features to access any ODBC available database in the system. (on request only)
* PCRE Adds features to do regexp using the PCRE implementeation.
* Request Class for extra features during API call from FS (using 'jsapi' function). This class cannot be constructed from JS code!
* The Request class is only availble when started from 'jsapi' FS command, and only inside the predefined variable 'request'.
* Session Main FS class, includes all functions to handle a session.
* Socket Class for communicating over a TCP/IP socket. (on request only)
* TeleTone Class used to play tones to a FS channel. (on request only)
* XML XML parsing class, using the features from switch_xml. (on request only)
*
* Some of the classes above are available on request only, using the command [use('Class');] before using the class for the first time.
*
* It also adds quite a few global functions, directly available for the user (see fsglobal.cpp for the implementation).
*
* Depedning on how the script was started from FreeSWITCH, some variables might be defined already;
* session If the script is started from the dialplan, the variable 'session' holds the session for the current call.
* request If the script is started using 'jsapi' function, the variable 'request' is an instance of the Request class.
* message If the script is started as a chat application, the actual FreeSWITCH event will be available in the variable 'message'.
*
* All classes are implemented in a pair of hpp/cpp files, named after the class. For instance; class "File" is implemented in fsfile.cpp.
*
*/
#include "mod_v8.h"
#include <fstream>
#ifdef V8_ENABLE_DEBUGGING
#include <v8-debug.h>
#endif
/* Global JavaScript functions */
#include "fsglobal.hpp"
/* Common JavaScript classes */
#include "fsrequest.hpp" /* Only loaded during 'jsapi' call */
#include "fspcre.hpp"
#include "fsevent.hpp"
#include "fssession.hpp"
#include "fsdtmf.hpp"
#include "fsfileio.hpp"
/* Optional JavaScript classes (loaded on demand) */
#include "fscoredb.hpp"
#include "fscurl.hpp"
#include "fsteletone.hpp"
#include "fssocket.hpp"
#include "fsodbc.hpp"
#include "fsxml.hpp"
#include "fsfile.hpp"
using namespace std;
using namespace v8;
SWITCH_BEGIN_EXTERN_C
/* FreeSWITCH module load definitions */
SWITCH_MODULE_LOAD_FUNCTION(mod_v8_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_v8_shutdown);
SWITCH_MODULE_DEFINITION_EX(mod_v8, mod_v8_load, mod_v8_shutdown, NULL, SMODF_GLOBAL_SYMBOLS);
/* API interfaces */
static switch_api_interface_t *jsrun_interface = NULL;
static switch_api_interface_t *jsapi_interface = NULL;
/* Module manager for loadable modules */
module_manager_t module_manager = { 0 };
/* Loadable module struct */
typedef struct {
char *filename;
void *lib;
const v8_mod_interface_t *module_interface;
v8_mod_init_t v8_mod_init;
} v8_loadable_module_t;
#ifdef V8_ENABLE_DEBUGGING
static bool debug_enable_callback = false;
static int debug_listen_port = 9999;
static bool debug_wait_for_connection = true;
static bool debug_manual_break = true;
#endif
using namespace v8;
static switch_status_t v8_mod_init_built_in(const v8_mod_interface_t *mod_interface)
{
switch_assert(mod_interface);
switch_core_hash_insert(module_manager.load_hash, (char *) mod_interface->name, mod_interface);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Successfully Loaded [%s]\n", mod_interface->name);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t v8_mod_load_file(const char *filename)
{
v8_loadable_module_t *module = NULL;
switch_dso_lib_t dso = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_loadable_module_function_table_t *function_handle = NULL;
v8_mod_init_t v8_mod_init = NULL;
const v8_mod_interface_t *module_interface = NULL, *mp;
char *derr = NULL;
const char *err = NULL;
switch_assert(filename != NULL);
if (!(dso = switch_dso_open(filename, 1, &derr))) {
status = SWITCH_STATUS_FALSE;
}
if (derr || status != SWITCH_STATUS_SUCCESS) {
err = derr;
goto err;
}
function_handle = (switch_loadable_module_function_table_t *)switch_dso_data_sym(dso, "v8_mod_init", &derr);
if (!function_handle || derr) {
status = SWITCH_STATUS_FALSE;
err = derr;
goto err;
}
v8_mod_init = (v8_mod_init_t) (intptr_t) function_handle;
if (v8_mod_init == NULL) {
err = "Cannot Load";
goto err;
}
if (v8_mod_init(&module_interface) != SWITCH_STATUS_SUCCESS) {
err = "Module load routine returned an error";
goto err;
}
if (!(module = (v8_loadable_module_t *) switch_core_permanent_alloc(sizeof(*module)))) {
err = "Could not allocate memory\n";
}
err:
if (err || !module) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Loading module %s\n**%s**\n", filename, switch_str_nil(err));
switch_safe_free(derr);
return SWITCH_STATUS_GENERR;
}
module->filename = switch_core_permanent_strdup(filename);
module->v8_mod_init = v8_mod_init;
module->module_interface = module_interface;
module->lib = dso;
if ((mp = module->module_interface)) {
switch_core_hash_insert(module_manager.load_hash, (char *) mp->name, (void *) mp);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Successfully Loaded [%s]\n", module->filename);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t v8_load_module(const char *dir, const char *fname)
{
switch_size_t len = 0;
char *path;
char *file;
#ifdef WIN32
const char *ext = ".dll";
#else
const char *ext = ".so";
#endif
if ((file = switch_core_strdup(module_manager.pool, fname)) == 0) {
return SWITCH_STATUS_FALSE;
}
if (*file == '/') {
path = switch_core_strdup(module_manager.pool, file);
} else {
if (strchr(file, '.')) {
len = strlen(dir);
len += strlen(file);
len += 4;
path = (char *) switch_core_alloc(module_manager.pool, len);
switch_snprintf(path, len, "%s%s%s", dir, SWITCH_PATH_SEPARATOR, file);
} else {
len = strlen(dir);
len += strlen(file);
len += 8;
path = (char *) switch_core_alloc(module_manager.pool, len);
switch_snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext);
}
}
return v8_mod_load_file(path);
}
SWITCH_END_EXTERN_C
static switch_status_t load_modules(void)
{
const char *cf = "v8.conf";
switch_xml_t cfg, xml;
unsigned int count = 0;
#ifdef WIN32
const char *ext = ".dll";
const char *EXT = ".DLL";
#elif defined (MACOSX) || defined (DARWIN)
const char *ext = ".dylib";
const char *EXT = ".DYLIB";
#else
const char *ext = ".so";
const char *EXT = ".SO";
#endif
memset(&module_manager, 0, sizeof(module_manager));
switch_core_new_memory_pool(&module_manager.pool);
switch_core_hash_init(&module_manager.load_hash, module_manager.pool);
if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_xml_t mods, ld;
if ((mods = switch_xml_child(cfg, "modules"))) {
for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) {
const char *val = switch_xml_attr_soft(ld, "module");
if (!zstr(val) && strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val);
continue;
}
v8_load_module(SWITCH_GLOBAL_dirs.mod_dir, val);
count++;
}
}
switch_xml_free(xml);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Open of %s failed\n", cf);
}
return SWITCH_STATUS_SUCCESS;
}
static int env_init(JSMain *js)
{
/* Init all "global" functions first */
const js_function_t *fs_proc = FSGlobal::GetFunctionDefinitions();
for (int i = 0; fs_proc[i].name && fs_proc[i].func; i++) {
js->AddJSExtenderFunction(fs_proc[i].func, fs_proc[i].name);
}
/* Init all basic classes made available from FreeSWITCH */
js->AddJSExtenderClass(FSSession::GetClassDefinition());
js->AddJSExtenderClass(FSFileIO::GetClassDefinition());
js->AddJSExtenderClass(FSEvent::GetClassDefinition());
js->AddJSExtenderClass(FSDTMF::GetClassDefinition());
js->AddJSExtenderClass(FSPCRE::GetClassDefinition());
/* To add a class that will always be available inside JS, add the definition here */
return 1;
}
static void v8_error(Isolate* isolate, TryCatch* try_catch)
{
HandleScope handle_scope(isolate);
String::Utf8Value exception(try_catch->Exception());
const char *exception_string = js_safe_str(*exception);
Handle<Message> message = try_catch->Message();
const char *msg = "";
string filename = __FILE__;
int line = __LINE__;
string text = "";
JSMain *js = JSMain::GetScriptInstanceFromIsolate(isolate);
if (js && js->GetForcedTermination()) {
js->ResetForcedTermination();
switch_log_printf(SWITCH_CHANNEL_ID_LOG, js->GetForcedTerminationScriptFile(), modname, js->GetForcedTerminationLineNumber(), NULL, SWITCH_LOG_NOTICE, "Script exited with info [%s]\n", js->GetForcedTerminationMessage());
return;
}
if (!message.IsEmpty()) {
String::Utf8Value fname(message->GetScriptResourceName());
if (*fname) {
filename = *fname;
}
line = message->GetLineNumber();
msg = exception_string;
String::Utf8Value sourceline(message->GetSourceLine());
if (*sourceline) {
text = *sourceline;
}
} else {
msg = exception_string;
}
if (!msg) {
msg = "";
}
if (text.length() > 0) {
switch_log_printf(SWITCH_CHANNEL_ID_LOG, filename.c_str(), modname, line, NULL, SWITCH_LOG_ERROR, "Exception: %s (near: \"%s\")\n", msg, text.c_str());
} else {
switch_log_printf(SWITCH_CHANNEL_ID_LOG, filename.c_str(), modname, line, NULL, SWITCH_LOG_ERROR, "Exception: %s\n", msg);
}
}
static char *v8_get_script_path(const char *script_file)
{
const char *p;
char *ret = NULL;
const char delims[] = "/\\";
const char *i;
if (script_file) {
for (i = delims; *i; i++) {
if ((p = strrchr(script_file, *i))) {
js_strdup(ret, script_file);
*(ret + (p - script_file)) = '\0';
return ret;
}
}
js_strdup(ret, ".");
return ret;
} else {
return NULL;
}
}
static int v8_parse_and_execute(switch_core_session_t *session, const char *input_code, switch_stream_handle_t *api_stream, switch_event_t *message)
{
string res;
JSMain *js;
Isolate *isolate;
char *arg, *argv[512];
int argc = 0, x = 0, y = 0;
unsigned int flags = 0;
char *path = NULL;
string result_string;
int result = 0;
if (zstr(input_code)) {
return -1;
}
js = new JSMain();
isolate = js->GetIsolate();
env_init(js);
/* Try to read lock the session first */
if (session) {
if (switch_core_session_read_lock_hangup(session) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read Lock Failure.\n");
session = NULL;
}
}
/* Execute the actual script */
//isolate->Enter();
{
Locker lock(isolate);
Isolate::Scope iscope(isolate);
{
const char *script;
// Create a stack-allocated handle scope.
HandleScope scope(isolate);
// Store our object internally
isolate->SetData(0, js);
// New global template
Handle<ObjectTemplate> global = ObjectTemplate::New();
if (global.IsEmpty()) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create JS global object template\n");
} else {
/* Function to print current V8 version */
global->Set(String::NewFromUtf8(isolate, "version"), FunctionTemplate::New(isolate, JSMain::Version));
/* Add all global functions */
for (size_t i = 0; i < js->GetExtenderFunctions().size(); i++) {
js_function_t *proc = js->GetExtenderFunctions()[i];
global->Set(String::NewFromUtf8(isolate, proc->name), FunctionTemplate::New(isolate, proc->func));
}
// Create a new context.
Local<Context> context = Context::New(isolate, NULL, global);
if (context.IsEmpty()) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create JS context\n");
} else {
// Enter the created context for compiling and running the script.
Context::Scope context_scope(context);
#ifdef V8_ENABLE_DEBUGGING
Persistent<Context> *debug_context = new Persistent<Context>();
isolate->SetData(1, debug_context);
debug_context->Reset(isolate, context);
//v8::Locker lck(isolate);
if (debug_enable_callback) {
Debug::SetDebugMessageDispatchHandler(V8DispatchDebugMessages, true);
}
if (debug_listen_port > 0) {
char *name = switch_mprintf("mod_v8-%d", (int)switch_thread_self());
Debug::EnableAgent(name, debug_listen_port, debug_wait_for_connection);
switch_safe_free(name);
}
#endif
/* Register all plugin classes */
for (size_t i = 0; i < js->GetExtenderClasses().size(); i++) {
JSBase::Register(isolate, js->GetExtenderClasses()[i]);
}
/* Register all instances of specific plugin classes */
for (size_t i = 0; i < js->GetExtenderInstances().size(); i++) {
registered_instance_t *inst = js->GetExtenderInstances()[i];
inst->obj->RegisterInstance(isolate, inst->name, inst->auto_destroy);
}
/* Emaculent conception of session object into the script if one is available */
if (session) {
FSSession *obj = new FSSession(js);
obj->Init(session, flags);
obj->RegisterInstance(isolate, "session", true);
} else {
/* Add a session object as a boolean instead, just to make it safe to check if it exists as expected */
context->Global()->Set(String::NewFromUtf8(isolate, "session"), Boolean::New(isolate, false));
}
if (message) {
FSEvent::New(message, "message", js);
}
if (api_stream) {
/* The JS class "Request" is only needed when a api_stream object is passed here */
JSBase::Register(isolate, FSRequest::GetClassDefinition());
FSRequest *ptr = new FSRequest(js);
ptr->Init(input_code, api_stream);
ptr->RegisterInstance(isolate, "request", true);
}
script = input_code;
if (*script != '~') {
if ((arg = (char *)strchr(script, ' '))) {
*arg++ = '\0';
argc = switch_separate_string(arg, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
// Add arguments before running script.
Local<Array> arguments = Array::New(isolate, argc);
for (y = 0; y < argc; y++) {
arguments->Set(Integer::New(isolate, y), String::NewFromUtf8(isolate, argv[y]));
}
context->Global()->Set(String::NewFromUtf8(isolate, "argv"), arguments);
context->Global()->Set(String::NewFromUtf8(isolate, "argc"), Integer::New(isolate, argc));
}
const char *script_data = NULL;
const char *script_file = NULL;
string s;
if (*script == '~') {
script_data = script + 1;
script_file = "inline";
} else {
const char *script_name = NULL;
if (switch_is_file_path(script)) {
script_name = script;
} else if ((path = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR, script))) {
script_name = path;
}
if (script_name) {
if (JSMain::FileExists(script_name)) {
s = JSMain::LoadFileToString(script_name);
script_data = s.c_str();
script_file = script_name;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Open File: %s\n", script_name);
}
}
}
if (!script_data) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No script to execute!\n");
} else {
/* Store our base directoy in variable 'scriptPath' */
char *path = v8_get_script_path(script_file);
if (path) {
context->Global()->Set(String::NewFromUtf8(isolate, "scriptPath"), String::NewFromUtf8(isolate, path));
free(path);
}
// Create a string containing the JavaScript source code.
Handle<String> source = String::NewFromUtf8(isolate, script_data);
TryCatch try_catch;
// Compile the source code.
Handle<Script> v8_script = Script::Compile(source, Handle<Value>::New(isolate, String::NewFromUtf8(isolate, script_file)));
if (try_catch.HasCaught()) {
v8_error(isolate, &try_catch);
} else {
// Run the script
#ifdef V8_ENABLE_DEBUGGING
/* Break before we actually start executing the script */
if (debug_manual_break) {
Debug::DebugBreak(isolate);
}
#endif
Handle<Value> result = v8_script->Run();
if (try_catch.HasCaught()) {
v8_error(isolate, &try_catch);
} else {
if (js->GetForcedTermination()) {
js->ResetForcedTermination();
switch_log_printf(SWITCH_CHANNEL_ID_LOG, js->GetForcedTerminationScriptFile(), modname, js->GetForcedTerminationLineNumber(), NULL, SWITCH_LOG_NOTICE, "Script exited with info [%s]\n", js->GetForcedTerminationMessage());
}
if (!result.IsEmpty()) {
// Return result as string
String::Utf8Value ascii(result);
if (*ascii) {
res = *ascii;
}
}
}
}
#ifndef V8_FORCE_GC_AFTER_EXECUTION
/* Clear up all destroyable C++ instances */
js->DisposeActiveInstances();
#endif
}
#ifdef V8_ENABLE_DEBUGGING
isolate->SetData(1, NULL);
if (debug_listen_port > 0) {
Debug::DisableAgent();
}
debug_context->Reset();
delete debug_context;
#endif
}
}
isolate->SetData(0, NULL);
}
#ifdef V8_FORCE_GC_AFTER_EXECUTION
/* Force GC to run. This should not be needed, but is left here for reference */
V8::ContextDisposedNotification();
while (!V8::IdleNotification()) {}
js->DisposeActiveInstances();
#endif
}
//isolate->Exit();
if (res.length() == 0) {
result = -1;
} else {
result = 0;
if (strcasecmp(res.c_str(), "undefined")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Javascript result: [%s]\n", res.c_str());
}
}
switch_safe_free(path);
delete js;
return result;
}
SWITCH_BEGIN_EXTERN_C
SWITCH_STANDARD_APP(v8_dp_function)
{
v8_parse_and_execute(session, data, NULL, NULL);
}
SWITCH_STANDARD_CHAT_APP(v8_chat_function)
{
v8_parse_and_execute(NULL, data, NULL, message);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_END_EXTERN_C
typedef struct {
switch_memory_pool_t *pool;
char *code;
} v8_task_t;
static void *SWITCH_THREAD_FUNC v8_thread_run(switch_thread_t *thread, void *obj)
{
v8_task_t *task = (v8_task_t *) obj;
switch_memory_pool_t *pool;
v8_parse_and_execute(NULL, task->code, NULL, NULL);
if ((pool = task->pool)) {
switch_core_destroy_memory_pool(&pool);
}
return NULL;
}
static void v8_thread_launch(const char *text)
{
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
v8_task_t *task;
switch_memory_pool_t *pool;
if (zstr(text)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "missing required input!\n");
return;
}
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
return;
}
task = (v8_task_t *)switch_core_alloc(pool, sizeof(*task));
task->pool = pool;
task->code = switch_core_strdup(pool, text);
switch_threadattr_create(&thd_attr, pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&thread, thd_attr, v8_thread_run, task, pool);
}
SWITCH_BEGIN_EXTERN_C
SWITCH_STANDARD_API(jsapi_function)
{
char *path_info = NULL;
if (stream->param_event) {
path_info = switch_event_get_header(stream->param_event, "http-path-info");
}
if (zstr(cmd) && path_info) {
cmd = path_info;
}
if (zstr(cmd)) {
stream->write_function(stream, "USAGE: %s\n", jsapi_interface->syntax);
return SWITCH_STATUS_SUCCESS;
}
v8_parse_and_execute(session, (char *) cmd, stream, NULL);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(launch_async)
{
if (zstr(cmd)) {
stream->write_function(stream, "USAGE: %s\n", jsrun_interface->syntax);
return SWITCH_STATUS_SUCCESS;
}
v8_thread_launch(cmd);
stream->write_function(stream, "+OK\n");
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_v8_load)
{
switch_application_interface_t *app_interface;
switch_chat_application_interface_t *chat_app_interface;
if (load_modules() != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
JSMain::Initialize();
/* Make all "built in" modules available to load on demand */
v8_mod_init_built_in(FSCoreDB::GetModuleInterface());
v8_mod_init_built_in(FSCURL::GetModuleInterface());
#ifdef HAVE_ODBC
/* Only add ODBC class if ODBC is available in the system */
v8_mod_init_built_in(FSODBC::GetModuleInterface());
#endif
v8_mod_init_built_in(FSSocket::GetModuleInterface());
v8_mod_init_built_in(FSTeleTone::GetModuleInterface());
v8_mod_init_built_in(FSXML::GetModuleInterface());
v8_mod_init_built_in(FSFile::GetModuleInterface());
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(jsrun_interface, "jsrun", "run a script", launch_async, "jsrun <script> [additional_vars [...]]");
SWITCH_ADD_API(jsapi_interface, "jsapi", "execute an api call", jsapi_function, "jsapi <script> [additional_vars [...]]");
SWITCH_ADD_APP(app_interface, "javascript", "Launch JS ivr", "Run a javascript ivr on a channel", v8_dp_function, "<script> [additional_vars [...]]", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_CHAT_APP(chat_app_interface, "javascript", "execute a js script", "execute a js script", v8_chat_function, "<script>", SCAF_NONE);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_NOUNLOAD;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_v8_shutdown)
{
switch_core_hash_destroy(&module_manager.load_hash);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_END_EXTERN_C
/* 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:
*/

View File

@ -0,0 +1,72 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 ported from 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_v8.h -- JavaScript FreeSWITCH module header file
*
*/
#ifndef MOD_V8_H
#define MOD_V8_H
#include "javascript.hpp"
#include <switch.h>
SWITCH_BEGIN_EXTERN_C
#define JS_BUFFER_SIZE 1024 * 32
#define JS_BLOCK_SIZE JS_BUFFER_SIZE
typedef switch_status_t (*v8_mod_load_t) (const v8::FunctionCallbackInfo<v8::Value>& info);
typedef struct {
const char *name;
v8_mod_load_t v8_mod_load;
} v8_mod_interface_t;
typedef switch_status_t (*v8_mod_init_t) (const v8_mod_interface_t **module_interface);
typedef struct {
switch_hash_t *load_hash;
switch_memory_pool_t *pool;
} module_manager_t;
extern module_manager_t module_manager;
SWITCH_END_EXTERN_C
#endif /* MOD_V8_H */
/* 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:
*/

View File

@ -0,0 +1,212 @@
<?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_v8_skel</ProjectName>
<ProjectGuid>{8B754330-A434-4791-97E5-1EE67060BAC0}</ProjectGuid>
<RootNamespace>mod_v8_skel</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\winlibs.props" />
<Import Project="..\..\..\..\w32\module_release.props" />
<Import Project="..\..\..\..\w32\v8.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\winlibs.props" />
<Import Project="..\..\..\..\w32\module_debug.props" />
<Import Project="..\..\..\..\w32\v8.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\winlibs.props" />
<Import Project="..\..\..\..\w32\module_release.props" />
<Import Project="..\..\..\..\w32\v8.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\winlibs.props" />
<Import Project="..\..\..\..\w32\module_debug.props" />
<Import Project="..\..\..\..\w32\v8.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(PlatformName)\$(Configuration)\mod_v8_skel\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(PlatformName)\$(Configuration)\mod_v8_skel\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(PlatformName)\$(Configuration)\mod_v8_skel\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(PlatformName)\$(Configuration)\mod_v8_skel\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
<RunCodeAnalysis>false</RunCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<ClCompile>
<PreprocessorDefinitions>JSMOD_IMPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PreprocessorDefinitions>JSMOD_IMPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
</ClCompile>
<Link>
<OutputFile>$(SolutionDir)$(Platform)\$(Configuration)/mod/$(ProjectName).dll</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<ClCompile>
<PreprocessorDefinitions>JSMOD_IMPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<PreprocessorDefinitions>JSMOD_IMPORT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>
</PrecompiledHeader>
<EnablePREfast>false</EnablePREfast>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
<OutputFile>$(SolutionDir)$(Platform)\$(Configuration)/mod/$(ProjectName).dll</OutputFile>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_v8_skel.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\libs\win32\v8\libv8.2012.vcxproj">
<Project>{AB03E82B-48B1-4374-B32A-A1AF83DDC6C2}</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>
<ProjectReference Include="mod_v8.2012.vcxproj">
<Project>{9B9D2551-D6BD-4F20-8BE5-DE30E154A064}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,211 @@
/*
* mod_v8_skel for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8_skel for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* mod_v8_skel.cpp -- JavaScript example extension module
*
*/
/* This class is only to demonstrate how to create an external loadable extension module to mod_v8. */
#include "mod_v8.h"
using namespace std;
using namespace v8;
static const char js_class_name[] = "Skel";
/* Macros for easier V8 callback definitions */
#define JS_SKEL_GET_PROPERTY_DEF(method_name) JS_GET_PROPERTY_DEF(method_name, FSSkel)
#define JS_SKEL_SET_PROPERTY_DEF(method_name) JS_SET_PROPERTY_DEF(method_name, FSSkel)
#define JS_SKEL_FUNCTION_DEF(method_name) JS_FUNCTION_DEF(method_name, FSSkel)
#define JS_SKEL_GET_PROPERTY_IMPL(method_name) JS_GET_PROPERTY_IMPL(method_name, FSSkel)
#define JS_SKEL_SET_PROPERTY_IMPL(method_name) JS_SET_PROPERTY_IMPL(method_name, FSSkel)
#define JS_SKEL_FUNCTION_IMPL(method_name) JS_FUNCTION_IMPL(method_name, FSSkel)
class FSSkel : public JSBase
{
private:
int x;
string y;
public:
FSSkel(const v8::FunctionCallbackInfo<Value>& info);
virtual ~FSSkel(void);
virtual string GetJSClassName() { return js_class_name; }
/* JS methods */
static void *Construct(const v8::FunctionCallbackInfo<Value>& info);
JS_SKEL_GET_PROPERTY_DEF(GetPropertyX);
JS_SKEL_SET_PROPERTY_DEF(SetPropertyX);
JS_SKEL_GET_PROPERTY_DEF(GetPropertyY);
JS_SKEL_SET_PROPERTY_DEF(SetPropertyY);
JS_SKEL_GET_PROPERTY_DEF(GetPropertyZ);
JS_SKEL_FUNCTION_DEF(MyFunction);
JS_SKEL_FUNCTION_DEF(MyFunction2);
};
/* =============================================================================== */
FSSkel::FSSkel(const v8::FunctionCallbackInfo<Value>& info) : JSBase(info)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::FSSkel()\n");
x = 0;
y = "";
}
FSSkel::~FSSkel(void)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::~FSSkel()\n");
}
void *FSSkel::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
FSSkel *obj;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::Constructor\n");
obj = new FSSkel(info);
/* Parse input variables */
if (info.Length() > 0) {
if (!info[0].IsEmpty() && info[0]->IsInt32()) {
obj->x = info[0]->Int32Value();
}
if (!info[1].IsEmpty() && info[1]->IsString()) {
String::Utf8Value str(info[1]);
if (*str) {
obj->y = *str;
}
}
}
return obj;
}
JS_SKEL_GET_PROPERTY_IMPL(GetPropertyX)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::GetPropertyX (%d)\n", x);
info.GetReturnValue().Set(x);
}
JS_SKEL_SET_PROPERTY_IMPL(SetPropertyX)
{
x = value->Int32Value();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::SetPropertyX to %d\n", x);
}
JS_SKEL_GET_PROPERTY_IMPL(GetPropertyY)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::GetPropertyY (%s)\n", y.c_str());
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), y.c_str()));
}
JS_SKEL_SET_PROPERTY_IMPL(SetPropertyY)
{
String::Utf8Value str(value);
y = js_safe_str(*str);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::SetPropertyY to '%s'\n", y.c_str());
}
JS_SKEL_GET_PROPERTY_IMPL(GetPropertyZ)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::GetPropertyZ (z)\n");
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "z"));
}
JS_SKEL_FUNCTION_IMPL(MyFunction)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::MyFunction\n");
}
JS_SKEL_FUNCTION_IMPL(MyFunction2)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "FSSkel::MyFunction2 - will twrow a JavaScript exception\n");
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Error in MyFunction2()"));
}
/* Add the JS methods here */
static const js_function_t skel_methods[] = {
{"myFunction", FSSkel::MyFunction},
{"myFunction2", FSSkel::MyFunction2},
{0}
};
/* Add the JS properties here */
static const js_property_t skel_props[] = {
{"x", FSSkel::GetPropertyX, FSSkel::SetPropertyX},
{"y", FSSkel::GetPropertyY, FSSkel::SetPropertyY},
{"z", FSSkel::GetPropertyZ, JSBase::DefaultSetProperty},
{0}
};
/* The main definition of the JS Class, holding the name of the class, the constructor and the moethods and properties */
static const js_class_definition_t skel_desc = {
js_class_name,
FSSkel::Construct,
skel_methods,
skel_props
};
SWITCH_BEGIN_EXTERN_C
/* Called from mod_v8 when user scripts [use('Skel');] inside the script. This will load the class into the current JS execution */
static switch_status_t skel_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &skel_desc);
return SWITCH_STATUS_SUCCESS;
}
/* The module interface that mod_v8 will get when loading this module */
static const v8_mod_interface_t skel_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ skel_load
};
/* The exported method called from the module to get this module's inteface */
SWITCH_MOD_DECLARE_NONSTD(switch_status_t) v8_mod_init(const v8_mod_interface_t **module_interface)
{
*module_interface = &skel_module_interface;
return SWITCH_STATUS_SUCCESS;
}
SWITCH_END_EXTERN_C
/* 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:
*/

View File

@ -0,0 +1,457 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
*
* fscoredb.cpp -- JavaScript CoreDB class
*
*/
#include "fscoredb.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "CoreDB";
FSCoreDB::~FSCoreDB(void)
{
_callback.Reset();
DoClose();
switch_core_destroy_memory_pool(&_pool);
}
string FSCoreDB::GetJSClassName()
{
return js_class_name;
}
void FSCoreDB::Init()
{
_pool = NULL;
_db = NULL;
_stmt = NULL;
_dbname = NULL;
}
void FSCoreDB::DoClose()
{
if (_stmt) {
switch_core_db_finalize(_stmt);
_stmt = NULL;
}
if (_db) {
switch_core_db_close(_db);
_db = NULL;
}
}
void *FSCoreDB::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
switch_memory_pool_t *pool;
switch_core_db_t *db;
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *dbname = js_safe_str(*str);
switch_core_new_memory_pool(&pool);
if (!(db = switch_core_db_open_file(dbname))) {
switch_core_destroy_memory_pool(&pool);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot Open DB!"));
return NULL;
}
FSCoreDB *dbo = new FSCoreDB(info);
dbo->_pool = pool;
dbo->_db = db;
dbo->_dbname = switch_core_strdup(pool, dbname);
return dbo;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return NULL;
}
int FSCoreDB::Callback(void *pArg, int argc, char **argv, char **columnNames)
{
FSCoreDB *dbo = static_cast<FSCoreDB *>(pArg);
HandleScope handle_scope(dbo->GetIsolate());
int x = 0;
if (!dbo) {
return 0;
}
if (dbo->_callback.IsEmpty()) {
dbo->GetIsolate()->ThrowException(String::NewFromUtf8(dbo->GetIsolate(), "No callback specified"));
return 0;
}
Handle<Array> arg = Array::New(dbo->GetIsolate(), argc);
for (x = 0; x < argc; x++) {
if (columnNames[x] && argv[x]) {
arg->Set(String::NewFromUtf8(dbo->GetIsolate(), columnNames[x]), String::NewFromUtf8(dbo->GetIsolate(), argv[x]));
}
}
HandleScope scope(dbo->GetIsolate());
Handle<Function> func = Handle<Function>::New(dbo->GetIsolate(), dbo->_callback);
Handle<Value> jsargv[1] = { arg };
func->Call(dbo->GetIsolate()->GetCurrentContext()->Global(), 1, jsargv);
return 0;
}
JS_COREDB_FUNCTION_IMPL(Close)
{
DoClose();
}
JS_COREDB_FUNCTION_IMPL(Exec)
{
HandleScope handle_scope(info.GetIsolate());
info.GetReturnValue().Set(0);
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *sql = js_safe_str(*str);
char *err = NULL;
void *arg = NULL;
switch_core_db_callback_func_t cb_func = NULL;
if (info.Length() > 1) {
Handle<Function> func = JSBase::GetFunctionFromArg(info.GetIsolate(), info[1]);
if (!func.IsEmpty()) {
_callback.Reset(info.GetIsolate(), func);
cb_func = FSCoreDB::Callback;
arg = this;
}
}
switch_core_db_exec(_db, sql, cb_func, arg, &err);
/* Make sure to release the callback handle again */
_callback.Reset();
if (err) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", err);
switch_core_db_free(err);
info.GetReturnValue().Set(-1);
} else {
info.GetReturnValue().Set(switch_core_db_changes(_db));
}
}
}
/* Evaluate a prepared statement
stepSuccessCode expected success code from switch_core_db_step()
return true if step return expected success code, false otherwise
*/
void FSCoreDB::StepEx(const v8::FunctionCallbackInfo<Value>& info, int stepSuccessCode)
{
HandleScope handle_scope(info.GetIsolate());
info.GetReturnValue().Set(false);
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
if (_stmt) {
int running = 1;
while (running < 5000) {
int result = switch_core_db_step(_stmt);
if (result == stepSuccessCode) {
info.GetReturnValue().Set(true);
break;
} else if (result == SWITCH_CORE_DB_BUSY) {
running++;
switch_cond_next(); /* wait a bit before retrying */
continue;
}
if (switch_core_db_finalize(_stmt) != SWITCH_CORE_DB_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", switch_core_db_errmsg(_db));
}
_stmt = NULL;
break;
}
}
}
/* Evaluate a prepared statement, to be used with statements that return data
return true while data is available, false when done or error
*/
JS_COREDB_FUNCTION_IMPL(Next)
{
/* return true until no more rows available */
StepEx(info, SWITCH_CORE_DB_ROW);
}
/* Evaluate a prepared statement, to be used with statements that return no data
return true if statement has finished executing successfully, false otherwise
*/
JS_COREDB_FUNCTION_IMPL(Step)
{
/* return true when the statement has finished executing successfully */
StepEx(info, SWITCH_CORE_DB_DONE);
}
JS_COREDB_FUNCTION_IMPL(Fetch)
{
HandleScope handle_scope(info.GetIsolate());
int colcount;
int x;
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
if (!_stmt) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "No query is active"));
return;
}
colcount = switch_core_db_column_count(_stmt);
Handle<Array> arg = Array::New(info.GetIsolate(), colcount);
for (x = 0; x < colcount; x++) {
const char *var = (char *) switch_core_db_column_name(_stmt, x);
const char *val = (char *) switch_core_db_column_text(_stmt, x);
if (var && val) {
arg->Set(String::NewFromUtf8(info.GetIsolate(), var), String::NewFromUtf8(info.GetIsolate(), val));
}
}
info.GetReturnValue().Set(arg);
}
JS_COREDB_FUNCTION_IMPL(Prepare)
{
HandleScope handle_scope(info.GetIsolate());
info.GetReturnValue().Set(false);
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
if (_stmt) {
switch_core_db_finalize(_stmt);
_stmt = NULL;
}
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *sql = js_safe_str(*str);
if (switch_core_db_prepare(_db, sql, -1, &_stmt, 0)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", switch_core_db_errmsg(_db));
} else {
info.GetReturnValue().Set(true);
}
}
}
JS_COREDB_FUNCTION_IMPL(BindText)
{
HandleScope handle_scope(info.GetIsolate());
bool status;
int32_t param_index = -1;
string param_value;
info.GetReturnValue().Set(false);
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
/* db_prepare() must be called first */
if (!_stmt) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "prepare() must be called first"));
return;
}
if (info.Length() < 2) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return;
}
/* convert args */
status = !info[0].IsEmpty() && info[0]->IsInt32() ? true : false;
param_index = info[0]->Int32Value();
String::Utf8Value str(info[1]);
param_value = js_safe_str(*str);
if ((param_index < 1) || (param_value.length() == 0)) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return;
}
/* bind param */
if (switch_core_db_bind_text(_stmt, param_index, param_value.c_str(), -1, SWITCH_CORE_DB_TRANSIENT)) {
char *err = switch_mprintf("Database error %s", switch_core_db_errmsg(_db));
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return;
} else {
info.GetReturnValue().Set(true);
}
}
JS_COREDB_FUNCTION_IMPL(BindInt)
{
HandleScope handle_scope(info.GetIsolate());
bool status;
int32_t param_index = -1;
int32_t param_value = -1;
info.GetReturnValue().Set(false);
if (!_db) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Database is not connected"));
return;
}
/* db_prepare() must be called first */
if (!_stmt) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "prepare() must be called first"));
return;
}
if (info.Length() < 2) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return;
}
/* convert args */
status = !info[0].IsEmpty() && info[0]->IsInt32() ? true : false;
param_index = info[0]->Int32Value();
status = !info[1].IsEmpty() && info[1]->IsInt32() ? true : false;
param_value = info[1]->Int32Value();
if (param_index < 1) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return;
}
/* bind param */
if (switch_core_db_bind_int(_stmt, param_index, param_value)) {
char *err = switch_mprintf("Database error %s", switch_core_db_errmsg(_db));
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return;
} else {
info.GetReturnValue().Set(true);
}
}
JS_COREDB_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
if (!this) {
info.GetReturnValue().Set(false);
return;
}
String::Utf8Value str(property);
if (!strcmp(js_safe_str(*str), "path")) {
if (_dbname) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), _dbname));
} else {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), ""));
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t db_methods[] = {
{"exec", FSCoreDB::Exec},
{"close", FSCoreDB::Close},
{"next", FSCoreDB::Next},
{"step", FSCoreDB::Step},
{"fetch", FSCoreDB::Fetch},
{"prepare", FSCoreDB::Prepare},
{"bindText", FSCoreDB::BindText},
{"bindInt", FSCoreDB::BindInt},
{0}
};
static const js_property_t db_props[] = {
{"path", FSCoreDB::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t db_desc = {
js_class_name,
FSCoreDB::Construct,
db_methods,
db_props
};
static switch_status_t db_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &db_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t db_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ db_load
};
const v8_mod_interface_t *FSCoreDB::GetModuleInterface()
{
return &db_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,270 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
*
* fscurl.cpp -- JavaScript CURL class
*
*/
#include "fscurl.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "CURL";
FSCURL::~FSCURL(void)
{
_function.Reset();
_user_data.Reset();
_ret.Reset();
if (_curl_handle) {
switch_curl_easy_cleanup(_curl_handle);
}
}
void FSCURL::Init(void)
{
_curl_handle = NULL;
}
string FSCURL::GetJSClassName()
{
return js_class_name;
}
size_t FSCURL::FileCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
FSCURL *obj = static_cast<FSCURL *>(data);
HandleScope handle_scope(obj->GetIsolate());
register unsigned int realsize = (unsigned int) (size * nmemb);
uint32_t argc = 0;
Handle<Value> argv[4];
if (!obj) {
return 0;
}
Handle<Function> func;
if (!obj->_function.IsEmpty()) {
func = Handle<Function>::New(obj->GetIsolate(), obj->_function);
}
if (!func.IsEmpty()) {
char *ret;
if (ptr) {
argv[argc++] = String::NewFromUtf8(obj->GetIsolate(), (char *)ptr);
} else {
argv[argc++] = String::NewFromUtf8(obj->GetIsolate(), "");
}
if (!obj->_user_data.IsEmpty()) {
argv[argc++] = Handle<Value>::New(obj->GetIsolate(), Persistent<Value>::Cast(obj->_user_data));
}
Handle<Value> res = func->Call(obj->GetIsolate()->GetCurrentContext()->Global(), argc, argv);
if (!res.IsEmpty()){
obj->_ret.Reset(obj->GetIsolate(), res);
} else {
obj->_ret.Reset();
}
String::Utf8Value str(Handle<Value>::New(obj->GetIsolate(), res));
if ((ret = *str)) {
if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) {
return realsize;
} else {
return 0;
}
}
}
return realsize;
}
void *FSCURL::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
FSCURL *obj = new FSCURL(info);
switch_assert(obj);
return obj;
}
JS_CURL_FUNCTION_IMPL(Run)
{
HandleScope handle_scope(info.GetIsolate());
const char *method, *url;
const char *url_p = NULL;
char *durl = NULL;
string data, cred;
long httpRes = 0;
struct curl_slist *headers = NULL;
int32_t timeout = 0;
char ct[80] = "Content-Type: application/x-www-form-urlencoded";
if (info.Length() < 2) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
return;
}
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
method = js_safe_str(*str1);
url = js_safe_str(*str2);
_curl_handle = switch_curl_easy_init();
if (!strncasecmp(url, "https", 5)) {
switch_curl_easy_setopt(_curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(_curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
if (info.Length() > 2) {
String::Utf8Value str3(info[2]);
data = js_safe_str(*str3);
}
if (info.Length() > 3) {
Handle<Function> func = JSBase::GetFunctionFromArg(info.GetIsolate(), info[3]);
if (!func.IsEmpty() && func->IsFunction()) {
_function.Reset(info.GetIsolate(), func);
}
}
if (info.Length() > 4) {
_user_data.Reset(info.GetIsolate(), Handle<Object>::Cast(info[4]));
}
if (info.Length() > 5) {
String::Utf8Value str4(info[5]);
cred = js_safe_str(*str4);
if (cred.length() > 0) {
switch_curl_easy_setopt(_curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
switch_curl_easy_setopt(_curl_handle, CURLOPT_USERPWD, cred.c_str());
}
}
if (info.Length() > 6) {
timeout = info[6]->Int32Value();
if (timeout > 0) {
switch_curl_easy_setopt(_curl_handle, CURLOPT_TIMEOUT, timeout);
}
}
if (info.Length() > 7) {
String::Utf8Value str5(info[7]);
const char *content_type = js_safe_str(*str5);
switch_snprintf(ct, sizeof(ct), "Content-Type: %s", content_type);
}
headers = curl_slist_append(headers, ct);
switch_curl_easy_setopt(_curl_handle, CURLOPT_HTTPHEADER, headers);
url_p = url;
if (!strcasecmp(method, "post")) {
switch_curl_easy_setopt(_curl_handle, CURLOPT_POST, 1);
if (!data.c_str()) {
data = "";
}
switch_curl_easy_setopt(_curl_handle, CURLOPT_POSTFIELDS, data.c_str());
} else if (data.length() > 0) {
durl = switch_mprintf("%s?%s", url, data.c_str());
url_p = durl;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Running: method: [%s] url: [%s] data: [%s] cred=[%s] cb: [%s]\n",
method, url_p, data.c_str(), switch_str_nil(cred.c_str()), !_function.IsEmpty() ? "yes" : "no");
switch_curl_easy_setopt(_curl_handle, CURLOPT_URL, url_p);
switch_curl_easy_setopt(_curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(_curl_handle, CURLOPT_WRITEFUNCTION, FSCURL::FileCallback);
switch_curl_easy_setopt(_curl_handle, CURLOPT_WRITEDATA, (void *) this);
switch_curl_easy_setopt(_curl_handle, CURLOPT_USERAGENT, "freeswitch-v8-curl/1.0");
switch_curl_easy_perform(_curl_handle);
switch_curl_easy_getinfo(_curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
switch_curl_easy_cleanup(_curl_handle);
curl_slist_free_all(headers);
_curl_handle = NULL;
_function.Reset();
_user_data.Reset();
switch_safe_free(durl);
if (!_ret.IsEmpty()) {
info.GetReturnValue().Set(_ret);
_ret.Reset();
}
}
static const js_function_t curl_methods[] = {
{"run", FSCURL::Run},
{0}
};
static const js_property_t curl_props[] = {
{0}
};
static const js_class_definition_t curl_desc = {
js_class_name,
FSCURL::Construct,
curl_methods,
curl_props
};
static switch_status_t curl_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &curl_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t curl_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ curl_load
};
const v8_mod_interface_t *FSCURL::GetModuleInterface()
{
return &curl_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,162 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fsdtmf.cpp -- JavaScript DTMF class
*
*/
#include "fsdtmf.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "DTMF";
FSDTMF::~FSDTMF(void)
{
switch_safe_free(_dtmf);
}
string FSDTMF::GetJSClassName()
{
return js_class_name;
}
Handle<Object> FSDTMF::New(switch_dtmf_t *dtmf, const char *name, JSMain *js)
{
FSDTMF *obj;
switch_dtmf_t *ddtmf;
if ((obj = new FSDTMF(js))) {
if ((ddtmf = (switch_dtmf_t *)malloc(sizeof(*ddtmf)))) {
*ddtmf = *dtmf;
obj->_dtmf = ddtmf;
obj->RegisterInstance(obj->GetIsolate(), js_safe_str(name), true);
return obj->GetJavaScriptObject();
} else {
delete obj;
}
}
return Handle<Object>();
}
void *FSDTMF::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
HandleScope handle_scope(info.GetIsolate());
switch_dtmf_t *dtmf;
int32_t duration = switch_core_default_dtmf_duration(0);
const char *dtmf_char;
if (info.Length() <= 0) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid Args"));
return NULL;
}
String::Utf8Value str(info[0]);
dtmf_char = *str;
if (info.Length() > 1) {
duration = info[1]->Int32Value();
if (duration <= 0) {
duration = switch_core_default_dtmf_duration(0);
}
}
if ((dtmf = (switch_dtmf_t *)malloc(sizeof(*dtmf)))) {
FSDTMF *obj = new FSDTMF(info);
obj->_dtmf = dtmf;
if (dtmf_char && *dtmf_char) {
obj->_dtmf->digit = *dtmf_char;
}
obj->_dtmf->duration = duration;
return obj;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Memory error"));
return NULL;
}
JS_DTMF_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
FSDTMF *obj = JSBase::GetInstance<FSDTMF>(info.Holder());
if (!obj) {
info.GetReturnValue().Set(false);
return;
}
String::Utf8Value str(property);
const char *prop = js_safe_str(*str);
if (!strcmp(prop, "digit")) {
char tmp[2] = { obj->_dtmf->digit, '\0' };
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), tmp));
} else if (!strcmp(prop, "duration")) {
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), obj->_dtmf->duration));
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t dtmf_proc[] = {
{0}
};
static const js_property_t dtmf_prop[] = {
{"digit", FSDTMF::GetProperty, JSBase::DefaultSetProperty},
{"duration", FSDTMF::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t dtmf_desc = {
js_class_name,
FSDTMF::Construct,
dtmf_proc,
dtmf_prop
};
const js_class_definition_t *FSDTMF::GetClassDefinition()
{
return &dtmf_desc;
}
/* 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:
*/

View File

@ -0,0 +1,394 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fsevent.cpp -- JavaScript Event class
*
*/
#include "fsevent.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "Event";
FSEvent::~FSEvent(void)
{
if (!_freed && _event) {
switch_event_destroy(&_event);
}
}
string FSEvent::GetJSClassName()
{
return js_class_name;
}
void FSEvent::Init()
{
_event = NULL;
_freed = 0;
}
void FSEvent::SetEvent(switch_event_t *event, int freed)
{
/* Free existing event if it exists already */
if (!this->_freed && this->_event) {
switch_event_destroy(&this->_event);
}
this->_event = event;
this->_freed = freed;
}
switch_event_t **FSEvent::GetEvent()
{
return &_event;
}
Handle<Object> FSEvent::New(switch_event_t *event, const char *name, JSMain *js)
{
FSEvent *obj;
if ((obj = new FSEvent(js))) {
obj->_event = event;
obj->_freed = 1;
obj->RegisterInstance(js->GetIsolate(), js_safe_str(name), true);
return obj->GetJavaScriptObject();
}
return Handle<Object>();
}
void *FSEvent::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 0) {
switch_event_t *event;
FSEvent *obj;
switch_event_types_t etype;
String::Utf8Value str(info[0]);
const char *ename = js_safe_str(*str);
if ((obj = new FSEvent(info))) {
if (switch_name_event(ename, &etype) != SWITCH_STATUS_SUCCESS) {
char *err = switch_mprintf("Unknown event %s", ename);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
delete obj;
return NULL;
}
if (etype == SWITCH_EVENT_CUSTOM) {
string subclass_name;
if (info.Length() > 1) {
String::Utf8Value str2(info[1]);
if (*str2) {
subclass_name = js_safe_str(*str2);
}
} else {
subclass_name = "none";
}
if (switch_event_create_subclass(&event, etype, subclass_name.c_str()) != SWITCH_STATUS_SUCCESS) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed to create sub class"));
delete obj;
return NULL;
}
} else {
if (switch_event_create(&event, etype) != SWITCH_STATUS_SUCCESS) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed to create event"));
delete obj;
return NULL;
}
}
obj->_event = event;
obj->_freed = 0;
return obj;
}
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid Args"));
return NULL;
}
JS_EVENT_FUNCTION_IMPL(AddHeader)
{
HandleScope handle_scope(info.GetIsolate());
if (!_event || _freed) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 1) {
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
const char *hname = js_safe_str(*str1);
const char *hval = js_safe_str(*str2);
switch_event_add_header_string(_event, SWITCH_STACK_BOTTOM, hname, hval);
info.GetReturnValue().Set(true);
return;
}
info.GetReturnValue().Set(false);
}
JS_EVENT_FUNCTION_IMPL(GetHeader)
{
HandleScope handle_scope(info.GetIsolate());
if (!_event) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *hname = js_safe_str(*str);
const char *val = switch_event_get_header(_event, hname);
if (!val) val = "";
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), val));
return;
}
info.GetReturnValue().Set(false);
}
JS_EVENT_FUNCTION_IMPL(AddBody)
{
HandleScope handle_scope(info.GetIsolate());
if (!_event || _freed) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *body = js_safe_str(*str);
switch_event_add_body(_event, "%s", body);
info.GetReturnValue().Set(true);
return;
}
info.GetReturnValue().Set(false);
}
JS_EVENT_FUNCTION_IMPL(GetBody)
{
HandleScope handle_scope(info.GetIsolate());
const char *body;
if (!_event) {
info.GetReturnValue().Set(false);
return;
}
if ((body = switch_event_get_body(_event))) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), body));
} else {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), ""));
}
}
JS_EVENT_FUNCTION_IMPL(GetType)
{
HandleScope handle_scope(info.GetIsolate());
const char *event_name;
if (!_event) {
info.GetReturnValue().Set(false);
return;
}
event_name = switch_event_name(_event->event_id);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(event_name)));
}
JS_EVENT_FUNCTION_IMPL(Serialize)
{
HandleScope handle_scope(info.GetIsolate());
char *buf;
uint8_t isxml = 0, isjson = 0;
if (!_event) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *arg = js_safe_str(*str);
if (!strcasecmp(arg, "xml")) {
isxml++;
} else if (!strcasecmp(arg, "json")) {
isjson++;
}
}
if (isxml) {
switch_xml_t xml;
char *xmlstr;
if ((xml = switch_event_xmlize(_event, SWITCH_VA_NONE))) {
xmlstr = switch_xml_toxml(xml, SWITCH_FALSE);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(xmlstr)));
switch_xml_free(xml);
switch_safe_free(xmlstr);
} else {
info.GetReturnValue().Set(false);
}
} else if (isjson) {
if (switch_event_serialize_json(_event, &buf) == SWITCH_STATUS_SUCCESS) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(buf)));
switch_safe_free(buf);
}
} else {
if (switch_event_serialize(_event, &buf, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(buf)));
switch_safe_free(buf);
}
}
}
JS_EVENT_FUNCTION_IMPL_STATIC(Fire)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
FSEvent *obj = JSBase::GetInstance<FSEvent>(info.Holder());
if (obj && obj->_event) {
switch_event_fire(&obj->_event);
obj->_freed = 1;
delete obj;
info.GetReturnValue().Set(true);
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No valid event to fire away\n");
info.GetReturnValue().Set(false);
}
JS_EVENT_FUNCTION_IMPL(ChatExecute)
{
HandleScope handle_scope(info.GetIsolate());
if (_event) {
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *app = js_safe_str(*str);
string arg;
if (info.Length() > 1) {
String::Utf8Value str2(info[1]);
if (*str2) {
arg = js_safe_str(*str2);
}
}
switch_core_execute_chat_app(_event, app, arg.c_str());
info.GetReturnValue().Set(true);
return;
}
}
info.GetReturnValue().Set(false);
}
JS_EVENT_FUNCTION_IMPL_STATIC(Destroy)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
FSEvent *obj = JSBase::GetInstance<FSEvent>(info.Holder());
if (obj) {
delete obj;
info.GetReturnValue().Set(true);
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Object already destroyed\n");
info.GetReturnValue().Set(false);
}
JS_EVENT_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
if (!strcmp(js_safe_str(*str), "ready")) {
info.GetReturnValue().Set(_event ? true : false);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t event_proc[] = {
{"addHeader", FSEvent::AddHeader},
{"getHeader", FSEvent::GetHeader},
{"addBody", FSEvent::AddBody},
{"getBody", FSEvent::GetBody},
{"getType", FSEvent::GetType},
{"serialize", FSEvent::Serialize},
{"fire", FSEvent::Fire},
{"chatExecute", FSEvent::ChatExecute},
{"destroy", FSEvent::Destroy},
{0}
};
static const js_property_t event_prop[] = {
{"ready", FSEvent::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t event_desc = {
js_class_name,
FSEvent::Construct,
event_proc,
event_prop
};
const js_class_definition_t *FSEvent::GetClassDefinition()
{
return &event_desc;
}
/* 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:
*/

View File

@ -0,0 +1,341 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* fsfile.cpp -- JavaScript File class - implements a class similar to the Spidermonkey built-in File class.
*
*/
#include "fsfile.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "File";
FSFile::~FSFile(void)
{
// Cleanup local objects
}
void FSFile::Init()
{
// Init local objects
}
string FSFile::GetJSClassName()
{
return js_class_name;
}
void *FSFile::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
return new FSFile(info);
// TODO: Implement the actual constructor code */
}
JS_FILE_FUNCTION_IMPL(Close)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(CopyTo)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Flush)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(List)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(MkDir)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Open)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Read)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(ReadAll)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(ReadLn)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Remove)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(RenameTo)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Seek)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(ToString)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(ToURL)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(Write)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(WriteAll)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_FUNCTION_IMPL(WriteLn)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropCanAppend)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropCanRead)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropCanReplace)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropCanWrite)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropCreationTime)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropExists)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropHasAutoFlush)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropHasRandomAccess)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropIsDirectory)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropIsFile)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropIsNative)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropIsOpen)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropLastModified)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropLength)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropMode)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropName)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropParent)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropPath)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropPosition)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_SET_PROPERTY_IMPL(SetPropPosition)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropSize)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
JS_FILE_GET_PROPERTY_IMPL(GetPropType)
{
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Not yet implemented"));
}
static const js_function_t file_proc[] = {
{"close", FSFile::Close},
{"copyTo", FSFile::CopyTo},
{"flush", FSFile::Flush},
{"list", FSFile::List},
{"mkdir", FSFile::MkDir},
{"open", FSFile::Open},
{"read", FSFile::Read},
{"readAll", FSFile::ReadAll},
{"readln", FSFile::ReadLn},
{"remove", FSFile::Remove},
{"renameTo", FSFile::RenameTo},
{"seek", FSFile::Seek},
{"toString", FSFile::ToString},
{"toURL", FSFile::ToURL},
{"write", FSFile::Write},
{"writeAll", FSFile::WriteAll},
{"writeln", FSFile::WriteLn},
{0}
};
static const js_property_t file_prop[] = {
{"canAppend", FSFile::GetPropCanAppend, JSBase::DefaultSetProperty},
{"canRead", FSFile::GetPropCanRead, JSBase::DefaultSetProperty},
{"canReplace", FSFile::GetPropCanReplace, JSBase::DefaultSetProperty},
{"canWrite", FSFile::GetPropCanWrite, JSBase::DefaultSetProperty},
{"creationTime", FSFile::GetPropCreationTime, JSBase::DefaultSetProperty},
{"exists", FSFile::GetPropExists, JSBase::DefaultSetProperty},
{"hasAutoFlush", FSFile::GetPropHasAutoFlush, JSBase::DefaultSetProperty},
{"hasRandomAccess", FSFile::GetPropHasRandomAccess, JSBase::DefaultSetProperty},
{"isDirectory", FSFile::GetPropIsDirectory, JSBase::DefaultSetProperty},
{"isFile", FSFile::GetPropIsFile, JSBase::DefaultSetProperty},
{"isNative", FSFile::GetPropIsNative, JSBase::DefaultSetProperty},
{"isOpen", FSFile::GetPropIsOpen, JSBase::DefaultSetProperty},
{"lastModified", FSFile::GetPropLastModified, JSBase::DefaultSetProperty},
{"length", FSFile::GetPropLength, JSBase::DefaultSetProperty},
{"mode", FSFile::GetPropMode, JSBase::DefaultSetProperty},
{"name", FSFile::GetPropName, JSBase::DefaultSetProperty},
{"parent", FSFile::GetPropParent, JSBase::DefaultSetProperty},
{"path", FSFile::GetPropPath, JSBase::DefaultSetProperty},
{"position", FSFile::GetPropPosition, FSFile::SetPropPosition},
{"size", FSFile::GetPropSize, JSBase::DefaultSetProperty},
{"type", FSFile::GetPropType, JSBase::DefaultSetProperty},
{0}
};
/*
- currentDir
- error
- input
- output
- separator
*/
static const js_class_definition_t file_desc = {
js_class_name,
FSFile::Construct,
file_proc,
file_prop
};
static switch_status_t file_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &file_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t file_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ file_load
};
const v8_mod_interface_t *FSFile::GetModuleInterface()
{
return &file_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,240 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fsfileio.cpp -- JavaScript FileIO class
*
*/
#include "fsfileio.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "FileIO";
FSFileIO::~FSFileIO(void)
{
if (_fd) {
switch_file_close(_fd);
}
switch_core_destroy_memory_pool(&_pool);
}
string FSFileIO::GetJSClassName()
{
return js_class_name;
}
void FSFileIO::Init()
{
_path = NULL;
_flags = 0;
_fd = NULL;
_pool = NULL;
_buf = NULL;
_buflen = 0;
_bufsize = 0;
}
void *FSFileIO::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
HandleScope handle_scope(info.GetIsolate());
switch_memory_pool_t *pool;
switch_file_t *fd;
unsigned int flags = 0;
FSFileIO *fio;
if (info.Length() > 1) {
const char *path, *flags_str;
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
path = js_safe_str(*str1);
flags_str = js_safe_str(*str2);
if (strchr(flags_str, 'r')) {
flags |= SWITCH_FOPEN_READ;
}
if (strchr(flags_str, 'w')) {
flags |= SWITCH_FOPEN_WRITE;
}
if (strchr(flags_str, 'c')) {
flags |= SWITCH_FOPEN_CREATE;
}
if (strchr(flags_str, 'a')) {
flags |= SWITCH_FOPEN_APPEND;
}
if (strchr(flags_str, 't')) {
flags |= SWITCH_FOPEN_TRUNCATE;
}
if (strchr(flags_str, 'b')) {
flags |= SWITCH_FOPEN_BINARY;
}
switch_core_new_memory_pool(&pool);
if (switch_file_open(&fd, path, flags, SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, pool) != SWITCH_STATUS_SUCCESS) {
switch_core_destroy_memory_pool(&pool);
char *err = switch_mprintf("Cannot Open File: %s", path);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return NULL;
}
fio = new FSFileIO(info);
fio->_fd = fd;
fio->_pool = pool;
fio->_path = switch_core_strdup(pool, path);
fio->_flags = flags;
return fio;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid Args"));
return NULL;
}
JS_FILEIO_FUNCTION_IMPL(Read)
{
HandleScope handle_scope(info.GetIsolate());
int32_t bytes = 0;
switch_size_t read = 0;
if (!(_flags & SWITCH_FOPEN_READ)) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 0) {
bytes = info[0]->Int32Value();
}
if (bytes) {
if (!_buf || _bufsize < bytes) {
_buf = (char *)switch_core_alloc(_pool, bytes);
_bufsize = bytes;
}
read = bytes;
switch_file_read(_fd, _buf, &read);
_buflen = read;
info.GetReturnValue().Set((read > 0) ? true : false);
} else {
info.GetReturnValue().Set(false);
}
}
JS_FILEIO_FUNCTION_IMPL(GetData)
{
HandleScope handle_scope(info.GetIsolate());
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(_buf)));
}
JS_FILEIO_FUNCTION_IMPL(Write)
{
HandleScope handle_scope(info.GetIsolate());
switch_size_t wrote = 0;
if (!(_flags & SWITCH_FOPEN_WRITE)) {
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 0) {
char *data = NULL;
String::Utf8Value str(info[0]);
data = *str;
if (data) {
wrote = strlen(data);
info.GetReturnValue().Set((switch_file_write(_fd, data, &wrote) == SWITCH_STATUS_SUCCESS) ? true : false);
return;
}
}
info.GetReturnValue().Set(false);
}
JS_FILEIO_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
const char *prop = js_safe_str(*str);
if (!strcmp(prop, "path")) {
if (_path) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), _path));
} else {
info.GetReturnValue().Set(false);
}
} else if (!strcmp(prop, "open")) {
info.GetReturnValue().Set(_fd ? true : false);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t fileio_proc[] = {
{"read", FSFileIO::Read},
{"write", FSFileIO::Write},
{"data", FSFileIO::GetData},
{0}
};
static const js_property_t fileio_prop[] = {
{"path", FSFileIO::GetProperty, JSBase::DefaultSetProperty},
{"open", FSFileIO::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t fileio_desc = {
js_class_name,
FSFileIO::Construct,
fileio_proc,
fileio_prop
};
const js_class_definition_t *FSFileIO::GetClassDefinition()
{
return &fileio_desc;
}
/* 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:
*/

View File

@ -0,0 +1,776 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fsglobal.cpp -- JavaScript Global functions
*
*/
#include "mod_v8.h"
#include "fsglobal.hpp"
#include "fssession.hpp"
#include <switch_curl.h>
using namespace std;
using namespace v8;
class CURLCallbackData
{
public:
Isolate *isolate;
Persistent<Array> hashObject;
int fileHandle;
switch_size_t bufferSize;
switch_size_t bufferDataLength;
char *buffer;
CURLCallbackData() {
isolate = NULL;
fileHandle = 0;
bufferSize = 0;
bufferDataLength = 0;
buffer = NULL;
}
~CURLCallbackData() {
hashObject.Reset();
}
};
size_t FSGlobal::HashCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register size_t realsize = size * nmemb;
char *line, lineb[2048], *nextline = NULL, *val = NULL, *p = NULL;
CURLCallbackData *config_data = (CURLCallbackData *)data;
if (!config_data->hashObject.IsEmpty()) {
switch_copy_string(lineb, (char *) ptr, sizeof(lineb));
line = lineb;
HandleScope scope(config_data->isolate);
/* Get the array object to store data in */
Local<Array> args = Local<Array>::New(config_data->isolate, config_data->hashObject);
while (line) {
if ((nextline = strchr(line, '\n'))) {
*nextline = '\0';
nextline++;
}
if ((val = strchr(line, '='))) {
*val = '\0';
val++;
if (val[0] == '>') {
*val = '\0';
val++;
}
for (p = line; p && *p == ' '; p++);
line = p;
for (p = line + strlen(line) - 1; *p == ' '; p--)
*p = '\0';
for (p = val; p && *p == ' '; p++);
val = p;
for (p = val + strlen(val) - 1; *p == ' '; p--)
*p = '\0';
// Add data to hash
args->Set(String::NewFromUtf8(config_data->isolate, line), String::NewFromUtf8(config_data->isolate, js_safe_str(val)));
}
line = nextline;
}
}
return realsize;
}
size_t FSGlobal::FileCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register unsigned int realsize = (unsigned int) (size * nmemb);
CURLCallbackData *config_data = (CURLCallbackData *)data;
if ((write(config_data->fileHandle, ptr, realsize) != (int) realsize)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to write all bytes!\n");
}
return realsize;
}
size_t FSGlobal::FetchUrlCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register unsigned int realsize = (unsigned int) (size * nmemb);
CURLCallbackData *config_data = (CURLCallbackData *)data;
/* Too much data. Do not increase buffer, but abort fetch instead. */
if (config_data->bufferDataLength + realsize >= config_data->bufferSize) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Data do not fit in the allocated buffer\n");
return 0;
}
memcpy(config_data->buffer + config_data->bufferDataLength, ptr, realsize);
config_data->bufferDataLength += realsize;
config_data->buffer[config_data->bufferDataLength] = 0;
return realsize;
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(FetchURLHash)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
switch_CURL *curl_handle = NULL;
CURLCallbackData config_data;
int saveDepth = 0;
if (info.Length() > 0) {
String::Utf8Value url(info[0]);
if (info.Length() > 1 && info[1]->IsString()) {
/* Cast to string */
Local<String> str = Local<String>::Cast(info[1]);
/* Try to get existing variable */
Local<Value> obj = info.GetIsolate()->GetCurrentContext()->Global()->Get(str);
if (!obj.IsEmpty() && obj->IsArray()) {
/* The existing var is an array, use it */
config_data.hashObject.Reset(info.GetIsolate(), Local<Array>::Cast(obj));
} else if (obj.IsEmpty() || obj->IsUndefined()) {
/* No existing var (or an existing that is undefined), create a new one */
Local<Array> arguments = Array::New(info.GetIsolate());
info.GetIsolate()->GetCurrentContext()->Global()->Set(str, arguments);
config_data.hashObject.Reset(info.GetIsolate(), arguments);
} else {
/* The var exists, but is wrong type - exit with error */
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Second argument is the name of an existing var of the wrong type"));
return;
}
} else if (info.Length() > 1 && info[1]->IsArray()) {
/* The var is an array, use it */
config_data.hashObject.Reset(info.GetIsolate(), Local<Array>::Cast(info[1]));
} else if (info.Length() > 1) {
/* The var exists, but is wrong type - exit with error */
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Second argument is of the wrong type"));
return;
} else {
/* Second argument doesn't exist, this is also ok. The hash will be returned as the result */
Local<Array> arguments = Array::New(info.GetIsolate());
config_data.hashObject.Reset(info.GetIsolate(), arguments);
}
curl_handle = switch_curl_easy_init();
if (!strncasecmp(js_safe_str(*url), "https", 5)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
config_data.isolate = info.GetIsolate();
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, js_safe_str(*url));
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, FSGlobal::HashCallback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &config_data);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-v8/1.0");
switch_curl_easy_perform(curl_handle);
switch_curl_easy_cleanup(curl_handle);
/* Return the hash */
info.GetReturnValue().Set(config_data.hashObject);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(FetchURLFile)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
switch_CURL *curl_handle = NULL;
CURLCallbackData config_data;
int saveDepth = 0;
if (info.Length() > 1) {
const char *url = NULL, *filename = NULL;
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
url = js_safe_str(*str1);
filename = js_safe_str(*str2);
curl_handle = switch_curl_easy_init();
if (!strncasecmp(url, "https", 5)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
config_data.isolate = info.GetIsolate();
if ((config_data.fileHandle = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, FSGlobal::FileCallback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &config_data);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-v8/1.0");
switch_curl_easy_perform(curl_handle);
switch_curl_easy_cleanup(curl_handle);
close(config_data.fileHandle);
info.GetReturnValue().Set(true);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open file [%s]\n", filename);
info.GetReturnValue().Set(false);
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(FetchURL)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
switch_CURL *curl_handle = NULL;
CURLCallbackData config_data;
int32_t buffer_size = 65535;
switch_CURLcode code = (switch_CURLcode)0;
int saveDepth = 0;
if (info.Length() >= 1) {
const char *url;
String::Utf8Value str(info[0]);
url = js_safe_str(*str);
if (info.Length() > 1) {
buffer_size = info[1]->Int32Value();
}
curl_handle = switch_curl_easy_init();
if (!strncasecmp(url, "https", 5)) {
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
}
config_data.isolate = info.GetIsolate();
config_data.bufferSize = buffer_size;
config_data.buffer = (char *)malloc(config_data.bufferSize);
config_data.bufferDataLength = 0;
if (config_data.buffer == NULL) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed to allocate data buffer."));
switch_curl_easy_cleanup(curl_handle);
return;
}
switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, FSGlobal::FetchUrlCallback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &config_data);
switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-v8/1.0");
code = switch_curl_easy_perform(curl_handle);
switch_curl_easy_cleanup(curl_handle);
if (code == CURLE_OK) {
config_data.buffer[config_data.bufferDataLength] = 0;
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(config_data.buffer)));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Curl returned error %u\n", (unsigned) code);
info.GetReturnValue().Set(false);
}
free(config_data.buffer);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Exit)
{
JS_CHECK_SCRIPT_STATE();
if (info.Length() > 0) {
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(info[0]);
if (*str) {
JSMain::ExitScript(info.GetIsolate(), *str);
return;
}
}
JSMain::ExitScript(info.GetIsolate(), NULL);
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Log)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
char *level_str, *msg;
switch_log_level_t level = SWITCH_LOG_DEBUG;
char *file = NULL;
int line = 0;
if (info.Length() > 0) {
/* Get filename and line number from stack */
file = JSMain::GetStackInfo(info.GetIsolate(), &line);
}
if (info.Length() > 1) {
String::Utf8Value str(info[0]);
if ((level_str = *str)) {
level = switch_log_str2level(level_str);
if (level == SWITCH_LOG_INVALID) {
level = SWITCH_LOG_DEBUG;
}
}
String::Utf8Value str2(info[1]);
if ((msg = *str2) && *msg != '\0') {
const char lastchar = msg[strlen(msg)-1];
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "console_log", line, NULL, level, "%s%s", msg, lastchar != '\n' ? "\n" : "");
switch_safe_free(file);
return;
}
} else if (info.Length() > 0) {
String::Utf8Value str(info[0]);
if ((msg = *str) && *msg != '\0') {
const char lastchar = msg[strlen(msg)-1];
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "console_log", line, NULL, level, "%s%s", msg, lastchar != '\n' ? "\n" : "");
switch_safe_free(file);
return;
}
}
switch_safe_free(file);
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(GlobalSet)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
const char *var_name = NULL, *val = NULL, *val2 = NULL;
bool tf = true;
if (info.Length() > 1) {
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
var_name = js_safe_str(*str1);
val = js_safe_str(*str2);
if (info.Length() == 2) {
switch_core_set_variable(var_name, val);
info.GetReturnValue().Set(true);
return;
} else {
String::Utf8Value str3(info[2]);
val2 = js_safe_str(*str3);
if (switch_core_set_var_conditional(var_name, val, val2) != SWITCH_TRUE) {
tf = false;
}
info.GetReturnValue().Set(tf);
return;
}
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "var name not supplied!"));
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(GlobalGet)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
const char *var_name = NULL;
char *val = NULL;
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
var_name = js_safe_str(*str);
val = switch_core_get_variable_dup(var_name);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(val)));
switch_safe_free(val);
return;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "var name not supplied!"));
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Include)
{
JS_CHECK_SCRIPT_STATE();
if (info.Length() < 1) {
/* Bad arguments, return exception */
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
} else {
/* Try to get the current script path */
string scriptPath = "";
Handle<Value> val = info.GetIsolate()->GetCurrentContext()->Global()->Get(String::NewFromUtf8(info.GetIsolate(), "scriptPath"));
if (!val.IsEmpty() && val->IsString()) {
String::Utf8Value tmp(val);
if (*tmp) {
scriptPath = *tmp;
}
}
/* Loop all arguments until we find a valid file */
for (int i = 0; i < info.Length(); i++) {
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(info[i]);
char *path = NULL;
const char *script_name = NULL;
if (*str) {
if (switch_is_file_path(*str)) {
script_name = *str;
} else {
/* First try to use the same path as the executing script */
if (scriptPath.length() > 0) {
path = switch_mprintf("%s%s%s", scriptPath.c_str(), SWITCH_PATH_SEPARATOR, *str);
if (path && JSMain::FileExists(path)) {
script_name = path;
} else {
switch_safe_free(path);
}
}
/* At last, use FS script directory */
if (!script_name && (path = switch_mprintf("%s%s%s", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR, *str))) {
script_name = path;
}
}
}
if (script_name && JSMain::FileExists(script_name)) {
string js_file = JSMain::LoadFileToString(script_name);
if (js_file.length() > 0) {
Handle<String> source = String::NewFromUtf8(info.GetIsolate(), js_file.c_str());
Handle<Script> script = Script::Compile(source, info[i]);
info.GetReturnValue().Set(script->Run());
switch_safe_free(path);
return;
}
}
switch_safe_free(path);
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed to include javascript file"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Sleep)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
int32_t msec = 0;
if (info.Length() > 0) {
msec = info[0]->Int32Value();
}
if (msec) {
switch_yield(msec * 1000);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "No time specified"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Use)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
char *mod_name = *str;
if (mod_name) {
const v8_mod_interface_t *mp;
if ((mp = (v8_mod_interface_t *)switch_core_hash_find(module_manager.load_hash, mod_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading %s\n", mod_name);
mp->v8_mod_load(info);
} else {
char *err = switch_mprintf("Error loading %s", mod_name);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
}
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(ApiExecute)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *cmd = js_safe_str(*str);
string arg;
switch_core_session_t *session = NULL;
switch_stream_handle_t stream = { 0 };
if (!strcasecmp(cmd, "jsapi")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid API Call!\n");
info.GetReturnValue().Set(false);
return;
}
if (info.Length() > 1) {
String::Utf8Value str2(info[1]);
arg = js_safe_str(*str2);
}
if (info.Length() > 2) {
if (!info[2].IsEmpty() && info[2]->IsObject()) {
Handle<Object> session_obj = Handle<Object>::Cast(info[2]);
FSSession *obj = JSBase::GetInstance<FSSession>(session_obj);
if (obj) {
session = obj->GetSession();
}
}
}
SWITCH_STANDARD_STREAM(stream);
switch_api_execute(cmd, arg.c_str(), session, &stream);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_str_nil((char *) stream.data)));
switch_safe_free(stream.data);
} else {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), ""));
}
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Email)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
string to, from, headers, body, file, convert_cmd, convert_ext;
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
to = js_safe_str(*str);
}
if (info.Length() > 1) {
String::Utf8Value str(info[1]);
from = js_safe_str(*str);
}
if (info.Length() > 2) {
String::Utf8Value str(info[2]);
headers = js_safe_str(*str);
}
if (info.Length() > 3) {
String::Utf8Value str(info[3]);
body = js_safe_str(*str);
}
if (info.Length() > 4) {
String::Utf8Value str(info[4]);
file = js_safe_str(*str);
}
if (info.Length() > 5) {
String::Utf8Value str(info[5]);
convert_cmd = js_safe_str(*str);
}
if (info.Length() > 6) {
String::Utf8Value str(info[6]);
convert_ext = js_safe_str(*str);
}
if (to.c_str() && from.c_str() && headers.c_str() && body.c_str() && switch_simple_email(to.c_str(), from.c_str(), headers.c_str(), body.c_str(), file.c_str(), convert_cmd.c_str(), convert_ext.c_str()) == SWITCH_TRUE) {
info.GetReturnValue().Set(true);
return;
}
info.GetReturnValue().Set(false);
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(Bridge)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
FSSession *jss_a = NULL, *jss_b = NULL;
Handle<Object> obj_a;
Handle<Object> obj_b;
void *bp = NULL;
switch_input_callback_function_t dtmf_func = NULL;
FSInputCallbackState cb_state;
info.GetReturnValue().Set(false);
if (info.Length() > 1) {
if (info[0]->IsObject()) {
obj_a = Handle<Object>::Cast(info[0]);
if (!(jss_a = JSBase::GetInstance<FSSession>(obj_a))) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot find session A"));
return;
}
}
if (info[1]->IsObject()) {
obj_b = Handle<Object>::Cast(info[1]);
if (!(jss_b = JSBase::GetInstance<FSSession>(obj_b))) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot find session B"));
return;
}
}
}
if (!(jss_a && jss_a->GetSession())) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "session A is not ready!"));
return;
}
if (!(jss_b && jss_b->GetSession())) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "session B is not ready!"));
return;
}
if (info.Length() > 2) {
Handle<Function> func = JSBase::GetFunctionFromArg(info.GetIsolate(), info[2]);
if (!func.IsEmpty()) {
cb_state.function.Reset(info.GetIsolate(), func);
if (info.Length() > 3 && !info[3].IsEmpty()) {
cb_state.arg.Reset(info.GetIsolate(), info[3]);
}
cb_state.jss_a = jss_a;
cb_state.jss_b = jss_b;
cb_state.session_obj_a.Reset(info.GetIsolate(), obj_a);
cb_state.session_obj_b.Reset(info.GetIsolate(), obj_b);
cb_state.session_state = jss_a;
dtmf_func = FSSession::CollectInputCallback;
bp = &cb_state;
}
}
switch_ivr_multi_threaded_bridge(jss_a->GetSession(), jss_b->GetSession(), dtmf_func, bp, bp);
info.GetReturnValue().Set(true);
}
/* Replace this with more robust version later */
JS_GLOBAL_FUNCTION_IMPL_STATIC(System)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
char *cmd;
int result;
info.GetReturnValue().Set(false);
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
cmd = *str;
if (cmd) {
result = switch_system(cmd, SWITCH_TRUE);
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), result));
return;
}
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
JS_GLOBAL_FUNCTION_IMPL_STATIC(FileDelete)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
const char *path;
info.GetReturnValue().Set(false);
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
path = *str;
if (path) {
if ((switch_file_remove(path, NULL)) == SWITCH_STATUS_SUCCESS) {
info.GetReturnValue().Set(true);
}
return;
}
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
static const js_function_t fs_proc[] = {
{"console_log", FSGlobal::Log}, // Deprecated
{"consoleLog", FSGlobal::Log},
{"log", FSGlobal::Log}, // Short version of 'consoleLog()'
{"getGlobalVariable", FSGlobal::GlobalGet},
{"setGlobalVariable", FSGlobal::GlobalSet},
{"exit", FSGlobal::Exit},
{"include", FSGlobal::Include},
{"require", FSGlobal::Include}, // Extra version of 'include()'
{"bridge", FSGlobal::Bridge},
{"email", FSGlobal::Email},
{"apiExecute", FSGlobal::ApiExecute},
{"use", FSGlobal::Use},
{"msleep", FSGlobal::Sleep},
{"fileDelete", FSGlobal::FileDelete},
{"system", FSGlobal::System},
{"fetchURL", FSGlobal::FetchURL}, // Deprecated
{"fetchURLHash", FSGlobal::FetchURLHash}, // Deprecated
{"fetchURLFile", FSGlobal::FetchURLFile}, // Deprecated
{"fetchUrl", FSGlobal::FetchURL},
{"fetchUrlHash", FSGlobal::FetchURLHash},
{"fetchUrlFile", FSGlobal::FetchURLFile},
{0}
};
const js_function_t *FSGlobal::GetFunctionDefinitions()
{
return fs_proc;
}
/* 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:
*/

View File

@ -0,0 +1,430 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
*
* fsodbc.cpp -- JavaScript ODBC class
*
*/
#include "fsodbc.hpp"
using namespace std;
using namespace v8;
#ifdef HAVE_ODBC
static const char js_class_name[] = "ODBC";
FSODBC::~FSODBC(void)
{
if (_stmt) {
SQLFreeHandle(SQL_HANDLE_STMT, _stmt);
}
if (_handle) {
switch_odbc_handle_destroy(&_handle);
}
switch_safe_free(_colbuf);
}
string FSODBC::GetJSClassName()
{
return js_class_name;
}
void FSODBC::Init()
{
_handle = NULL;
_stmt = NULL;
_colbuf = NULL;
_cblen = 0;
}
FSODBC *FSODBC::New(char *dsn, char *username, char *password, const v8::FunctionCallbackInfo<Value>& info)
{
FSODBC *new_obj = NULL;
if (!(new_obj = new FSODBC(info))) {
goto err;
}
if (!(new_obj->_handle = switch_odbc_handle_new(dsn, username, password))) {
goto err;
}
new_obj->_dsn = dsn;
return new_obj;
err:
if (new_obj) {
if (new_obj->_handle) {
switch_odbc_handle_destroy(&new_obj->_handle);
}
delete new_obj;
}
return NULL;
}
switch_odbc_status_t FSODBC::Connect()
{
return switch_odbc_handle_connect(_handle);
}
void *FSODBC::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
FSODBC *odbc_obj = NULL;
char *dsn, *username, *password;
int32_t blen = 1024;
if (info.Length() < 3) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid parameters"));
return NULL;
}
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
String::Utf8Value str3(info[2]);
dsn = *str1;
username = *str2;
password = *str3;
if (info.Length() > 3) {
int32_t len = info[3]->Int32Value();
if (len > 0) {
blen = len;
}
}
if (zstr(username)) {
username = NULL;
}
if (zstr(password)) {
password = NULL;
}
if (dsn) {
odbc_obj = New(dsn, username, password, info);
}
if (!odbc_obj) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed to create new ODBC instance"));
return NULL;
}
if (!(odbc_obj->_colbuf = (SQLCHAR *) malloc(blen))) {
delete odbc_obj;
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Memory error"));
return NULL;
}
odbc_obj->_cblen = blen;
return odbc_obj;
}
JS_ODBC_FUNCTION_IMPL(Connect)
{
HandleScope handle_scope(info.GetIsolate());
bool tf = true;
if (Connect() == SWITCH_ODBC_SUCCESS) {
tf = true;
} else {
tf = false;
}
info.GetReturnValue().Set(tf);
}
JS_ODBC_FUNCTION_IMPL(Execute)
{
HandleScope handle_scope(info.GetIsolate());
const char *sql;
bool tf = false;
SQLHSTMT local_stmt;
String::Utf8Value str(info[0]);
if (info.Length() < 1) {
goto done;
}
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
sql = js_safe_str(*str);
if (switch_odbc_handle_exec(_handle, sql, &local_stmt, NULL) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[ODBC] Execute failed for: %s\n", sql);
goto done;
}
SQLFreeHandle(SQL_HANDLE_STMT, local_stmt);
tf = true;
done:
info.GetReturnValue().Set(tf);
}
JS_ODBC_FUNCTION_IMPL(Exec)
{
HandleScope handle_scope(info.GetIsolate());
const char *sql;
bool tf = false;
String::Utf8Value str(info[0]);
if (info.Length() < 1) {
goto done;
}
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
if (_stmt) {
SQLFreeHandle(SQL_HANDLE_STMT, _stmt);
_stmt = NULL;
}
sql = js_safe_str(*str);
if (switch_odbc_handle_exec(_handle, sql, &_stmt, NULL) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[ODBC] query failed: %s\n", sql);
goto done;
}
tf = true;
done:
info.GetReturnValue().Set(tf);
}
JS_ODBC_FUNCTION_IMPL(NumRows)
{
HandleScope handle_scope(info.GetIsolate());
SQLLEN row_count = 0;
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
if (_stmt) {
SQLRowCount(_stmt, &row_count);
}
done:
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), (int32_t)row_count));
}
JS_ODBC_FUNCTION_IMPL(NumCols)
{
HandleScope handle_scope(info.GetIsolate());
SQLSMALLINT cols = 0;
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
if (_stmt) {
SQLNumResultCols(_stmt, &cols);
}
done:
info.GetReturnValue().Set(cols);
}
JS_ODBC_FUNCTION_IMPL(NextRow)
{
HandleScope handle_scope(info.GetIsolate());
int result = 0;
bool tf = false;
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
if (_stmt) {
if ((result = SQLFetch(_stmt) == SQL_SUCCESS)) {
tf = true;
}
}
done:
info.GetReturnValue().Set(tf);
}
JS_ODBC_FUNCTION_IMPL(GetData)
{
HandleScope handle_scope(info.GetIsolate());
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
goto done;
}
if (_stmt) {
SQLSMALLINT nColumns = 0, x = 0;
if (SQLNumResultCols(_stmt, &nColumns) != SQL_SUCCESS) {
goto done;
}
Handle<Array> arg = Array::New(GetIsolate(), nColumns);
for (x = 1; x <= nColumns; x++) {
SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
SQLULEN ColumnSize;
SQLCHAR name[1024] = "";
SQLCHAR *data = _colbuf;
SQLDescribeCol(_stmt, x, name, sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
SQLGetData(_stmt, x, SQL_C_CHAR, _colbuf, _cblen, NULL);
if (name) {
arg->Set(String::NewFromUtf8(GetIsolate(), (const char *)name), String::NewFromUtf8(GetIsolate(), data ? (const char *)data : ""));
}
}
info.GetReturnValue().Set(arg);
return;
}
done:
info.GetReturnValue().Set(false);
}
JS_ODBC_FUNCTION_IMPL_STATIC(Close)
{
JS_CHECK_SCRIPT_STATE();
HandleScope handle_scope(info.GetIsolate());
FSODBC *obj = JSBase::GetInstance<FSODBC>(info);
if (obj) {
delete obj;
}
}
JS_ODBC_FUNCTION_IMPL(Disconnect)
{
HandleScope handle_scope(info.GetIsolate());
if (switch_odbc_handle_get_state(_handle) != SWITCH_ODBC_STATE_CONNECTED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Database is not connected!\n");
return;
}
if (_stmt) {
SQLFreeHandle(SQL_HANDLE_STMT, _stmt);
_stmt = NULL;
}
switch_odbc_handle_disconnect(_handle);
}
JS_ODBC_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
if (!strcmp(js_safe_str(*str), "name")) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), _dsn.length() > 0 ? _dsn.c_str() : ""));
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t odbc_methods[] = {
{"connect", FSODBC::Connect},
{"disconnect", FSODBC::Disconnect},
{"exec", FSODBC::Exec}, // Deprecated
{"query", FSODBC::Exec},
{"execute", FSODBC::Execute},
{"numRows", FSODBC::NumRows},
{"numCols", FSODBC::NumCols},
{"nextRow", FSODBC::NextRow},
{"getData", FSODBC::GetData},
{"close", FSODBC::Close},
{0}
};
static const js_property_t odbc_props[] = {
{"name", FSODBC::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t odbc_desc = {
js_class_name,
FSODBC::Construct,
odbc_methods,
odbc_props
};
static switch_status_t odbc_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &odbc_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t odbc_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ odbc_load
};
const v8_mod_interface_t *FSODBC::GetModuleInterface()
{
return &odbc_module_interface;
}
#endif /* HAVE_ODBC */
/* 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:
*/

View File

@ -0,0 +1,158 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fspcre.cpp -- JavaScript PCRE class
*
*/
#include "fspcre.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "PCRE";
FSPCRE::~FSPCRE(void)
{
if (!_freed && _re) {
switch_regex_safe_free(_re);
switch_safe_free(_str);
}
}
string FSPCRE::GetJSClassName()
{
return js_class_name;
}
void FSPCRE::Init()
{
_re = NULL;
_str = NULL;
_proceed = 0;
memset(&_ovector, 0, sizeof(_ovector));
_freed = 0;
}
void *FSPCRE::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
return new FSPCRE(info);
}
JS_PCRE_FUNCTION_IMPL(Compile)
{
HandleScope handle_scope(info.GetIsolate());
const char *string, *regex_string;
if (info.Length() > 1) {
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
string = js_safe_str(*str1);
regex_string = js_safe_str(*str2);
switch_regex_safe_free(this->_re);
switch_safe_free(this->_str);
js_strdup(this->_str, string);
this->_proceed = switch_regex_perform(this->_str, regex_string, &this->_re, this->_ovector,
sizeof(this->_ovector) / sizeof(this->_ovector[0]));
info.GetReturnValue().Set(this->_proceed ? true : false);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid args"));
}
}
JS_PCRE_FUNCTION_IMPL(Substitute)
{
HandleScope handle_scope(info.GetIsolate());
const char *subst_string;
char *substituted;
if (!this->_proceed) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "REGEX is not compiled or has no matches"));
return;
}
if (info.Length() > 0) {
uint32_t len;
String::Utf8Value str(info[0]);
subst_string = js_safe_str(*str);
len = (uint32_t) (strlen(this->_str) + strlen(subst_string) + 10) * this->_proceed;
substituted = (char *)malloc(len);
switch_assert(substituted != NULL);
switch_perform_substitution(this->_re, this->_proceed, subst_string, this->_str, substituted, len, this->_ovector);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), substituted));
free(substituted);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid Args"));
}
}
JS_PCRE_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
if (!strcmp(js_safe_str(*str), "ready")) {
info.GetReturnValue().Set(true);
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t pcre_proc[] = {
{"compile", FSPCRE::Compile},
{"substitute", FSPCRE::Substitute},
{0}
};
static const js_property_t pcre_prop[] = {
{"ready", FSPCRE::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t pcre_desc = {
js_class_name,
FSPCRE::Construct,
pcre_proc,
pcre_prop
};
const js_class_definition_t *FSPCRE::GetClassDefinition()
{
return &pcre_desc;
}
/* 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:
*/

View File

@ -0,0 +1,204 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
* William King <william.king@quentustech.com>
*
* fsrequest.cpp -- JavaScript Request class
*
*/
#include "fsrequest.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "Request";
FSRequest::~FSRequest(void)
{
}
string FSRequest::GetJSClassName()
{
return js_class_name;
}
void FSRequest::Init()
{
_cmd = NULL;
_stream = NULL;
}
void FSRequest::Init(const char *cmd, switch_stream_handle_t *stream)
{
this->_cmd = cmd;
this->_stream = stream;
}
JS_REQUEST_FUNCTION_IMPL(Write)
{
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
if (*str) this->_stream->write_function(this->_stream, "%s", *str);
info.GetReturnValue().Set(true);
return;
}
info.GetReturnValue().Set(false);
}
JS_REQUEST_FUNCTION_IMPL(AddHeader)
{
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 1) {
String::Utf8Value str1(info[0]);
String::Utf8Value str2(info[1]);
const char *hname = js_safe_str(*str1);
const char *hval = js_safe_str(*str2);
switch_event_add_header_string(this->_stream->param_event, SWITCH_STACK_BOTTOM, hname, hval);
info.GetReturnValue().Set(true);
return;
}
info.GetReturnValue().Set(false);
}
JS_REQUEST_FUNCTION_IMPL(GetHeader)
{
HandleScope handle_scope(info.GetIsolate());
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
const char *hname = js_safe_str(*str);
char *val = switch_event_get_header(this->_stream->param_event, hname);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(val)));
return;
}
info.GetReturnValue().Set(false);
}
JS_REQUEST_FUNCTION_IMPL(DumpEnv)
{
HandleScope handle_scope(info.GetIsolate());
string how = "text";
if (info.Length() > 0) {
String::Utf8Value str(info[0]);
how = js_safe_str(*str);
}
if (!strcasecmp(how.c_str(), "xml")) {
switch_xml_t xml;
if ((xml = switch_event_xmlize(this->_stream->param_event, SWITCH_VA_NONE))) {
char *xmlstr;
if ((xmlstr = switch_xml_toxml(xml, SWITCH_FALSE))) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), xmlstr));
switch_safe_free(xmlstr);
switch_xml_free(xml);
return;
} else {
switch_xml_free(xml);
}
}
} else if (!strcasecmp(how.c_str(), "json")) {
char *buf = NULL;
if (switch_event_serialize_json(this->_stream->param_event, &buf) == SWITCH_STATUS_SUCCESS) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(buf)));
switch_safe_free(buf);
return;
} else {
switch_safe_free(buf);
}
} else {
char *buf = NULL;
if (switch_event_serialize(this->_stream->param_event, &buf, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(buf)));
switch_safe_free(buf);
return;
} else {
switch_safe_free(buf);
}
}
info.GetReturnValue().Set(false);
}
JS_REQUEST_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
if (!strcmp(js_safe_str(*str), "command")) {
if (this->_cmd) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), this->_cmd));
} else {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), ""));
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t request_proc[] = {
{"write", FSRequest::Write},
{"getHeader", FSRequest::GetHeader},
{"addHeader", FSRequest::AddHeader},
{"dumpENV", FSRequest::DumpEnv}, // Deprecated
{"dumpEnv", FSRequest::DumpEnv},
{0}
};
static const js_property_t request_prop[] = {
{"command", FSRequest::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t request_desc = {
js_class_name,
NULL, /* No constructor given, since it's not allowed to construct this from JS code */
request_proc,
request_prop
};
const js_class_definition_t *FSRequest::GetClassDefinition()
{
return &request_desc;
}
/* 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:
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,337 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in Spidermonkey Socket Module
*
* The Initial Developer of the Original Code is
* Jonas Gauffin <jonas.gauffin@gmail.com>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
* Jonas Gauffin <jonas.gauffin@gmail.com>
*
* fssocket.cpp -- JavaScript Socket class
*
*/
#include "fssocket.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "Socket";
FSSocket::~FSSocket(void)
{
if (_socket) {
switch_socket_shutdown(_socket, SWITCH_SHUTDOWN_READWRITE);
switch_socket_close(_socket);
}
if (_pool) {
switch_core_destroy_memory_pool(&_pool);
}
}
string FSSocket::GetJSClassName()
{
return js_class_name;
}
void FSSocket::Init()
{
_socket = NULL;
_pool = NULL;
_read_buffer = NULL;
_buffer_size = 0;
_state = 0;
}
void *FSSocket::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
FSSocket *js_socket_obj = NULL;
switch_memory_pool_t *pool;
switch_socket_t *socket;
switch_status_t ret;
switch_core_new_memory_pool(&pool);
ret = switch_socket_create(&socket, AF_INET, SOCK_STREAM, SWITCH_PROTO_TCP, pool);
if (ret != SWITCH_STATUS_SUCCESS) {
switch_core_destroy_memory_pool(&pool);
char *err = switch_mprintf("Failed to create socket, reason: %d", ret);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return NULL;
}
js_socket_obj = new FSSocket(info);
js_socket_obj->_pool = pool;
js_socket_obj->_socket = socket;
return js_socket_obj;
}
JS_SOCKET_FUNCTION_IMPL(Connect)
{
if (info.Length() == 2) {
String::Utf8Value str(info[0]);
const char *host = js_safe_str(*str);
int32_t port;
switch_sockaddr_t *addr;
switch_status_t ret;
port = info[1]->Int32Value();
/* Recreate socket if it has been closed */
if (!this->_socket) {
if ((ret = switch_socket_create(&this->_socket, AF_INET, SOCK_STREAM, SWITCH_PROTO_TCP, this->_pool)) != SWITCH_STATUS_SUCCESS) {
char *err = switch_mprintf("Failed to create socket, reason: %d", ret);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return;
}
}
ret = switch_sockaddr_info_get(&addr, host, AF_INET, (switch_port_t) port, 0, this->_pool);
if (ret != SWITCH_STATUS_SUCCESS) {
char *err = switch_mprintf("switch_sockaddr_info_get failed: %d", ret);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), err));
free(err);
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Connecting to: %s:%d.\n", host, port);
ret = switch_socket_connect(this->_socket, addr);
if (ret != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_connect failed: %d.\n", ret);
info.GetReturnValue().Set(false);
} else
info.GetReturnValue().Set(true);
}
}
JS_SOCKET_FUNCTION_IMPL(Send)
{
if (!this->_socket) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Socket is not active"));
return;
}
if (info.Length() == 1) {
switch_status_t ret;
String::Utf8Value str(info[0]);
const char *buffer = js_safe_str(*str);
switch_size_t len = strlen(buffer);
ret = switch_socket_send(this->_socket, buffer, &len);
if (ret != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_send failed: %d.\n", ret);
info.GetReturnValue().Set(false);
} else
info.GetReturnValue().Set(true);
} else {
info.GetReturnValue().Set(false);
}
}
JS_SOCKET_FUNCTION_IMPL(ReadBytes)
{
if (!this->_socket) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Socket is not active"));
return;
}
if (info.Length() == 1) {
int32_t bytes_to_read;
switch_status_t ret;
switch_size_t len;
bytes_to_read = info[0]->Int32Value();
len = (switch_size_t) bytes_to_read;
if (this->_buffer_size < len) {
this->_read_buffer = (char *)switch_core_alloc(this->_pool, len + 1);
this->_buffer_size = bytes_to_read + 1;
}
ret = switch_socket_recv(this->_socket, this->_read_buffer, &len);
if (ret != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_send failed: %d.\n", ret);
info.GetReturnValue().Set(false);
return;
} else {
this->_read_buffer[len] = 0;
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(this->_read_buffer)));
return;
}
}
info.GetReturnValue().Set(false);
}
JS_SOCKET_FUNCTION_IMPL(Read)
{
string delimiter = "\n";
switch_status_t ret = SWITCH_STATUS_FALSE;
switch_size_t len = 1;
switch_size_t total_length = 0;
int can_run = TRUE;
char tempbuf[2];
if (!this->_socket) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Socket is not active"));
return;
}
if (info.Length() == 1) {
String::Utf8Value str(info[0]);
delimiter = js_safe_str(*str);
}
if (this->_read_buffer == 0) {
this->_read_buffer = (char *)switch_core_alloc(this->_pool, this->_buffer_size);
}
while (can_run == TRUE) {
ret = switch_socket_recv(this->_socket, tempbuf, &len);
if (ret != SWITCH_STATUS_SUCCESS)
break;
tempbuf[1] = 0;
if (tempbuf[0] == delimiter[0])
break;
else if (tempbuf[0] == '\r' && delimiter[0] == '\n')
continue;
else {
// Buffer is full, let's increase it.
if (total_length == this->_buffer_size - 1) {
switch_size_t new_size = this->_buffer_size + 4196;
char *new_buffer = (char *)switch_core_alloc(this->_pool, this->_buffer_size);
memcpy(new_buffer, this->_read_buffer, total_length);
this->_buffer_size = new_size;
this->_read_buffer = new_buffer;
}
this->_read_buffer[total_length] = tempbuf[0];
++total_length;
}
}
if (ret != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "socket receive failed: %d.\n", ret);
info.GetReturnValue().Set(false);
} else {
this->_read_buffer[total_length] = 0;
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(this->_read_buffer)));
}
}
JS_SOCKET_FUNCTION_IMPL(Close)
{
switch_socket_shutdown(this->_socket, SWITCH_SHUTDOWN_READWRITE);
switch_socket_close(this->_socket);
this->_socket = NULL;
}
JS_SOCKET_GET_PROPERTY_IMPL(GetProperty)
{
HandleScope handle_scope(info.GetIsolate());
String::Utf8Value str(property);
if (!this->_socket) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Socket is not active"));
return;
}
if (!strcmp(js_safe_str(*str), "address")) {
switch_sockaddr_t *sa = NULL;
char tmp[30];
switch_socket_addr_get(&sa, SWITCH_TRUE, this->_socket);
if (sa && switch_get_addr(tmp, sizeof(tmp), sa) && !zstr(tmp)) {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), tmp));
} else {
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "unknown"));
}
} else if (!strcmp(js_safe_str(*str), "port")) {
switch_sockaddr_t *sa = NULL;
switch_socket_addr_get(&sa, SWITCH_TRUE, this->_socket);
if (sa) {
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), switch_sockaddr_get_port(sa)));
} else {
info.GetReturnValue().Set(Integer::New(info.GetIsolate(), 0));
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad property"));
}
}
static const js_function_t socket_methods[] = {
{"connect", FSSocket::Connect},
{"close", FSSocket::Close},
{"send", FSSocket::Send},
{"readBytes", FSSocket::ReadBytes},
{"read", FSSocket::Read},
{0}
};
static const js_property_t socket_props[] = {
{"address", FSSocket::GetProperty, JSBase::DefaultSetProperty},
{"port", FSSocket::GetProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t socket_desc = {
js_class_name,
FSSocket::Construct,
socket_methods,
socket_props
};
static switch_status_t socket_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &socket_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t socket_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ socket_load
};
const v8_mod_interface_t *FSSocket::GetModuleInterface()
{
return &socket_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,378 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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.
*
* Ported from the Original Code in 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):
* Peter Olsson <peter@olssononline.se>
* Anthony Minessale II <anthm@freeswitch.org>
*
* fsteletone.cpp -- JavaScript TeleTone class
*
*/
#include "fsteletone.hpp"
#include "fssession.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "TeleTone";
FSTeleTone::~FSTeleTone(void)
{
/* Release persistent JS handles */
_function.Reset();
_arg.Reset();
if (_timer) {
switch_core_timer_destroy(_timer);
}
teletone_destroy_session(&_ts);
switch_buffer_destroy(&_audio_buffer);
switch_core_codec_destroy(&_codec);
if (_pool) {
switch_core_destroy_memory_pool(&_pool);
}
}
string FSTeleTone::GetJSClassName()
{
return js_class_name;
}
void FSTeleTone::Init()
{
memset(&_ts, 0, sizeof(_ts));
_session = NULL;
memset(&_codec, 0, sizeof(_codec));
_audio_buffer = NULL;
_pool = NULL;
_timer = NULL;
memset(&_timer_base, 0, sizeof(_timer_base));
flags = 0;
}
typedef enum {
TTF_DTMF = (1 << 0)
} teletone_flag_t;
int FSTeleTone::Handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
{
FSTeleTone *tto = (FSTeleTone *)ts->user_data;
int wrote;
if (!tto) {
return -1;
}
wrote = teletone_mux_tones(ts, map);
switch_buffer_write(tto->_audio_buffer, ts->buffer, wrote * 2);
return 0;
}
void *FSTeleTone::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
FSTeleTone *tto = NULL;
FSSession *jss = NULL;
switch_memory_pool_t *pool;
string timer_name;
switch_codec_implementation_t read_impl;
memset(&read_impl, 0, sizeof(read_impl));
if (info.Length() > 0 && info[0]->IsObject()) {
Handle<Object> session_obj(Handle<Object>::Cast(info[0]));
if (!session_obj.IsEmpty()) {
if (!(jss = JSBase::GetInstance<FSSession>(session_obj)) || !jss->GetSession()) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot Find Session [1]"));
return NULL;
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot Find Session [2]"));
return NULL;
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Missing Session Arg"));
return NULL;
}
if (info.Length() > 1) {
String::Utf8Value str(info[1]);
timer_name = js_safe_str(*str);
}
switch_core_new_memory_pool(&pool);
if (!(tto = new FSTeleTone(info))) {
switch_core_destroy_memory_pool(&pool);
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Memory Error"));
return NULL;
}
switch_core_session_get_read_impl(jss->GetSession(), &read_impl);
if (switch_core_codec_init(&tto->_codec,
"L16",
NULL,
read_impl.actual_samples_per_second,
read_impl.microseconds_per_packet / 1000,
read_impl.number_of_channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
} else {
switch_core_destroy_memory_pool(&pool);
delete tto;
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Raw codec activation failed"));
return NULL;
}
if (timer_name.length() > 0) {
unsigned int ms = read_impl.microseconds_per_packet / 1000;
if (switch_core_timer_init(&tto->_timer_base,
timer_name.c_str(), ms, (read_impl.samples_per_second / 50) * read_impl.number_of_channels, pool) == SWITCH_STATUS_SUCCESS) {
tto->_timer = &tto->_timer_base;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Success %u\n", ms);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Failed\n");
}
}
switch_buffer_create_dynamic(&tto->_audio_buffer, JS_BLOCK_SIZE, JS_BUFFER_SIZE, 0);
tto->_pool = pool;
tto->_session = jss->GetSession();
teletone_init_session(&tto->_ts, 0, FSTeleTone::Handler, tto);
return tto;
}
JS_TELETONE_FUNCTION_IMPL(AddTone)
{
if (info.Length() > 2) {
int x;
int nmax = info.Length();
const char *map_str;
String::Utf8Value str(info[0]);
map_str = js_safe_str(*str);
if ( TELETONE_MAX_TONES < nmax ) {
nmax = TELETONE_MAX_TONES;
}
for (x = 1; x < nmax; x++) {
String::Utf8Value fval(info[x]);
if (*fval) {
_ts.TONES[(int) *map_str].freqs[x - 1] = strtod(*fval, NULL);
}
}
return;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
JS_TELETONE_FUNCTION_IMPL(OnDTMF)
{
/* Clear callbacks first */
_function.Reset();
_arg.Reset();
switch_clear_flag(this, TTF_DTMF);
info.GetReturnValue().Set(false);
if (info.Length() > 0) {
Handle<Function> func = JSBase::GetFunctionFromArg(info.GetIsolate(), info[0]);
if (!func.IsEmpty()) {
_function.Reset(info.GetIsolate(), func);
if (info.Length() > 1 && !info[1].IsEmpty()) {
_arg.Reset(info.GetIsolate(), info[1]);
}
switch_set_flag(this, TTF_DTMF);
info.GetReturnValue().Set(true);
}
}
}
JS_TELETONE_FUNCTION_IMPL(Generate)
{
int32_t loops = 0;
if (info.Length() > 0) {
const char *script;
switch_core_session_t *session;
switch_frame_t write_frame = { 0 };
unsigned char *fdata[1024];
switch_frame_t *read_frame;
switch_channel_t *channel;
if (info.Length() > 1) {
if (!info[1]->IsInt32() || !(loops = info[1]->Int32Value())) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Cannot get second argument (should be int)"));
return;
}
loops--;
}
if (_audio_buffer) {
switch_buffer_zero(_audio_buffer);
}
_ts.debug = 1;
_ts.debug_stream = switch_core_get_console();
String::Utf8Value str(info[0]);
script = js_safe_str(*str);
teletone_run(&_ts, script);
session = this->_session;
write_frame.codec = &_codec;
write_frame.data = fdata;
write_frame.buflen = sizeof(fdata);
channel = switch_core_session_get_channel(session);
if (_timer) {
switch_core_service_session(session);
}
if (_audio_buffer && loops) {
switch_buffer_set_loops(_audio_buffer, loops);
}
for (;;) {
if (switch_test_flag(this, TTF_DTMF)) {
char dtmf[128];
const char *ret;
if (switch_channel_has_dtmf(channel)) {
HandleScope hs(info.GetIsolate());
uint32_t aargc = 0;
Handle<Value> aargv[4];
switch_channel_dequeue_dtmf_string(channel, dtmf, sizeof(dtmf));
aargv[aargc++] = String::NewFromUtf8(info.GetIsolate(), dtmf);
if (!_arg.IsEmpty()) {
aargv[aargc++] = Handle<Value>::New(info.GetIsolate(), _arg);
}
Handle<Function> func = Handle<Function>::New(info.GetIsolate(), _function);
Handle<Value> res = func->Call(info.GetIsolate()->GetCurrentContext()->Global(), aargc, aargv);
String::Utf8Value tmp(res);
ret = js_safe_str(*tmp);
if (strcmp(ret, "true") && strcmp(ret, "undefined")) {
info.GetReturnValue().Set(res);
return;
}
}
}
if (_timer) {
if (switch_core_timer_next(_timer) != SWITCH_STATUS_SUCCESS) {
break;
}
} else {
switch_status_t status;
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
}
if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(_audio_buffer,
fdata, write_frame.codec->implementation->decoded_bytes_per_packet)) <= 0) {
break;
}
write_frame.samples = write_frame.datalen / 2;
if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad Write\n");
break;
}
}
if (_timer) {
switch_core_thread_session_end(session);
}
return;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
JS_TELETONE_GET_PROPERTY_IMPL(GetNameProperty)
{
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), "TeleTone"));
}
static const js_function_t teletone_methods[] = {
{"generate", FSTeleTone::Generate},
{"onDTMF", FSTeleTone::OnDTMF},
{"addTone", FSTeleTone::AddTone},
{0}
};
static const js_property_t teletone_props[] = {
{"name", FSTeleTone::GetNameProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t teletone_desc = {
js_class_name,
FSTeleTone::Construct,
teletone_methods,
teletone_props
};
static switch_status_t teletone_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &teletone_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t teletone_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ teletone_load
};
const v8_mod_interface_t *FSTeleTone::GetModuleInterface()
{
return &teletone_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,462 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for 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):
* Peter Olsson <peter@olssononline.se>
*
* fsxml.cpp -- JavaScript XML class
*
*/
#include "fsxml.hpp"
using namespace std;
using namespace v8;
static const char js_class_name[] = "XML";
FSXML::~FSXML(void)
{
if (!_rootObject) {
/* This is the root object */
/* Free the xml struct if it still exists */
if (_xml) {
switch_xml_free(_xml);
}
/* Free all sub-objects in the hash and destroy the hash */
DestroyHash();
} else if (_rootObject && _xml && _rootObject->_obj_hash) {
/* This is not the root object. Remove this object from the root oject's hash */
_rootObject->DeleteObjectInHash(_xml);
}
/* Clear JS reference to the root node */
_rootJSObject.Reset();
if (_pool) {
switch_core_destroy_memory_pool(&_pool);
}
}
string FSXML::GetJSClassName()
{
return js_class_name;
}
void FSXML::Init()
{
_xml = NULL;
_obj_hash = NULL;
_pool = NULL;
_rootObject = NULL;
}
void FSXML::InitRootObject()
{
/* Create hash and pool - for the root object only */
if (switch_core_new_memory_pool(&_pool) == SWITCH_STATUS_SUCCESS && _pool) {
if (switch_core_hash_init(&_obj_hash, _pool) != SWITCH_STATUS_SUCCESS) {
switch_core_destroy_memory_pool(&_pool);
_obj_hash = NULL;
_pool = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to init hash\n");
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create memory pool\n");
}
}
void *FSXML::Construct(const v8::FunctionCallbackInfo<Value>& info)
{
String::Utf8Value data(info[0]);
switch_xml_t xml;
if (*data && (xml = switch_xml_parse_str_dynamic(*data, SWITCH_TRUE))) {
FSXML *obj = new FSXML(info);
obj->_xml = xml;
obj->InitRootObject();
return obj;
}
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Bad arguments!"));
return NULL;
/*
var xml = new XML(XML_FS_CONF, fs_config_name_string);
var xml = new XML(XML_FILE, file_name_string);
var xml = new XML(XML_NEW, new);
*/
}
Handle<Value> FSXML::GetJSObjFromXMLObj(const switch_xml_t xml, const v8::FunctionCallbackInfo<Value>& info)
{
FSXML *newObj, *rootObj = NULL;
if (!_rootObject) {
rootObj = this;
} else {
rootObj = _rootObject;
}
if (!rootObj) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find XML root node\n");
return Handle<Value>();
}
/* Try to find an existing object in the hash */
if (!(newObj = rootObj->FindObjectInHash(xml))) {
/* Create a new object if it wasn't found in the hash */
if ((newObj = new FSXML(info))) {
if (_rootJSObject.IsEmpty()) {
newObj->_rootJSObject.Reset(info.GetIsolate(), info.Holder()); /* The caller is the owner */
} else {
newObj->_rootJSObject.Reset(info.GetIsolate(), _rootJSObject); /* The owner is stored in the persistent object */
}
newObj->_xml = xml;
newObj->_rootObject = rootObj;
rootObj->StoreObjectInHash(xml, newObj);
newObj->RegisterInstance(info.GetIsolate(), "", true);
}
}
if (newObj) {
return newObj->GetJavaScriptObject();
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new object - memory error?\n");
return Handle<Value>();
}
void FSXML::StoreObjectInHash(switch_xml_t xml, FSXML *obj)
{
if (!_obj_hash) {
return;
}
char *key = switch_mprintf("%p", xml);
switch_core_hash_insert(_obj_hash, key, (void *) obj);
switch_safe_free(key);
}
FSXML *FSXML::FindObjectInHash(switch_xml_t xml)
{
if (!_obj_hash) {
return NULL;
}
char *key = switch_mprintf("%p", xml);
FSXML *obj = (FSXML *)switch_core_hash_find(_obj_hash, key);
switch_safe_free(key);
return obj;
}
void FSXML::DeleteObjectInHash(switch_xml_t xml)
{
if (!_obj_hash) {
return;
}
if (FindObjectInHash(xml)) {
char *key = switch_mprintf("%p", xml);
switch_core_hash_delete(_obj_hash, key);
switch_safe_free(key);
}
}
void FSXML::DestroyHash()
{
switch_hash_index_t *hi;
switch_hash_t *tmp = _obj_hash;
_obj_hash = NULL; /* NULL this, so nothing else tries to modify the hash during cleanup */
if (!tmp) {
return;
}
/* First destroy all objects in the hash */
for (hi = switch_hash_first(NULL, tmp); hi; hi = switch_hash_next(hi)) {
const void *var = NULL;
void *val = NULL;
FSXML *obj;
switch_hash_this(hi, &var, NULL, &val);
if (val) {
obj = static_cast<FSXML *>(val);
delete obj;
}
}
/* And finally destroy the hash itself */
switch_core_hash_destroy(&tmp);
}
JS_XML_FUNCTION_IMPL(GetChild)
{
if (info.Length() > 0) {
String::Utf8Value name(info[0]);
string attr_name, attr_value;
switch_xml_t xml = NULL;
/* Check if attribute name/value was provided as well */
if (info.Length() > 1) {
String::Utf8Value str(info[1]);
attr_name = js_safe_str(*str);
if (info.Length() > 2) {
String::Utf8Value str2(info[2]);
attr_value = js_safe_str(*str2);
}
}
/* Find the XML child */
if (*name && !attr_name.length()) {
xml = switch_xml_child(_xml, *name);
} else if (*name) {
xml = switch_xml_find_child(_xml, *name, attr_name.c_str(), attr_value.c_str());
}
/* Return the JS object */
if (xml) {
Handle<Value> jsObj = GetJSObjFromXMLObj(xml, info);
if (jsObj.IsEmpty()) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed!"));
} else {
info.GetReturnValue().Set(jsObj);
}
} else {
info.GetReturnValue().Set(Null(info.GetIsolate()));
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_XML_FUNCTION_IMPL(AddChild)
{
if (info.Length() > 0) {
String::Utf8Value name(info[0]);
switch_xml_t xml;
int offset = 0;
if (info.Length() > 1) {
offset = info[1]->Int32Value();
}
/* Add new child */
xml = switch_xml_add_child_d(_xml, js_safe_str(*name), offset);
/* Return the JS object */
if (xml) {
Handle<Value> jsObj = GetJSObjFromXMLObj(xml, info);
if (jsObj.IsEmpty()) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed!"));
} else {
info.GetReturnValue().Set(jsObj);
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "XML error"));
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_XML_FUNCTION_IMPL(Next)
{
switch_xml_t xml;
/* Get next */
xml = switch_xml_next(_xml);
/* Return the JS object */
if (xml) {
Handle<Value> jsObj = GetJSObjFromXMLObj(xml, info);
if (jsObj.IsEmpty()) {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Failed!"));
} else {
info.GetReturnValue().Set(jsObj);
}
} else {
info.GetReturnValue().Set(Null(info.GetIsolate()));
}
}
JS_XML_FUNCTION_IMPL(GetAttribute)
{
if (info.Length() > 0) {
String::Utf8Value name(info[0]);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), switch_xml_attr_soft(_xml, js_safe_str(*name))));
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_XML_FUNCTION_IMPL(SetAttribute)
{
if (info.Length() > 0) {
String::Utf8Value name(info[0]);
string val;
if (info.Length() > 1) {
String::Utf8Value str(info[1]);
val = js_safe_str(*str);
}
if (switch_xml_set_attr_d(_xml, js_safe_str(*name), val.c_str())) {
info.GetReturnValue().Set(true);
} else {
info.GetReturnValue().Set(false);
}
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "Invalid arguments"));
}
}
JS_XML_IMPL_STATIC(Remove)
{
JS_CHECK_SCRIPT_STATE();
FSXML *obj = JSBase::GetInstance<FSXML>(info);
if (obj) {
switch_xml_remove(obj->_xml);
if (!obj->_rootObject) {
/* If this is the root node, make sure we don't try to free _xml again */
obj->_xml = NULL;
}
delete obj;
} else {
String::Utf8Value str(info.Holder());
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No valid internal data available for %s when calling FSXML::Remove()\n", *str ? *str : "[unknown]");
}
}
JS_XML_FUNCTION_IMPL(Copy)
{
FSXML *obj;
switch_xml_t xml;
/* Create a new xml object from the existing. The new object will be a new root object */
xml = switch_xml_dup(_xml);
if (xml && (obj = new FSXML(info))) {
obj->_xml = xml;
obj->InitRootObject();
obj->RegisterInstance(info.GetIsolate(), "", true);
info.GetReturnValue().Set(obj->GetJavaScriptObject());
} else {
info.GetIsolate()->ThrowException(String::NewFromUtf8(info.GetIsolate(), "XML error"));
}
}
JS_XML_FUNCTION_IMPL(Serialize)
{
char *data = switch_xml_toxml(_xml, SWITCH_FALSE);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(data)));
switch_safe_free(data);
}
JS_XML_GET_PROPERTY_IMPL(GetNameProperty)
{
const char *data = switch_xml_name(_xml);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(data)));
}
JS_XML_GET_PROPERTY_IMPL(GetDataProperty)
{
const char *data = switch_xml_txt(_xml);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(data)));
}
JS_XML_SET_PROPERTY_IMPL(SetDataProperty)
{
String::Utf8Value str(value);
switch_xml_set_txt_d(_xml, js_safe_str(*str));
}
JS_XML_GET_PROPERTY_IMPL(GetXmlErrorProperty)
{
const char *data = switch_xml_error(_xml);
info.GetReturnValue().Set(String::NewFromUtf8(info.GetIsolate(), js_safe_str(data)));
}
static const js_function_t xml_methods[] = {
{"getChild", FSXML::GetChild},
{"addChild", FSXML::AddChild},
{"next", FSXML::Next},
{"getAttribute", FSXML::GetAttribute},
{"setAttribute", FSXML::SetAttribute},
{"remove", FSXML::Remove},
{"copy", FSXML::Copy},
{"serialize", FSXML::Serialize},
{0}
};
static const js_property_t xml_props[] = {
{"name", FSXML::GetNameProperty, JSBase::DefaultSetProperty},
{"data", FSXML::GetDataProperty, FSXML::SetDataProperty},
{"xmlError", FSXML::GetXmlErrorProperty, JSBase::DefaultSetProperty},
{0}
};
static const js_class_definition_t xml_desc = {
js_class_name,
FSXML::Construct,
xml_methods,
xml_props
};
static switch_status_t xml_load(const v8::FunctionCallbackInfo<Value>& info)
{
JSBase::Register(info.GetIsolate(), &xml_desc);
return SWITCH_STATUS_SUCCESS;
}
static const v8_mod_interface_t xml_module_interface = {
/*.name = */ js_class_name,
/*.js_mod_load */ xml_load
};
const v8_mod_interface_t *FSXML::GetModuleInterface()
{
return &xml_module_interface;
}
/* 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:
*/

View File

@ -0,0 +1,269 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* jsbase.cpp -- JavaScript Base class (all other JS class implementations must inherit JSBase)
*
*/
#include "javascript.hpp"
#include <string.h>
#include <assert.h>
using namespace std;
using namespace v8;
JSBase::JSBase(JSMain *owner)
{
persistentHandle = new Persistent<Object>();
autoDestroy = false;
if ((js = owner)) {
js->AddActiveInstance(this);
}
}
JSBase::JSBase(const v8::FunctionCallbackInfo<Value>& info)
{
persistentHandle = new Persistent<Object>();
autoDestroy = false;
if ((js = JSMain::GetScriptInstanceFromIsolate(info.GetIsolate()))) {
js->AddActiveInstance(this);
}
}
JSBase::~JSBase(void)
{
if (js) {
js->RemoveActiveInstance(this);
}
if (persistentHandle->IsEmpty()) {
delete persistentHandle;
return;
}
/* If the object is still alive inside V8, set the internal field to NULL. But only if we're actually inside a JS context */
if (!persistentHandle->IsNearDeath() && !GetIsolate()->GetCurrentContext().IsEmpty()) {
Handle<Object> jsObj = GetJavaScriptObject();
jsObj->SetInternalField(0, Null(GetIsolate()));
}
persistentHandle->ClearWeak();
persistentHandle->Reset();
delete persistentHandle;
}
Handle<Object> JSBase::GetJavaScriptObject()
{
/* Returns the javascript object related to this C++ instance */
return Handle<Object>::New(GetIsolate(), *persistentHandle);
}
void JSBase::AddInstance(Isolate *isolate, const Handle<Object>& handle, const Handle<External>& object, bool autoDestroy)
{
// Get the actual C++ class pointer
JSBase *obj = static_cast<JSBase*>(object->Value());
// Sanity check
assert(obj->persistentHandle->IsEmpty());
// Store the C++ instance in JavaScript engine.
assert(handle->InternalFieldCount() > 0);
handle->SetInternalField(0, object);
obj->autoDestroy = autoDestroy;
// Make the handle weak
obj->persistentHandle->Reset(isolate, handle);
obj->persistentHandle->SetWeak<JSBase>(obj, WeakCallback);
obj->persistentHandle->MarkIndependent();
}
void JSBase::WeakCallback(const WeakCallbackData<Object, JSBase>& data)
{
JSBase *wrap = data.GetParameter();
Local<Object> pobj = data.GetValue();
if (wrap->autoDestroy) {
HandleScope scope(data.GetIsolate());
assert(pobj == *wrap->persistentHandle);
delete wrap;
} else if (!wrap->persistentHandle->IsEmpty()) {
wrap->persistentHandle->ClearWeak();
wrap->persistentHandle->Reset();
}
}
void JSBase::CreateInstance(const v8::FunctionCallbackInfo<Value>& args)
{
Handle<External> external;
bool autoDestroy = true;
bool constructorFailed = false;
if (!args.IsConstructCall()) {
args.GetIsolate()->ThrowException(String::NewFromUtf8(args.GetIsolate(), "Seems you forgot the 'new' operator."));
return;
}
if (args[0]->IsExternal()) {
// The argument is an existing object, just use that.
external = Handle<External>::Cast(args[0]);
autoDestroy = args[1]->BooleanValue();
} else {
// Create a new C++ instance
Handle<External> ex = Handle<External>::Cast(args.Callee()->GetHiddenValue(String::NewFromUtf8(args.GetIsolate(), "constructor_method")));
if (ex->Value()) {
ConstructorCallback cb = (ConstructorCallback)ex->Value();
void *p = cb(args);
if (p) {
external = External::New(args.GetIsolate(), p);
} else {
constructorFailed = true;
}
}
}
// Add this instance to Javascript.
if (!external.IsEmpty()) {
AddInstance(args.GetIsolate(), args.This(), external, autoDestroy);
// Return the newly created object
args.GetReturnValue().Set(args.This());
} else if (!constructorFailed) {
args.GetIsolate()->ThrowException(String::NewFromUtf8(args.GetIsolate(), "This class cannot be created from javascript."));
} else {
/* Use whatever was set from the constructor */
}
}
void JSBase::Register(Isolate *isolate, const js_class_definition_t *desc)
{
// Get the context's global scope (that's where we'll put the constructor)
Handle<Object> global = isolate->GetCurrentContext()->Global();
// Create function template for our constructor it will call the JSBase::createInstance method
Handle<FunctionTemplate> function = FunctionTemplate::New(isolate, JSBase::CreateInstance);
function->SetClassName(String::NewFromUtf8(isolate, desc->name));
// Make room for saving the C++ object reference somewhere
function->InstanceTemplate()->SetInternalFieldCount(1);
// Add methods to the object
for (int i = 0;; i++) {
if (!desc->functions[i].func) break;
function->InstanceTemplate()->Set(String::NewFromUtf8(isolate, desc->functions[i].name), FunctionTemplate::New(isolate, desc->functions[i].func));
}
// Add properties to the object
for (int i = 0;; i++) {
if (!desc->properties[i].get) break;
function->InstanceTemplate()->SetAccessor(String::NewFromUtf8(isolate, desc->properties[i].name), desc->properties[i].get, desc->properties[i].set);
}
function->GetFunction()->SetHiddenValue(String::NewFromUtf8(isolate, "constructor_method"), External::New(isolate, (void *)desc->constructor));
// Set the function in the global scope, to make it available
global->Set(v8::String::NewFromUtf8(isolate, desc->name), function->GetFunction());
}
void JSBase::RegisterInstance(Isolate *isolate, string name, bool autoDestroy)
{
// Get the context's global scope (that's where we'll put the constructor)
Handle<Object> global = isolate->GetCurrentContext()->Global();
Local<Function> func = Local<Function>::Cast(global->Get(v8::String::NewFromUtf8(isolate, this->GetJSClassName().c_str())));
// Add the C++ instance as an argument, so it won't try to create another one.
Handle<Value> args[] = { External::New(isolate, this), Boolean::New(isolate, autoDestroy) };
Handle<Object> newObj = func->NewInstance(2, args);
// Add the instance to JavaScript.
if (name.size() > 0) {
global->Set(String::NewFromUtf8(isolate, name.c_str()), newObj);
}
}
JSMain *JSBase::GetOwner()
{
return js;
}
Isolate *JSBase::GetIsolate()
{
return (js && js->GetIsolate()) ? js->GetIsolate() : NULL;
}
bool JSBase::GetAutoDestroy()
{
return autoDestroy;
}
Handle<Function> JSBase::GetFunctionFromArg(Isolate *isolate, const Local<Value>& arg)
{
Handle<Function> func;
if (!arg.IsEmpty() && arg->IsFunction()) {
// Cast the argument directly to a function
func = Handle<Function>::Cast(arg);
} else if (!arg.IsEmpty() && arg->IsString()) {
Handle<String> tmp = Handle<String>::Cast(arg);
if (!tmp.IsEmpty() && *tmp) {
// Fetch the actual function pointer from the global context (by function name)
Handle<Value> val = isolate->GetCurrentContext()->Global()->Get(tmp);
if (!val.IsEmpty() && val->IsFunction()) {
func = Handle<Function>::Cast(val);
}
}
}
if (!func.IsEmpty() && func->IsFunction()) {
return func;
} else {
return Handle<Function>();
}
}
void JSBase::DefaultSetProperty(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
{
info.GetIsolate()->ThrowException(v8::String::NewFromUtf8(info.GetIsolate(), "this property cannot be changed!"));
}
/* 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:
*/

View File

@ -0,0 +1,593 @@
/*
* mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2013-2014, Peter Olsson <peter@olssononline.se>
*
* 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 mod_v8 for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Peter Olsson <peter@olssononline.se>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Peter Olsson <peter@olssononline.se>
*
* jsmain.cpp -- JavaScript Main V8 script runner
*
*/
#include "javascript.hpp"
#ifdef V8_ENABLE_DEBUGGING
#include <v8-debug.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
using namespace v8;
#ifdef V8_ENABLE_DEBUGGING
void V8DispatchDebugMessages()
{
Isolate* isolate = Isolate::GetCurrent();
Persistent<Context> *persistent_contect = (Persistent<Context> *)isolate->GetData(1);
HandleScope handle_scope(isolate);
Local<Context> context = Local<Context>::New(isolate, *persistent_contect);
Context::Scope scope(context);
Debug::ProcessDebugMessages();
}
#endif
bool JSMain::FileExists(const char *file)
{
ifstream fh(file);
bool file_exists = false;
if (fh) {
fh.close();
file_exists = true;
}
return file_exists;
}
const string JSMain::LoadFileToString(const string& filename)
{
if (filename.length() == 0) {
return "";
}
ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
if (in) {
string contents;
in.seekg(0, std::ios::end);
contents.resize((size_t)in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
in.close();
return contents;
}
return "";
}
JSMain::JSMain(void)
{
isolate = Isolate::New();
extenderClasses = new vector<const js_class_definition_t *>();
extenderFunctions = new vector<js_function_t *>();
extenderInstances = new vector<registered_instance_t*>();
activeInstances = new set<JSBase *>();
forcedTermination = false;
forcedTerminationMessage = NULL;
forcedTerminationLineNumber = 0;
forcedTerminationScriptFile = NULL;
}
JSMain::~JSMain(void)
{
bool enteredIsolate = false;
for (size_t i = 0; i < extenderInstances->size(); i++) {
registered_instance_t *inst = (*extenderInstances)[i];
if (inst) {
if (inst->name) free(inst->name);
free(inst);
}
}
for (size_t i = 0; i < extenderFunctions->size(); i++) {
js_function_t *proc = (*extenderFunctions)[i];
if (proc) {
if (proc->name) free((char *)proc->name);
free(proc);
}
}
extenderInstances->clear();
extenderClasses->clear();
extenderFunctions->clear();
if (!Isolate::GetCurrent()) {
enteredIsolate = true;
isolate->Enter();
}
/* It's probably not totally safe to call this here, but it whould always be empty by now anyway */
DisposeActiveInstances();
if (enteredIsolate) {
isolate->Exit();
}
delete extenderClasses;
delete extenderFunctions;
delete extenderInstances;
delete activeInstances;
if (forcedTerminationMessage) free(forcedTerminationMessage);
if (forcedTerminationScriptFile) free(forcedTerminationScriptFile);
isolate->Dispose();
}
const string JSMain::GetExceptionInfo(Isolate* isolate, TryCatch* try_catch)
{
HandleScope handle_scope(isolate);
String::Utf8Value exception(try_catch->Exception());
const char *exception_string = js_safe_str(*exception);
Handle<Message> message = try_catch->Message();
string res;
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just return the exception.
res = exception_string;
} else {
String::Utf8Value filename(message->GetScriptResourceName());
const char *filename_string = js_safe_str(*filename);
int linenum = message->GetLineNumber();
ostringstream ss;
ss << filename_string << ":" << linenum << ": " << exception_string << "\r\n";
// Print line of source code.
String::Utf8Value sourceline(message->GetSourceLine());
const char *sourceline_string = js_safe_str(*sourceline);
ss << sourceline_string << "\r\n";
// Print wavy underline.
int start = message->GetStartColumn();
for (int i = 0; i < start; i++) {
ss << " ";
}
int end = message->GetEndColumn();
for (int i = start; i < end; i++) {
ss << "^";
}
res = ss.str();
}
return res;
}
void JSMain::Include(const v8::FunctionCallbackInfo<Value>& args)
{
for (int i = 0; i < args.Length(); i++) {
HandleScope handle_scope(args.GetIsolate());
String::Utf8Value str(args[i]);
// load_file loads the file with this name into a string
string js_file = LoadFileToString(js_safe_str(*str));
if (js_file.length() > 0) {
Handle<String> source = String::NewFromUtf8(args.GetIsolate(), js_file.c_str());
Handle<Script> script = Script::Compile(source, args[i]);
args.GetReturnValue().Set(script->Run());
return;
}
}
args.GetReturnValue().Set(Undefined(args.GetIsolate()));
}
void JSMain::Log(const v8::FunctionCallbackInfo<Value>& args)
{
HandleScope handle_scope(args.GetIsolate());
String::Utf8Value str(args[0]);
printf("%s\r\n", js_safe_str(*str));
args.GetReturnValue().Set(Undefined(args.GetIsolate()));
}
void JSMain::Version(const v8::FunctionCallbackInfo<Value>& args)
{
args.GetReturnValue().Set(String::NewFromUtf8(args.GetIsolate(), V8::GetVersion()));
}
const string JSMain::ExecuteScript(const string& filename, bool *resultIsError)
{
// Get the file and load into a string.
string data = LoadFileToString(filename);
return ExecuteString(data, filename, resultIsError);
}
const string JSMain::ExecuteString(const string& scriptData, const string& fileName, bool *resultIsError)
{
string res;
bool isError = false;
//solate->Enter();
{
Locker lock(isolate);
Isolate::Scope iscope(isolate);
{
// Create a stack-allocated handle scope.
HandleScope scope(isolate);
isolate->SetData(0, this);
Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::NewFromUtf8(isolate, "include"), FunctionTemplate::New(isolate, Include));
global->Set(String::NewFromUtf8(isolate, "require"), FunctionTemplate::New(isolate, Include));
global->Set(String::NewFromUtf8(isolate, "log"), FunctionTemplate::New(isolate, Log));
for (int i = 0; i < extenderFunctions->size(); i++) {
js_function_t *proc = (*extenderFunctions)[i];
global->Set(String::NewFromUtf8(isolate, proc->name), FunctionTemplate::New(isolate, proc->func));
}
// Create a new context.
Local<Context> context = Context::New(isolate, NULL, global);
if (context.IsEmpty()) {
return "Failed to create new JS context";
}
// Enter the created context for compiling and running the script.
Context::Scope context_scope(context);
// Register all plugins.
for (int i = 0; i < extenderClasses->size(); i++) {
JSBase::Register(isolate, (*extenderClasses)[i]);
}
// Register all instances.
for (int i = 0; i < extenderInstances->size(); i++) {
registered_instance_t *inst = (*extenderInstances)[i];
inst->obj->RegisterInstance(isolate, inst->name, inst->auto_destroy);
}
// Create a string containing the JavaScript source code.
Handle<String> source = String::NewFromUtf8(isolate, scriptData.c_str());
TryCatch try_catch;
// Compile the source code.
Handle<Script> script = Script::Compile(source, Handle<Value>::New(isolate, String::NewFromUtf8(isolate, fileName.c_str())));
if (try_catch.HasCaught()) {
res = JSMain::GetExceptionInfo(isolate, &try_catch);
isError = true;
} else {
// Run the script
Handle<Value> result = script->Run();
if (try_catch.HasCaught()) {
res = JSMain::GetExceptionInfo(isolate, &try_catch);
isError = true;
} else {
if (forcedTermination) {
forcedTermination = false;
res = GetForcedTerminationMessage();
}
// return result as string.
String::Utf8Value ascii(result);
if (*ascii) {
res = *ascii;
}
#ifndef V8_FORCE_GC_AFTER_EXECUTION
DisposeActiveInstances();
#endif
}
}
isolate->SetData(0, NULL);
}
#ifdef V8_FORCE_GC_AFTER_EXECUTION
V8::ContextDisposedNotification();
while (!V8::IdleNotification()) {}
DisposeActiveInstances();
#endif
}
//isolate->Exit();
if (resultIsError) {
*resultIsError = isError;
}
return res;
}
/** Add a class to be used in JS, the definition passed here must never be destroyed */
void JSMain::AddJSExtenderClass(const js_class_definition_t *method)
{
extenderClasses->push_back(method);
}
void JSMain::AddJSExtenderFunction(FunctionCallback func, const string& name)
{
if (!func || name.length() == 0) {
return;
}
js_function_t *proc = (js_function_t *)malloc(sizeof(*proc));
if (proc) {
memset(proc, 0, sizeof(*proc));
proc->func = func;
js_strdup(proc->name, name.c_str());
extenderFunctions->push_back(proc);
}
}
void JSMain::AddJSExtenderInstance(JSBase *instance, const string& objectName, bool autoDestroy)
{
registered_instance_t *inst = (registered_instance_t *)malloc(sizeof(*inst));
if (inst) {
memset(inst, 0, sizeof(*inst));
inst->obj = instance;
if (objectName.size() > 0) js_strdup(inst->name, objectName.c_str());
inst->auto_destroy = autoDestroy;
extenderInstances->push_back(inst);
}
}
JSMain *JSMain::GetScriptInstanceFromIsolate(Isolate* isolate)
{
if (isolate) {
void *p = isolate->GetData(0);
if (p) {
return static_cast<JSMain *>(p);
}
}
return NULL;
}
Isolate *JSMain::GetIsolate()
{
return isolate;
}
void JSMain::Initialize()
{
V8::InitializeICU(); // Initialize();
}
void JSMain::Dispose()
{
// Make sure to cleanup properly!
V8::LowMemoryNotification();
while (!V8::IdleNotification()) {}
V8::Dispose();
}
const vector<const js_class_definition_t *>& JSMain::GetExtenderClasses() const
{
return *extenderClasses;
}
const vector<js_function_t *>& JSMain::GetExtenderFunctions() const
{
return *extenderFunctions;
}
const vector<registered_instance_t*>& JSMain::GetExtenderInstances() const
{
return *extenderInstances;
}
void JSMain::AddActiveInstance(JSBase *obj)
{
activeInstances->insert(obj);
}
void JSMain::RemoveActiveInstance(JSBase *obj)
{
if (obj) {
set<JSBase *>::iterator it = activeInstances->find(obj);
if (it != activeInstances->end()) {
activeInstances->erase(it);
}
}
}
void JSMain::DisposeActiveInstances()
{
set<JSBase *>::iterator it = activeInstances->begin();
size_t c = activeInstances->size();
while (it != activeInstances->end()) {
JSBase *obj = *it;
delete obj; /* After this, the iteratior might be invalid, since the slot in the set might be removed already */
if (c == activeInstances->size()) {
/* Nothing changed in the set, make sure to manually remove this instance from the set */
activeInstances->erase(it);
}
it = activeInstances->begin();
c = activeInstances->size();
}
}
bool JSMain::GetForcedTermination(void)
{
return forcedTermination;
}
void JSMain::ResetForcedTermination(void)
{
forcedTermination = false;
}
const char *JSMain::GetForcedTerminationMessage(void)
{
return js_safe_str(forcedTerminationMessage);
}
const char *JSMain::GetForcedTerminationScriptFile(void)
{
return js_safe_str(forcedTerminationScriptFile);
}
int JSMain::GetForcedTerminationLineNumber(void)
{
return forcedTerminationLineNumber;
}
void JSMain::ExitScript(Isolate *isolate, const char *msg)
{
if (!isolate) {
return;
}
JSMain *js = JSMain::GetScriptInstanceFromIsolate(isolate);
if (js) {
js->forcedTermination = true;
/* Free old data if it exists already */
if (js->forcedTerminationMessage) {
free(js->forcedTerminationMessage);
js->forcedTerminationMessage = NULL;
}
if (js->forcedTerminationScriptFile) {
free(js->forcedTerminationScriptFile);
js->forcedTerminationScriptFile = NULL;
}
/* Save message for later use */
if (msg) {
js_strdup(js->forcedTerminationMessage, msg);
}
js->forcedTerminationScriptFile = GetStackInfo(isolate, &js->forcedTerminationLineNumber);
}
V8::TerminateExecution(isolate);
}
char *JSMain::GetStackInfo(Isolate *isolate, int *lineNumber)
{
HandleScope handle_scope(isolate);
const char *file = __FILE__; /* Use current filename if we can't find the correct from JS stack */
int line = __LINE__; /* Use current line number if we can't find the correct from JS stack */
char *ret = NULL;
/* Try to get the current stack trace (script file) */
Local<StackTrace> stFile = StackTrace::CurrentStackTrace(isolate, 1, StackTrace::kScriptName);
if (!stFile.IsEmpty()) {
Local<StackFrame> sf = stFile->GetFrame(0);
if (!sf.IsEmpty()) {
Local<String> fn = sf->GetScriptName();
if (!fn.IsEmpty()) {
String::Utf8Value str(fn);
if (*str) {
js_strdup(ret, *str); // We must dup here
}
}
}
}
/* dup current filename if we got nothing from stack */
if (ret == NULL) {
js_strdup(ret, file);
}
/* Try to get the current stack trace (line number) */
if (lineNumber) {
*lineNumber = 0;
Local<StackTrace> stLine = StackTrace::CurrentStackTrace(isolate, 1, StackTrace::kLineNumber);
if (!stLine.IsEmpty()) {
Local<StackFrame> sf = stLine->GetFrame(0);
if (!sf.IsEmpty()) {
*lineNumber = sf->GetLineNumber();
}
}
/* Use current file number if we got nothing from stack */
if (*lineNumber == 0) {
*lineNumber = line;
}
}
/* Return dup'ed value - this must be freed by the calling function */
return ret;
}
/* 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:
*/

21
w32/v8.props Normal file
View File

@ -0,0 +1,21 @@
<?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="curl.props" Condition=" '$(CurlPropsImported)' == '' "/>
</ImportGroup>
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<AdditionalIncludeDirectories>$(SolutionDir)libs\v8-3.24.14\include;$(SolutionDir)src\mod\languages\mod_v8;$(SolutionDir)src\mod\languages\mod_v8\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(SolutionDir)libs\v8-3.24.14\build\$(Configuration)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>icui18n.lib;icuuc.lib;v8.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>