diff --git a/.github/workflows/Alma_build.yml b/.github/workflows/Alma_build.yml new file mode 100644 index 0000000..e61e9c2 --- /dev/null +++ b/.github/workflows/Alma_build.yml @@ -0,0 +1,98 @@ +name: alma build workflows + +on: + push: + branches: + - 'develop' + paths: + - 'XEngine_Source/**' + - 'XEngine_Release/**' + - '.github/**' + +permissions: + contents: read + +jobs: + build: + runs-on: ${{ matrix.runner }} + container: + image: almalinux:${{ matrix.version }} + options: --platform ${{ matrix.platform }} + strategy: + matrix: + include: + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + artifact: x86-64 + version: 9 + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + artifact: x86-64 + version: 10 + - arch: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64 + artifact: Arm64 + version: 9 + - arch: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64 + artifact: Arm64 + version: 10 + + steps: + - name: Checkout main repository code + uses: actions/checkout@v4 + + - name: Checkout dependency repository (xengine) + uses: actions/checkout@v4 + with: + repository: libxengine/libxengine + path: libxengine + + - name: sub module checkout (opensource) + uses: actions/checkout@v4 + with: + repository: libxengine/XEngine_OPenSource + path: XEngine_Source/XEngine_DependLibrary + + - name: Set TERM variable + run: echo "TERM=xterm" >> $GITHUB_ENV + + - name: install system package + run: | + dnf update -y + dnf install gcc g++ make git jq unzip wget -y + + - name: install xengine library + run: | + latest_tag=$(curl -s https://api.github.com/repos/libxengine/libxengine/releases/latest | jq -r .tag_name) + wget https://github.com/libxengine/libxengine/releases/download/$latest_tag/XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }}.zip + unzip ./XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }}.zip -d ./XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} + cd XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} + + chmod 777 * + ./XEngine_LINEnv.sh -i 3 + + - name: install depend library + run: dnf install libsrtp-devel srt-devel -y + + - name: make + run: | + cd XEngine_Source + make RELEASE=1 + make FLAGS=InstallAll + make FLAGS=CleanAll + cd .. + - name: test + run: | + cd XEngine_Release + ./XEngine_StreamMediaApp -t + + - name: Upload folder as artifact + uses: actions/upload-artifact@v4 + with: + name: XEngine_StreamMediaApp-AlmaLinux_${{ matrix.version }}_${{ matrix.artifact }} + path: XEngine_Release/ \ No newline at end of file diff --git a/.github/workflows/Centos_build.yml b/.github/workflows/Centos_build.yml new file mode 100644 index 0000000..eafc9f0 --- /dev/null +++ b/.github/workflows/Centos_build.yml @@ -0,0 +1,102 @@ +name: centos build workflows + +on: + push: + branches: + - 'develop' + paths: + - 'XEngine_Source/**' + - 'XEngine_Release/**' + - '.github/**' + +permissions: + contents: read + +jobs: + build: + runs-on: ${{ matrix.runner }} + container: + image: quay.io/centos/centos:${{ matrix.stream }} + options: --platform ${{ matrix.platform }} + strategy: + matrix: + include: + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + artifact: x86-64 + version: 9 + stream: stream9 + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + artifact: x86-64 + version: 10 + stream: stream10 + - arch: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64 + artifact: Arm64 + version: 9 + stream: stream9 + - arch: arm64 + runner: ubuntu-24.04-arm + platform: linux/arm64 + artifact: Arm64 + version: 10 + stream: stream10 + + steps: + - name: Checkout main repository code + uses: actions/checkout@v4 + + - name: Checkout dependency repository (xengine) + uses: actions/checkout@v4 + with: + repository: libxengine/libxengine + path: libxengine + + - name: sub module checkout (opensource) + uses: actions/checkout@v4 + with: + repository: libxengine/XEngine_OPenSource + path: XEngine_Source/XEngine_DependLibrary + + - name: Set TERM variable + run: echo "TERM=xterm" >> $GITHUB_ENV + + - name: install system package + run: | + dnf update -y + dnf install gcc g++ make git jq unzip wget -y + + - name: install xengine library + run: | + latest_tag=$(curl -s https://api.github.com/repos/libxengine/libxengine/releases/latest | jq -r .tag_name) + wget https://github.com/libxengine/libxengine/releases/download/$latest_tag/XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }}.zip + unzip ./XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }}.zip -d ./XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} + cd XEngine_RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} + + chmod 777 * + ./XEngine_LINEnv.sh -i 3 + + - name: install depend library + run: dnf install libsrtp-devel srt-devel -y + + - name: make + run: | + cd XEngine_Source + make RELEASE=1 + make FLAGS=InstallAll + make FLAGS=CleanAll + cd .. + - name: test + run: | + cd XEngine_Release + ./XEngine_StreamMediaApp -t + + - name: Upload folder as artifact + uses: actions/upload-artifact@v4 + with: + name: XEngine_StreamMediaApp-CentOS_${{ matrix.version }}_${{ matrix.artifact }} + path: XEngine_Release/ \ No newline at end of file diff --git a/.github/workflows/Rocky_build.yml b/.github/workflows/Rocky_build.yml index d3376a8..3372c08 100644 --- a/.github/workflows/Rocky_build.yml +++ b/.github/workflows/Rocky_build.yml @@ -65,9 +65,6 @@ jobs: - name: install system package run: | - dnf clean all - dnf makecache - dnf distro-sync -y dnf update -y dnf install gcc g++ make git jq unzip wget -y - name: install xengine library @@ -79,6 +76,7 @@ jobs: chmod 777 * ./XEngine_LINEnv.sh -i 3 + - name: install depend library run: dnf install libsrtp-devel srt-devel -y diff --git a/.github/workflows/debian_build.yml b/.github/workflows/debian_build.yml index 94031c2..642d279 100644 --- a/.github/workflows/debian_build.yml +++ b/.github/workflows/debian_build.yml @@ -16,7 +16,7 @@ jobs: build: runs-on: ${{ matrix.runner }} container: - image: debian:bookworm + image: debian:${{ matrix.name }} options: --platform ${{ matrix.platform }} strategy: matrix: @@ -25,6 +25,14 @@ jobs: runner: ubuntu-24.04 platform: linux/amd64 artifact: x86-64 + name: bookworm + version: 12 + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + artifact: x86-64 + name: trixie + version: 13 steps: - name: Checkout main repository code @@ -50,18 +58,22 @@ jobs: - name: install system package run: | apt update -y + apt upgrade -y apt install gcc g++ make git jq unzip curl wget -y - apt install libsrt-gnutls-dev libsrtp2-dev -y - name: install xengine library run: | latest_tag=$(curl -s https://api.github.com/repos/libxengine/libxengine/releases/latest | jq -r .tag_name) - wget https://github.com/libxengine/libxengine/releases/download/$latest_tag/XEngine_Debian_12_${{ matrix.artifact }}.zip - unzip ./XEngine_Debian_12_${{ matrix.artifact }}.zip -d ./XEngine_Debian_12_${{ matrix.artifact }} - cd XEngine_Debian_12_${{ matrix.artifact }} + wget https://github.com/libxengine/libxengine/releases/download/$latest_tag/XEngine_Debian_${{ matrix.version }}_${{ matrix.artifact }}.zip + unzip ./XEngine_Debian_${{ matrix.version }}_${{ matrix.artifact }}.zip -d ./XEngine_Debian_${{ matrix.version }}_${{ matrix.artifact }} + cd XEngine_Debian_${{ matrix.version }}_${{ matrix.artifact }} chmod 777 * ./XEngine_LINEnv.sh -i 3 + + - name: install system package + run: apt install libsrt-gnutls-dev libsrtp2-dev -y + - name: make run: | cd XEngine_Source @@ -81,6 +93,6 @@ jobs: - name: Upload folder as artifact uses: actions/upload-artifact@v4 with: - name: XEngine_StreamMediaApp-Debian_12_x86-64 + name: XEngine_StreamMediaApp-Debian_${{ matrix.version }}_x86-64 path: XEngine_Release/ retention-days: 1 \ No newline at end of file diff --git a/.github/workflows/macbuild.yml b/.github/workflows/macbuild.yml index f1296eb..ca59b4a 100644 --- a/.github/workflows/macbuild.yml +++ b/.github/workflows/macbuild.yml @@ -17,8 +17,8 @@ jobs: strategy: matrix: include: - - os: macos-13 - - os: macos-14 + - os: macos-15 + - os: macos-15-intel runs-on: ${{ matrix.os }} steps: @@ -48,13 +48,13 @@ jobs: run: echo "TERM=xterm" >> $GITHUB_ENV - name: Set up Dependency x86_64 Environment - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' run: | cd libxengine chmod 777 * ./XEngine_LINEnv.sh -i 3 - name: Set up Dependency Arm64 Environment - if: matrix.os == 'macos-14' + if: matrix.os == 'macos-15' run: | latest_tag=$(git ls-remote --tags --sort="v:refname" https://github.com/libxengine/libxengine.git | awk '{print $2}' | sed 's/refs\/tags\///' | tail -n 1) wget https://github.com/libxengine/libxengine/releases/download/$latest_tag/XEngine_Mac_Arm64.zip @@ -83,14 +83,14 @@ jobs: #./XEngine_StreamMediaApp -t - name: Upload folder as artifact with mac x64 - if: matrix.os == 'macos-13' + if: matrix.os == 'macos-15-intel' uses: actions/upload-artifact@v4 with: name: XEngine_StreamMediaApp-Mac_x86_64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with mac arm - if: matrix.os == 'macos-14' + if: matrix.os == 'macos-15' uses: actions/upload-artifact@v4 with: name: XEngine_StreamMediaApp-Mac_Arm64 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a544436..3036c31 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -51,6 +51,24 @@ jobs: skip_unpack: true if_no_artifact_found: fail path: ./XRelease/ + - name: Download Alma build + uses: dawidd6/action-download-artifact@v6 + with: + workflow: Alma_build.yml + workflow_conclusion: success + check_artifacts: false + skip_unpack: true + if_no_artifact_found: fail + path: ./XRelease/ + - name: Download CentOS build + uses: dawidd6/action-download-artifact@v6 + with: + workflow: Centos_build.yml + workflow_conclusion: success + check_artifacts: false + skip_unpack: true + if_no_artifact_found: fail + path: ./XRelease/ - name: Download macbuild uses: dawidd6/action-download-artifact@v6 with: @@ -85,7 +103,7 @@ jobs: build=$(echo $latest_tag | cut -d '.' -f 4) new_minor=$((minor + 1)) - new_version="$major.$new_minor.0.$build" + new_version="$major.$new_minor.$patch.$build" echo "New version: $new_version" echo "new_tag=$new_version" >> $GITHUB_OUTPUT echo "prev_tag=$latest_tag" >> $GITHUB_OUTPUT diff --git a/CHANGELOG b/CHANGELOG index 2f0160b..80a2d96 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,19 @@ +XEngine_StreamMedia V2.13.0.1001 + +ci:增加了centos alma系统支持 +增加:http验证功能支持 +更新:依赖库 +修改:启动参数不区分大小写 +修改:统一Http错误码 +修正:某些时候配置读取问题 + +ci:add alma and centos and debian 13 system support +added:http basic and digest verification +update:depend library +modify:start parameter does not case sensitive +modify:Unify HTTP error code definitions +fixed:sometime configure read memory leak +======================================================= XEngine_StreamMedia V2.12.0.1001 added:webrtc push stream test code diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx index cf015ee..a314982 100644 Binary files a/XEngine_Docment/Docment_en.docx and b/XEngine_Docment/Docment_en.docx differ diff --git a/XEngine_Docment/Docment_zh.docx b/XEngine_Docment/Docment_zh.docx index 73a94f1..fa1e0ca 100644 Binary files a/XEngine_Docment/Docment_zh.docx and b/XEngine_Docment/Docment_zh.docx differ diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json index 6e14b45..cb2f5b1 100644 --- a/XEngine_Release/XEngine_Config/XEngine_Config.json +++ b/XEngine_Release/XEngine_Config/XEngine_Config.json @@ -80,6 +80,13 @@ "LogLeave": 17, "LogType": 32 }, + "XVerification": { + "bEnable": false, + "tszUser": "xengine", + "tszPass": "123123aa", + "tszAPIUrl": "", + "nVerType": 2 + }, "XReport":{ "bEnable":true, "tszServiceName":"XEngine_StreamMedia", diff --git a/XEngine_Release/XEngine_Config/XEngine_Version.json b/XEngine_Release/XEngine_Config/XEngine_Version.json index f7739c4..d8dec01 100644 --- a/XEngine_Release/XEngine_Config/XEngine_Version.json +++ b/XEngine_Release/XEngine_Config/XEngine_Version.json @@ -1,5 +1,6 @@ { "XVer": [ + "V2.13.0.1001 Build20251107", "V2.12.0.1001 Build20250815", "V2.11.1.1001 Build20250409", "V2.11.0.1001 Build20250426", diff --git a/XEngine_Source/Makefile b/XEngine_Source/Makefile index 1ba3576..0a87d20 100644 --- a/XEngine_Source/Makefile +++ b/XEngine_Source/Makefile @@ -5,6 +5,7 @@ FLAGS= #要编译的模块 THIRDPART_MODULE_JSONCPP = ./XEngine_DependLibrary/XEngine_Module/jsoncpp THIRDPART_MODULE_REPORT = ./XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport +THIRDPART_MODULE_VERIFICATION = ./XEngine_DependLibrary/XEngine_Module/XEngine_Verification MODULE_CONFIGURE_PATH = ./XEngine_ModuleConfigure MODULE_HELP_PATH = ./XEngine_ModuleHelp @@ -20,7 +21,7 @@ else ifeq ($(PLATFORM),mac) FILEEXT = dylib endif -XENGINE_MODULES = libjsoncpp.so libXEngine_InfoReport.so \ +XENGINE_MODULES = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so \ libXEngine_ModuleConfigure.so libXEngine_ModuleHelp.so libXEngine_ModuleProtocol.so libXEngine_ModuleSession.so libXEngine_ModuleQueue.so \ XEngine_StreamMediaApp.exe @@ -40,6 +41,12 @@ ifeq ($(FLAGS), InstallAll) else make -C $(THIRDPART_MODULE_REPORT) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) RELEASE=$(RELEASE) $(FLAGS) endif +libXEngine_Verification.so: +ifeq ($(FLAGS), InstallAll) + cp $(THIRDPART_MODULE_VERIFICATION)/libXEngine_Verification.$(FILEEXT) ../XEngine_Release/ +else + make -C $(THIRDPART_MODULE_VERIFICATION) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) RELEASE=$(RELEASE) $(FLAGS) +endif libXEngine_ModuleConfigure.so: make -C $(MODULE_CONFIGURE_PATH) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) RELEASE=$(RELEASE) $(FLAGS) diff --git a/XEngine_Source/VSCopy_Arm64.bat b/XEngine_Source/VSCopy_Arm64.bat index 9128790..059454a 100644 --- a/XEngine_Source/VSCopy_Arm64.bat +++ b/XEngine_Source/VSCopy_Arm64.bat @@ -5,7 +5,7 @@ copy /y "%XEngine_LibArm64%\XEngine_Core\XEngine_Core.dll" "./" copy /y "%XEngine_LibArm64%\XEngine_Core\XEngine_ManagePool.dll" "./" copy /y "%XEngine_LibArm64%\XEngine_Core\XEngine_Cryption.dll" "./" -copy /y "%XEngine_LibArm64%\XEngine_Client\XClient_Stream.dll" "./" +copy /y "%XEngine_LibArm64%\XEngine_Client\XClient_Socket.dll" "./" copy /y "%XEngine_LibArm64%\XEngine_Client\XClient_APIHelp.dll" "./" copy /y "%XEngine_LibArm64%\XEngine_NetHelp\NetHelp_XSocket.dll" "./" diff --git a/XEngine_Source/VSCopy_Debug.bat b/XEngine_Source/VSCopy_Debug.bat index 0380452..43bf4e2 100644 --- a/XEngine_Source/VSCopy_Debug.bat +++ b/XEngine_Source/VSCopy_Debug.bat @@ -5,7 +5,7 @@ copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_Core.dll" "./" copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_ManagePool.dll" "./" copy /y "D:\XEngine\XEngine_SourceCode\Debug\XEngine_Cryption.dll" "./" -copy /y "D:\XEngine\XEngine_SourceCode\Debug\XClient_Stream.dll" "./" +copy /y "D:\XEngine\XEngine_SourceCode\Debug\XClient_Socket.dll" "./" copy /y "D:\XEngine\XEngine_SourceCode\Debug\XClient_APIHelp.dll" "./" copy /y "D:\XEngine\XEngine_SourceCode\Debug\NetHelp_XSocket.dll" "./" diff --git a/XEngine_Source/VSCopy_x64.bat b/XEngine_Source/VSCopy_x64.bat index c4c4739..a0a38a0 100644 --- a/XEngine_Source/VSCopy_x64.bat +++ b/XEngine_Source/VSCopy_x64.bat @@ -5,7 +5,7 @@ copy /y "%XEngine_Lib64%\XEngine_Core\XEngine_Core.dll" "./" copy /y "%XEngine_Lib64%\XEngine_Core\XEngine_ManagePool.dll" "./" copy /y "%XEngine_Lib64%\XEngine_Core\XEngine_Cryption.dll" "./" -copy /y "%XEngine_Lib64%\XEngine_Client\XClient_Stream.dll" "./" +copy /y "%XEngine_Lib64%\XEngine_Client\XClient_Socket.dll" "./" copy /y "%XEngine_Lib64%\XEngine_Client\XClient_APIHelp.dll" "./" copy /y "%XEngine_Lib64%\XEngine_NetHelp\NetHelp_XSocket.dll" "./" diff --git a/XEngine_Source/VSCopy_x86.bat b/XEngine_Source/VSCopy_x86.bat index fce463a..9b45f37 100644 --- a/XEngine_Source/VSCopy_x86.bat +++ b/XEngine_Source/VSCopy_x86.bat @@ -5,7 +5,7 @@ copy /y "%XEngine_Lib32%\XEngine_Core\XEngine_Core.dll" "./" copy /y "%XEngine_Lib32%\XEngine_Core\XEngine_ManagePool.dll" "./" copy /y "%XEngine_Lib32%\XEngine_Core\XEngine_Cryption.dll" "./" -copy /y "%XEngine_Lib32%\XEngine_Client\XClient_Stream.dll" "./" +copy /y "%XEngine_Lib32%\XEngine_Client\XClient_Socket.dll" "./" copy /y "%XEngine_Lib32%\XEngine_Client\XClient_APIHelp.dll" "./" copy /y "%XEngine_Lib32%\XEngine_NetHelp\NetHelp_XSocket.dll" "./" diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln index bc16292..238ce4e 100644 --- a/XEngine_Source/XEngine.sln +++ b/XEngine_Source/XEngine.sln @@ -31,6 +31,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_StreamMediaApp", "X {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D} = {6D0FCB40-D544-4AB2-A239-2FEBC4B98F6D} {98DB01B5-30B7-4C00-9A84-39886680F069} = {98DB01B5-30B7-4C00-9A84-39886680F069} {9FF6FA78-456E-4A7E-86B1-17E4DB5403C9} = {9FF6FA78-456E-4A7E-86B1-17E4DB5403C9} + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} {F54F152C-594F-4465-A44E-2DB915B39760} = {F54F152C-594F-4465-A44E-2DB915B39760} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} @@ -47,6 +48,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_InfoReport", "XEngi {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Verification", "XEngine_DependLibrary\XEngine_Module\XEngine_Verification\XEngine_Verification.vcxproj", "{A8E43EC0-698A-4807-8A61-B2BE5FAB7256}" + ProjectSection(ProjectDependencies) = postProject + {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -153,6 +159,18 @@ Global {F6520D2C-BB8E-45BB-964B-F5D6A4318A89}.Release|x64.Build.0 = Release|x64 {F6520D2C-BB8E-45BB-964B-F5D6A4318A89}.Release|x86.ActiveCfg = Release|Win32 {F6520D2C-BB8E-45BB-964B-F5D6A4318A89}.Release|x86.Build.0 = Release|Win32 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|ARM64.Build.0 = Debug|ARM64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|x64.ActiveCfg = Debug|x64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|x64.Build.0 = Debug|x64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|x86.ActiveCfg = Debug|Win32 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Debug|x86.Build.0 = Debug|Win32 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|ARM64.ActiveCfg = Release|ARM64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|ARM64.Build.0 = Release|ARM64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x64.ActiveCfg = Release|x64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x64.Build.0 = Release|x64 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.ActiveCfg = Release|Win32 + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -161,6 +179,7 @@ Global {2E55D676-E9F5-48B8-B65E-FE0E7C3D2AEB} = {79A9A569-7DA8-4D9D-AD34-D11115199EA1} {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {6A753FB6-282E-4E86-91BB-BE97618B65A4} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {6A753FB6-282E-4E86-91BB-BE97618B65A4} + {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {6A753FB6-282E-4E86-91BB-BE97618B65A4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9B202F91-A601-429E-BB0F-880DDEE096FE} diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary index 269830b..dc2e4b3 160000 --- a/XEngine_Source/XEngine_DependLibrary +++ b/XEngine_Source/XEngine_DependLibrary @@ -1 +1 @@ -Subproject commit 269830be96d7e95646ce43533294156063178509 +Subproject commit dc2e4b3af5b666e888166ef1e7567475f6f03904 diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h index c9b137d..c75a860 100644 --- a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Define.h @@ -111,6 +111,14 @@ typedef struct tag_XEngine_ServiceConfig }st_PullWebRtc; }st_XPull; struct + { + XCHAR tszAPIUrl[XPATH_MID]; //验证API地址 + XCHAR tszUserName[128]; //验证用户名 + XCHAR tszUserPass[128]; //验证密码 + int nVType; //验证方法,1 基本,2摘要 + bool bEnable; //是否启用HTTP接口权限验证 + }st_XVerification; + struct { XCHAR tszAPIUrl[XPATH_MAX]; XCHAR tszServiceName[128]; diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h index 1c37a99..64acc67 100644 --- a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfig_Error.h @@ -19,4 +19,5 @@ #define ERROR_MODULE_CONFIGURE_JSON_XVER 0xA0007 //读取版本列表失败 #define ERROR_MODULE_CONFIGURE_JSON_MALLOC 0xA0008 //申请内存失败 #define ERROR_MODULE_CONFIGURE_JSON_XPULL 0xA0009 //拉流配置不存在 -#define ERROR_MODULE_CONFIGURE_JSON_REPORT 0xA000A //报告配置不存在 \ No newline at end of file +#define ERROR_MODULE_CONFIGURE_JSON_REPORT 0xA000A //报告配置不存在 +#define ERROR_MODULE_CONFIGURE_JSON_VERIFICATION 0xA000B //验证配置不存在 \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp index ec4e1b2..51bc466 100644 --- a/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp +++ b/XEngine_Source/XEngine_ModuleConfigure/ModuleConfigure_Json/ModuleConfigure_Json.cpp @@ -177,6 +177,19 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_File(LPCXSTR lpszConfigFile, XE pSt_ServerConfig->st_XLog.nLogLeave = st_JsonXLog["LogLeave"].asInt(); pSt_ServerConfig->st_XLog.nLogType = st_JsonXLog["LogType"].asInt(); _tcsxcpy(pSt_ServerConfig->st_XLog.tszLogFile, st_JsonXLog["LogFile"].asCString()); + //接口验证 + if (st_JsonRoot["XVerification"].empty() || (5 != st_JsonRoot["XVerification"].size())) + { + Config_IsErrorOccur = true; + Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_VERIFICATION; + return false; + } + Json::Value st_JsonXVerification = st_JsonRoot["XVerification"]; + pSt_ServerConfig->st_XVerification.bEnable = st_JsonXVerification["bEnable"].asBool(); + pSt_ServerConfig->st_XVerification.nVType = st_JsonXVerification["nVerType"].asInt(); + _tcsxcpy(pSt_ServerConfig->st_XVerification.tszUserName, st_JsonXVerification["tszUser"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XVerification.tszUserPass, st_JsonXVerification["tszPass"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XVerification.tszAPIUrl, st_JsonXVerification["tszAPIUrl"].asCString()); //信息报告 if (st_JsonRoot["XReport"].empty() || (3 != st_JsonRoot["XReport"].size())) { @@ -229,21 +242,12 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_Versions(LPCXSTR lpszConfigFile Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_OPENFILE; return false; } - size_t nCount = 0; - XCHAR tszMsgBuffer[4096]; - while (1) - { - size_t nRet = fread(tszMsgBuffer + nCount, 1, 2048, pSt_File); - if (nRet <= 0) - { - break; - } - nCount += nRet; - } + XCHAR tszMsgBuffer[8192] = {}; + size_t nRet = fread(tszMsgBuffer, 1, sizeof(tszMsgBuffer), pSt_File); fclose(pSt_File); //开始解析配置文件 std::unique_ptr const pSt_JsonReader(st_JsonBuilder.newCharReader()); - if (!pSt_JsonReader->parse(tszMsgBuffer, tszMsgBuffer + nCount, &st_JsonRoot, &st_JsonError)) + if (!pSt_JsonReader->parse(tszMsgBuffer, tszMsgBuffer + nRet, &st_JsonRoot, &st_JsonError)) { Config_IsErrorOccur = true; Config_dwErrorCode = ERROR_MODULE_CONFIGURE_JSON_PARSE; diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h index f85e27c..06c1e21 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Define.h @@ -217,4 +217,28 @@ extern "C" bool ModuleProtocol_Packet_HTTPPullGet(XCHAR* ptszMsgBuffer, int* pIn 意思:是否成功 备注: *********************************************************************/ -extern "C" bool ModuleProtocol_Parse_HTTPForward(LPCXSTR lpszMsgBuffer, int nMsgLen, XCHAR * ptszAVUrl = NULL); \ No newline at end of file +extern "C" bool ModuleProtocol_Parse_HTTPForward(LPCXSTR lpszMsgBuffer, int nMsgLen, XCHAR * ptszAVUrl = NULL); +/******************************************************************** +函数名称:ModuleProtocol_Parse_HTTPParseAuth +函数功能:用户验证解析协议 + 参数.一:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要解析的缓冲区 + 参数.二:nMsgLen + In/Out:In + 类型:整数型 + 可空:N + 意思:输入要解析的大小 + 参数.三:pSt_UserAuth + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出解析的数据 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" bool ModuleProtocol_Parse_HTTPParseAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, XENGINE_PROTOCOL_USERAUTHEX* pSt_UserAuth); \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp index e3c3c0d..fd5807a 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.cpp @@ -70,4 +70,76 @@ bool CModuleProtocol_Parse::ModuleProtocol_Parse_HTTPForward(LPCXSTR lpszMsgBuff _tcsxcpy(ptszAVUrl, st_JsonRoot["tszAVUrl"].asCString()); } return true; +} +/******************************************************************** +函数名称:ModuleProtocol_Parse_HTTPParseAuth +函数功能:用户验证解析协议 + 参数.一:lpszMsgBuffer + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:输入要解析的缓冲区 + 参数.二:nMsgLen + In/Out:In + 类型:整数型 + 可空:N + 意思:输入要解析的大小 + 参数.三:pSt_UserAuth + In/Out:Out + 类型:数据结构指针 + 可空:N + 意思:输出解析的数据 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +bool CModuleProtocol_Parse::ModuleProtocol_Parse_HTTPParseAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, XENGINE_PROTOCOL_USERAUTHEX* pSt_UserAuth) +{ + ModuleProtocol_IsErrorOccur = false; + + if ((NULL == lpszMsgBuffer) || (NULL == pSt_UserAuth)) + { + ModuleProtocol_IsErrorOccur = true; + ModuleProtocol_dwErrorCode = ERROR_MODULE_PROTOCOL_PARSE_PARAMENT; + return false; + } + Json::Value st_JsonRoot; + JSONCPP_STRING st_JsonError; + Json::CharReaderBuilder st_ReaderBuilder; + + std::unique_ptr const pSt_JsonReader(st_ReaderBuilder.newCharReader()); + if (!pSt_JsonReader->parse(lpszMsgBuffer, lpszMsgBuffer + nMsgLen, &st_JsonRoot, &st_JsonError)) + { + ModuleProtocol_IsErrorOccur = true; + ModuleProtocol_dwErrorCode = ERROR_MODULE_PROTOCOL_PARSE_JSON; + return false; + } + Json::Value st_JsonProtocol = st_JsonRoot["st_UserAuth"]; + + if (!st_JsonProtocol["tszUserName"].isNull()) + { + _tcsxcpy(pSt_UserAuth->tszUserName, st_JsonProtocol["tszUserName"].asCString()); + } + if (!st_JsonProtocol["tszUserPass"].isNull()) + { + _tcsxcpy(pSt_UserAuth->tszUserPass, st_JsonProtocol["tszUserPass"].asCString()); + } + if (!st_JsonProtocol["enClientType"].isNull()) + { + pSt_UserAuth->enClientType = (ENUM_PROTOCOLCLIENT_TYPE)st_JsonProtocol["enClientType"].asInt(); + } + if (!st_JsonProtocol["enDeviceType"].isNull()) + { + pSt_UserAuth->enDeviceType = (ENUM_PROTOCOLDEVICE_TYPE)st_JsonProtocol["enDeviceType"].asInt(); + } + if (!st_JsonProtocol["tszDCode"].isNull()) + { + _tcsxcpy(pSt_UserAuth->tszDCode, st_JsonProtocol["tszDCode"].asCString()); + } + if (!st_JsonProtocol["tszHWCode"].isNull()) + { + _tcsxcpy(pSt_UserAuth->tszHWCode, st_JsonProtocol["tszHWCode"].asCString()); + } + return true; } \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h index f7db4ba..ca79c9e 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h +++ b/XEngine_Source/XEngine_ModuleProtocol/ModuleProtocol_Parse/ModuleProtocol_Parse.h @@ -18,5 +18,6 @@ class CModuleProtocol_Parse ~CModuleProtocol_Parse(); public: bool ModuleProtocol_Parse_HTTPForward(LPCXSTR lpszMsgBuffer, int nMsgLen, XCHAR* ptszAVUrl); + bool ModuleProtocol_Parse_HTTPParseAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, XENGINE_PROTOCOL_USERAUTHEX* pSt_UserAuth); private: }; \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def index 7c828ac..70a4406 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.def @@ -10,4 +10,5 @@ EXPORTS ModuleProtocol_Packet_HTTPPublishGet ModuleProtocol_Packet_HTTPPullGet - ModuleProtocol_Parse_HTTPForward \ No newline at end of file + ModuleProtocol_Parse_HTTPForward + ModuleProtocol_Parse_HTTPParseAuth \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj index 1d93f42..f1d8e2f 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj +++ b/XEngine_Source/XEngine_ModuleProtocol/XEngine_ModuleProtocol.vcxproj @@ -99,7 +99,7 @@ true - $(XEngine_Include);../XEngine_DependLibrary/XEngine_Module/jsoncpp;$(IncludePath) + $(XEngine_Include);../XEngine_DependLibrary/XEngine_Module/jsoncpp;..\XEngine_ModuleProtocol;$(IncludePath) $(XEngine_Lib32);$(LibraryPath) diff --git a/XEngine_Source/XEngine_ModuleProtocol/pch.cpp b/XEngine_Source/XEngine_ModuleProtocol/pch.cpp index a5fe6ce..9e9bae9 100644 --- a/XEngine_Source/XEngine_ModuleProtocol/pch.cpp +++ b/XEngine_Source/XEngine_ModuleProtocol/pch.cpp @@ -61,4 +61,8 @@ extern "C" bool ModuleProtocol_Packet_HTTPPullGet(XCHAR * ptszMsgBuffer, int* pI extern "C" bool ModuleProtocol_Parse_HTTPForward(LPCXSTR lpszMsgBuffer, int nMsgLen, XCHAR * ptszAVUrl) { return m_ProtocolParse.ModuleProtocol_Parse_HTTPForward(lpszMsgBuffer, nMsgLen, ptszAVUrl); +} +extern "C" bool ModuleProtocol_Parse_HTTPParseAuth(LPCXSTR lpszMsgBuffer, int nMsgLen, XENGINE_PROTOCOL_USERAUTHEX* pSt_UserAuth) +{ + return m_ProtocolParse.ModuleProtocol_Parse_HTTPParseAuth(lpszMsgBuffer, nMsgLen, pSt_UserAuth); } \ No newline at end of file diff --git a/XEngine_Source/XEngine_ModuleSession/ModuleSession_Define.h b/XEngine_Source/XEngine_ModuleSession/ModuleSession_Define.h index 0d7e3f5..42689b2 100644 --- a/XEngine_Source/XEngine_ModuleSession/ModuleSession_Define.h +++ b/XEngine_Source/XEngine_ModuleSession/ModuleSession_Define.h @@ -818,7 +818,7 @@ extern "C" bool ModuleSession_PushStream_HLSTimeGet(LPCXSTR lpszClientAddr, __in 意思:是否成功 备注: *********************************************************************/ -extern "C" bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XNETHANDLE xhAudioDecodec, XNETHANDLE xhAudioEncodec); +extern "C" bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XHANDLE xhAudioDecodec, XHANDLE xhAudioEncodec); /******************************************************************** 函数名称:ModuleSession_PushStream_AudioCodecGet 函数功能:获取解码器句柄 @@ -842,7 +842,7 @@ extern "C" bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, X 意思:是否成功 备注: *********************************************************************/ -extern "C" bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XNETHANDLE* pxhAudioDecodec, XNETHANDLE* pxhAudioEncodec); +extern "C" bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XHANDLE* pxhAudioDecodec, XHANDLE* pxhAudioEncodec); /******************************************************************** 函数名称:ModuleSession_PushStream_RTCConnSet 函数功能:设置RTC连接状态 diff --git a/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.cpp b/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.cpp index bd3f6e5..4444446 100644 --- a/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.cpp +++ b/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.cpp @@ -817,7 +817,7 @@ bool CModuleSession_PushStream::ModuleSession_PushStream_HLSTimeGet(LPCXSTR lpsz 意思:是否成功 备注: *********************************************************************/ -bool CModuleSession_PushStream::ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XNETHANDLE xhAudioDecodec, XNETHANDLE xhAudioEncodec) +bool CModuleSession_PushStream::ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XHANDLE xhAudioDecodec, XHANDLE xhAudioEncodec) { Session_IsErrorOccur = false; @@ -866,7 +866,7 @@ bool CModuleSession_PushStream::ModuleSession_PushStream_AudioCodecSet(LPCXSTR l 意思:是否成功 备注: *********************************************************************/ -bool CModuleSession_PushStream::ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XNETHANDLE* pxhAudioDecodec, XNETHANDLE* pxhAudioEncodec) +bool CModuleSession_PushStream::ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XHANDLE* pxhAudioDecodec, XHANDLE* pxhAudioEncodec) { Session_IsErrorOccur = false; diff --git a/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.h b/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.h index f312ba0..46e8013 100644 --- a/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.h +++ b/XEngine_Source/XEngine_ModuleSession/ModuleSession_PushStream/ModuleSession_PushStream.h @@ -29,8 +29,8 @@ typedef struct }st_RTCInfo; struct { - XNETHANDLE xhAudioDecodec; - XNETHANDLE xhAudioEncodec; + XHANDLE xhAudioDecodec; + XHANDLE xhAudioEncodec; }st_AVCodec; XENGINE_PROTOCOL_AVINFO st_AVInfo; XCHAR tszSMSAddr[XPATH_MAX]; @@ -65,8 +65,8 @@ class CModuleSession_PushStream bool ModuleSession_PushStream_HLSTimeSet(LPCXSTR lpszClientAddr, __int64u nTime); bool ModuleSession_PushStream_HLSTimeGet(LPCXSTR lpszClientAddr, __int64u *pInt_Time); public: - bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XNETHANDLE xhAudioDecodec, XNETHANDLE xhAudioEncodec); - bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XNETHANDLE* pxhAudioDecodec, XNETHANDLE* pxhAudioEncodec); + bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XHANDLE xhAudioDecodec, XHANDLE xhAudioEncodec); + bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XHANDLE* pxhAudioDecodec, XHANDLE* pxhAudioEncodec); public: bool ModuleSession_PushStream_RTCAddrSet(LPCXSTR lpszClientUser, LPCXSTR lpszClientAddr); bool ModuleSession_PushStream_RTCAddrGet(LPCXSTR lpszClientAddr, XCHAR* ptszClientUser); diff --git a/XEngine_Source/XEngine_ModuleSession/pch.cpp b/XEngine_Source/XEngine_ModuleSession/pch.cpp index a01f330..50e6f0e 100644 --- a/XEngine_Source/XEngine_ModuleSession/pch.cpp +++ b/XEngine_Source/XEngine_ModuleSession/pch.cpp @@ -176,11 +176,11 @@ extern "C" bool ModuleSession_PushStream_HLSTimeGet(LPCXSTR lpszClientAddr, __in { return m_PushStream.ModuleSession_PushStream_HLSTimeGet(lpszClientAddr, pInt_Time); } -extern "C" bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XNETHANDLE xhAudioDecodec, XNETHANDLE xhAudioEncodec) +extern "C" bool ModuleSession_PushStream_AudioCodecSet(LPCXSTR lpszClientAddr, XHANDLE xhAudioDecodec, XHANDLE xhAudioEncodec) { return m_PushStream.ModuleSession_PushStream_AudioCodecSet(lpszClientAddr, xhAudioDecodec, xhAudioEncodec); } -extern "C" bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XNETHANDLE* pxhAudioDecodec, XNETHANDLE* pxhAudioEncodec) +extern "C" bool ModuleSession_PushStream_AudioCodecGet(LPCXSTR lpszClientAddr, XHANDLE* pxhAudioDecodec, XHANDLE* pxhAudioEncodec) { return m_PushStream.ModuleSession_PushStream_AudioCodecGet(lpszClientAddr, pxhAudioDecodec, pxhAudioEncodec); } diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/Makefile b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/Makefile index d978688..6f4dbde 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/Makefile +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/Makefile @@ -2,10 +2,10 @@ CC = g++ -Wall -std=c++20 PLATVER = LOADHDR = -I ./ LOADSO = -L ../../XEngine_ModuleConfigure -L ../../XEngine_ModuleProtocol -L ../../XEngine_ModuleSession -L ../../XEngine_ModuleHelp -L ../../XEngine_ModuleQueue \ - -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport + -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification LIB = -lXEngine_BaseLib -lXEngine_Algorithm \ -lXEngine_Core -lXEngine_ManagePool -lXEngine_Cryption \ - -lXClient_Stream \ + -lXClient_APIHelp \ -lXEngine_SystemApi \ -lHelpComponents_XLog -lHelpComponents_Packets \ -lNetHelp_APIHelp -lNetHelp_XSocket -lNetHelp_APIAddr \ @@ -13,7 +13,7 @@ LIB = -lXEngine_BaseLib -lXEngine_Algorithm \ -lXEngine_AVHelp -lXEngine_AudioCodec \ -lStreamMedia_FLVProtocol -lStreamMedia_RTMPProtocol -lStreamMedia_SDPProtocol -lStreamMedia_HLSProtocol -lStreamMedia_RTSPProtocol -lStreamMedia_RTPProtocol -lStreamMedia_RTCPProtocol \ -lXEngine_ModuleConfigure -lXEngine_ModuleProtocol -lXEngine_ModuleSession -lXEngine_ModuleHelp -lXEngine_ModuleQueue \ - -ljsoncpp -lXEngine_InfoReport + -ljsoncpp -lXEngine_InfoReport -lXEngine_Verification LIBEX = OBJECTS = PullStream_ClientGet.o PullStream_ClientRtsp.o PullStream_ClientWebRtc.o \ PushStream_JT1078Task.o PushStream_RTMPTask.o PushStream_XStreamTask.o PushStream_SrtTask.o PushStream_ClientWebRtc.o \ diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PullStream/PullStream_ClientGet.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PullStream/PullStream_ClientGet.cpp index f202a5f..a8868cc 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PullStream/PullStream_ClientGet.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PullStream/PullStream_ClientGet.cpp @@ -126,7 +126,7 @@ bool PullStream_ClientGet_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, { if (!st_ServiceConfig.st_XPull.st_PullFlv.bPrePull) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 404, "not found"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_NOTFOUND, "not found"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("拉流端:%s,请求拉流的URL参数不正确:%s,可能流不存在,错误:%lX"), lpszClientAddr, tszVluBuffer, ModuleSession_GetLastError()); @@ -163,7 +163,7 @@ bool PullStream_ClientGet_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, { if (!ModuleSession_PushStream_FindStream(tszSMSAddr, tszPushAddr)) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 404, "not found"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_NOTFOUND, "not found"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("拉流端:%s,请求拉流的URL参数不正确:%s,可能流不存在,错误:%lX"), lpszClientAddr, tszVluBuffer, ModuleSession_GetLastError()); @@ -202,7 +202,7 @@ bool PullStream_ClientGet_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, { if (!st_ServiceConfig.st_XPull.st_PullTs.bPrePull) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 404, "not found"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_NOTFOUND, "not found"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("拉流端:%s,请求拉流的URL参数不正确:%s,可能流不存在,错误:%lX"), lpszClientAddr, tszVluBuffer, ModuleSession_GetLastError()); @@ -230,7 +230,7 @@ bool PullStream_ClientGet_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, } else { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 500, "not support"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_NOTSUPPORT, "not support"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("拉流端:%s,请求拉流的数据类型不支持:%s,错误:%lX"), lpszClientAddr, tszVluBuffer, ModuleSession_GetLastError()); @@ -249,7 +249,7 @@ bool PullStream_ClientGet_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, if (!ModuleSession_PullStream_GetPushAddr(lpszClientAddr, tszPushAddr)) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 404, "not found"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_NOTFOUND, "not found"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("拉流端:%s,请求停止拉流失败,获取绑定推流地址失败,错误:%lX"), lpszClientAddr, ModuleSession_GetLastError()); diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PushStream/PushStream_ClientWebRtc.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PushStream/PushStream_ClientWebRtc.cpp index 8c4d629..7042c0b 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PushStream/PushStream_ClientWebRtc.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/StreamMedia_PushStream/PushStream_ClientWebRtc.cpp @@ -182,6 +182,11 @@ bool PushStream_ClientProtocol_Thread() { int nVideoIndex = 0; int nAudioIndex = 0; + int nRVLen = 0; + int nSDLen = 0; + XCHAR* ptszRVBuffer = (XCHAR*)ManagePool_Memory_Alloc(xhMemoryPool, XENGINE_MEMORY_SIZE_MAX); + XCHAR* ptszSDBuffer = (XCHAR*)ManagePool_Memory_Alloc(xhMemoryPool, XENGINE_MEMORY_SIZE_MAX); + ModuleSession_PushStream_RTCIndexGet(ppSt_ListAddr[i]->tszClientAddr, &nVideoIndex, &nAudioIndex); while (true) { @@ -193,6 +198,28 @@ bool PushStream_ClientProtocol_Thread() { break; } + + int nPos = 0; + int nNALLen = 0; + int nFIXLen = 0; + XENGINE_AVCODEC_VIDEOFRAMETYPE enFrameType; + + AVHelp_Parse_NaluHdr(ptszMSGBuffer, nMSGLen, &nNALLen, &nFIXLen); + AVHelp_Parse_NaluType(ptszMSGBuffer + nPos, ENUM_XENGINE_AVCODEC_VIDEO_TYPE_H264, &enFrameType); + //如果是AUD单元,跳过AUD + if (ENUM_XENGINE_AVCODEC_VIDEO_FRAMETYPE_AUD == enFrameType) + { + nPos = nNALLen; + //重新获取 + AVHelp_Parse_NaluType(ptszMSGBuffer + nPos, ENUM_XENGINE_AVCODEC_VIDEO_TYPE_H264, &enFrameType); + } + //如果是关键帧 + if (ENUM_XENGINE_AVCODEC_VIDEO_FRAMETYPE_SPS == enFrameType || ENUM_XENGINE_AVCODEC_VIDEO_FRAMETYPE_PPS == enFrameType || ENUM_XENGINE_AVCODEC_VIDEO_FRAMETYPE_SEI == enFrameType) + { + XEngine_AVPacket_AVHdr(ppSt_ListAddr[i]->tszClientAddr, ptszMSGBuffer + nPos, nMSGLen - nPos, 0, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT); + } + XEngine_AVPacket_AVFrame(ptszSDBuffer, &nSDLen, ptszRVBuffer, &nRVLen, ppSt_ListAddr[i]->tszClientAddr, ptszMSGBuffer + nPos, nMSGLen - nPos, 0); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DEBUG, _X("SRT推流端:%s,接受视频推流数据,数据大小:%d,帧类型:%d,跳过AUD:%d"), ppSt_ListAddr[i]->tszClientAddr, nMSGLen, enFrameType, nPos); //fwrite(ptszMSGBuffer, 1, nMSGLen, pSt_VFile); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMSGBuffer); } @@ -206,7 +233,11 @@ bool PushStream_ClientProtocol_Thread() { break; } - //fwrite(ptszMSGBuffer, 1, nRVLen, pSt_AFile); + //OPUS + //XEngine_AVPacket_AVHdr(ppSt_ListAddr[i]->tszClientAddr, ptszMSGBuffer, nMSGLen, 1, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT); + //XEngine_AVPacket_AVFrame(ptszSDBuffer, &nSDLen, ptszRVBuffer, &nRVLen, ppSt_ListAddr[i]->tszClientAddr, ptszMSGBuffer + 7, nMSGLen - 7, 1); + //XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DEBUG, _X("SRT推流端:%s,接受音频推流数据,数据大小:%d"), ppSt_ListAddr[i]->tszClientAddr, nMSGLen); + fwrite(ptszMSGBuffer, 1, nRVLen, pSt_AFile); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMSGBuffer); } } @@ -412,9 +443,11 @@ bool PushStream_ClientWhip_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LP SDPProtocol_Packet_GetPacket(xhPacket, tszRVBuffer, &nRVLen); SDPProtocol_Packet_Destory(xhPacket); - ModuleSession_PushStream_Create(tszUserStr, tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTC); + ModuleSession_PushStream_Create(tszUserStr, tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTC); ModuleSession_PushStream_RTCIndexSet(tszUserStr, nVideoIndex, nAudioIndex); ModuleSession_PushStream_SetAVInfo(tszUserStr, &st_AVInfo); + + XEngine_AVPacket_AVCreate(tszUserStr); SocketOpt_HeartBeat_InsertAddrEx(xhRTCWhipHeart, tszUserStr); //需要加入心跳,不然没法知道超时 st_HDRParam.nHttpCode = 201; diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_AVPacket.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_AVPacket.cpp index bb9da3b..b30dc2c 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_AVPacket.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_AVPacket.cpp @@ -23,7 +23,6 @@ bool XEngine_AVPacket_AVCreate(LPCXSTR lpszClientAddr) if (st_ServiceConfig.st_XPull.st_PullHls.bEnable || st_ServiceConfig.st_XPull.st_PullSrt.bEnable || st_ServiceConfig.st_XPull.st_PullTs.bEnable) { HLSProtocol_TSPacket_Insert(lpszClientAddr, 100); - if (st_ServiceConfig.st_XPull.st_PullHls.bEnable) { XCHAR tszSMSAddr[XPATH_MAX] = {}; @@ -314,19 +313,75 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n } } } + else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTC == enClientType) + { + //SRT推流 + ModuleSession_PushStream_GetAVInfo(lpszClientAddr, &st_AVInfo); + if (0 == byAVType) + { + int nPos = 0; + int nSPSLen = 0; + int nPPSLen = 0; + XBYTE uszSPSBuffer[1024]; + XBYTE uszPPSBuffer[1024]; + + memset(uszSPSBuffer, '\0', sizeof(uszSPSBuffer)); + memset(uszPPSBuffer, '\0', sizeof(uszPPSBuffer)); + if (!AVHelp_Parse_VideoHdr(lpszMsgBuffer, nMsgLen, ENUM_XENGINE_AVCODEC_VIDEO_TYPE_H264, NULL, uszSPSBuffer, uszPPSBuffer, NULL, NULL, &nSPSLen, &nPPSLen, NULL, &nPos)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("SRT推流端:%s,解析SPS,PPS,VPS失败,错误:%lX"), lpszClientAddr, AVHelp_GetLastError()); + return false; + } + AFHELP_FRAMESPS st_SPSFrame; + memset(&st_SPSFrame, '\0', sizeof(AFHELP_FRAMESPS)); + + AVHelp_Parse_SPSInfo((LPCXSTR)uszSPSBuffer + 1, nSPSLen - 1, &st_SPSFrame); + _tcsxcpy(st_AVInfo.tszPktName, "Lavf59.27.100"); + st_AVInfo.st_VideoInfo.bEnable = true; + st_AVInfo.st_VideoInfo.enAVCodec = 7; + st_AVInfo.st_VideoInfo.nWidth = st_SPSFrame.nFrameWidth; + st_AVInfo.st_VideoInfo.nHeight = st_SPSFrame.nFrameHeigth; + st_AVInfo.st_VideoInfo.nFrameRate = st_SPSFrame.nFrameFPS; + st_AVInfo.st_VideoInfo.nVLen = nPos; + memset(st_AVInfo.st_VideoInfo.tszVInfo, '\0', sizeof(st_AVInfo.st_VideoInfo.tszVInfo)); + memcpy(st_AVInfo.st_VideoInfo.tszVInfo, lpszMsgBuffer, nPos); + XEngine_AVPacket_AVSetTime(lpszClientAddr, st_AVInfo.st_VideoInfo.nFrameRate, st_AVInfo.st_AudioInfo.nSampleRate); + ModuleSession_PushStream_SetAVInfo(lpszClientAddr, &st_AVInfo); + } + else + { + //音频参数信息是否存在 + if (0 == st_AVInfo.st_AudioInfo.nALen) + { + int nProfile = 0; + int nConfig = 0; + if (AVHelp_Parse_AACInfo((const XBYTE*)lpszMsgBuffer, nMsgLen, &st_AVInfo.st_AudioInfo.nChannel, &st_AVInfo.st_AudioInfo.nSampleRate, &nProfile, &nConfig)) + { + st_AVInfo.st_AudioInfo.bEnable = true; + st_AVInfo.st_AudioInfo.nALen = 7; + st_AVInfo.st_AudioInfo.enAVCodec = 10; + st_AVInfo.st_AudioInfo.nSampleFmt = 16; + st_AVInfo.st_AudioInfo.nChannel = 1; + XEngine_AVPacket_AVSetTime(lpszClientAddr, st_AVInfo.st_VideoInfo.nFrameRate, st_AVInfo.st_AudioInfo.nSampleRate); + AVHelp_Packet_AACHdr((XBYTE*)st_AVInfo.st_AudioInfo.tszAInfo, st_AVInfo.st_AudioInfo.nSampleRate, st_AVInfo.st_AudioInfo.nChannel, 0); + ModuleSession_PushStream_SetAVInfo(lpszClientAddr, &st_AVInfo); + } + } + } + } if (st_ServiceConfig.st_XPull.st_PullWebRtc.bEnable && 0 != byAVType) { - XNETHANDLE xhDecodec = 0; - XNETHANDLE xhEncodec = 0; - if (!AudioCodec_Stream_DeInit(&xhDecodec, ENUM_XENGINE_AVCODEC_AUDIO_TYPE_AAC)) + XHANDLE xhDecodec = AudioCodec_Stream_DeInit(ENUM_XENGINE_AVCODEC_AUDIO_TYPE_AAC); + if (NULL == xhDecodec) { XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("推流端:%s,初始化音频解码器失败,错误:%lX"), lpszClientAddr, AudioCodec_GetLastError()); return false; } st_AVInfo.st_AudioInfo.enAVCodec = ENUM_XENGINE_AVCODEC_AUDIO_TYPE_AAC; - if (!AudioCodec_Stream_EnInit(&xhEncodec, &st_AVInfo.st_AudioInfo)) + XHANDLE xhEncodec = AudioCodec_Stream_EnInit(&st_AVInfo.st_AudioInfo); + if (NULL == xhEncodec) { AudioCodec_Stream_Destroy(xhDecodec); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("推流端:%s,初始化音频编码器失败,错误:%lX"), lpszClientAddr, AudioCodec_GetLastError()); @@ -561,7 +616,7 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTSP == stl_ListIteratorClient->enClientType) { int nPacketCount = 0; - STREAMMEDIA_RTPPROTOCOL_PACKET** ppSt_RTPPacket; + XENGINE_MSGBUFFER** ppSt_RTPPacket; XCHAR tszSSCRStr[XPATH_MAX] = {}; XCHAR tszADDRStr[128] = {}; @@ -573,7 +628,7 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR //发送数据,RTSP使用UDP发送 for (int i = 0; i < nPacketCount; i++) { - NetCore_UDPXCore_SendEx(xhVRTPSocket, tszADDRStr, ppSt_RTPPacket[i]->tszMsgBuffer, ppSt_RTPPacket[i]->nMsgLen); + NetCore_UDPXCore_SendEx(xhVRTPSocket, tszADDRStr, (LPCXSTR)ppSt_RTPPacket[i]->unData.tszMSGBuffer, ppSt_RTPPacket[i]->nMSGLen[0]); } } else @@ -584,7 +639,7 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR //发送数据,RTSP使用UDP发送 for (int i = 0; i < nPacketCount; i++) { - NetCore_UDPXCore_SendEx(xhARTPSocket, tszADDRStr, ppSt_RTPPacket[i]->tszMsgBuffer, ppSt_RTPPacket[i]->nMsgLen); + NetCore_UDPXCore_SendEx(xhARTPSocket, tszADDRStr, (LPCXSTR)ppSt_RTPPacket[i]->unData.tszMSGBuffer, ppSt_RTPPacket[i]->nMSGLen[0]); } } BaseLib_Memory_Free((XPPPMEM)&ppSt_RTPPacket, nPacketCount); @@ -601,7 +656,7 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTC == stl_ListIteratorClient->enClientType) { int nPacketCount = 0; - STREAMMEDIA_RTPPROTOCOL_PACKET** ppSt_RTPPacket; + XENGINE_MSGBUFFER** ppSt_RTPPacket; XCHAR tszSSCRStr[XPATH_MAX] = {}; if (0 == byAVType) @@ -611,8 +666,8 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR //发送数据,RTSP使用UDP发送 for (int i = 0; i < nPacketCount; i++) { - ModuleHelp_SRTPCore_RTPINProtect(ppSt_RTPPacket[i]->tszMsgBuffer, &ppSt_RTPPacket[i]->nMsgLen); - XEngine_Network_Send(stl_ListIteratorClient->tszClientID, ppSt_RTPPacket[i]->tszMsgBuffer, ppSt_RTPPacket[i]->nMsgLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTC); + ModuleHelp_SRTPCore_RTPINProtect((XCHAR *)ppSt_RTPPacket[i]->unData.tszMSGBuffer, &ppSt_RTPPacket[i]->nMSGLen[0]); + XEngine_Network_Send(stl_ListIteratorClient->tszClientID, (LPCXSTR)ppSt_RTPPacket[i]->unData.tszMSGBuffer, ppSt_RTPPacket[i]->nMSGLen[0], ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTC); } } else diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Configure.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Configure.cpp index 280b0a0..a7a4df2 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Configure.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Configure.cpp @@ -28,35 +28,35 @@ bool XEngine_Configure_Parament(int argc, char** argv) for (int i = 0; i < argc; i++) { - if ((0 == _tcsxicmp("-h", argv[i])) || (0 == _tcsxicmp("-H", argv[i]))) + if ((0 == _tcsxcmp("-h", argv[i])) || (0 == _tcsxcmp("-H", argv[i]))) { XEngine_Configure_Help(); return false; } - else if (0 == _tcsxicmp("-d", argv[i])) + else if (0 == _tcsxcmp("-d", argv[i])) { st_ServiceConfig.bDeamon = _ttxoi(argv[i + 1]); } - else if (0 == _tcsxicmp("-b", argv[i])) + else if (0 == _tcsxcmp("-b", argv[i])) { st_ServiceConfig.bDebug = true; } - else if (0 == _tcsxicmp("-t", argv[i])) + else if (0 == _tcsxcmp("-t", argv[i])) { bIsTest = true; } - else if (0 == _tcsxicmp("-l", argv[i])) + else if (0 == _tcsxcmp("-l", argv[i])) { LPCXSTR lpszLogLevel = argv[++i]; - if (0 == _tcsxicmp("debug", lpszLogLevel)) + if (0 == _tcsxcmp("debug", lpszLogLevel)) { st_ServiceConfig.st_XLog.nLogLeave = XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DETAIL; } - else if (0 == _tcsxicmp("detail", lpszLogLevel)) + else if (0 == _tcsxcmp("detail", lpszLogLevel)) { st_ServiceConfig.st_XLog.nLogLeave = XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DETAIL; } - else if (0 == _tcsxicmp("info", lpszLogLevel)) + else if (0 == _tcsxcmp("info", lpszLogLevel)) { st_ServiceConfig.st_XLog.nLogLeave = XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO; } diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Hdr.h b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Hdr.h index 24d460c..6f21a29 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Hdr.h +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Hdr.h @@ -31,6 +31,8 @@ using namespace std; #include #include #include +#include +#include #include #include #include @@ -59,9 +61,9 @@ using namespace std; #include #include #include -#include #include #include +#include #include #include #include @@ -81,6 +83,8 @@ using namespace std; #include "../../XEngine_ModuleQueue/ModuleQueue_Error.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport/InfoReport_Define.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport/InfoReport_Error.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Define.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" //加载自己的头文件 #include "XEngine_Configure.h" #include "XEngine_Network.h" @@ -163,6 +167,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"XEngine_Core/XEngine_Core.lib") #pragma comment(lib,"XEngine_Core/XEngine_ManagePool.lib") #pragma comment(lib,"XEngine_Core/XEngine_Cryption.lib") +#pragma comment(lib,"XEngine_Client/XClient_APIHelp.lib") #pragma comment(lib,"XEngine_NetHelp/NetHelp_XSocket.lib") #pragma comment(lib,"XEngine_NetHelp/NetHelp_APIHelp.lib") #pragma comment(lib,"XEngine_NetHelp/NetHelp_APIAddr.lib") @@ -188,6 +193,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../x64/Debug/XEngine_ModuleHelp") #pragma comment(lib,"../../x64/Debug/XEngine_ModuleQueue") #pragma comment(lib,"../../x64/Debug/XEngine_InfoReport") +#pragma comment(lib,"../../x64/Debug/XEngine_Verification") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Debug/XEngine_ModuleConfigure.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_ModuleProtocol.lib") @@ -195,6 +201,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../ARM64/Debug/XEngine_ModuleHelp") #pragma comment(lib,"../../ARM64/Debug/XEngine_ModuleQueue") #pragma comment(lib,"../../ARM64/Debug/XEngine_InfoReport") +#pragma comment(lib,"../../ARM64/Debug/XEngine_Verification") #elif _M_IX86 #pragma comment(lib,"../../Debug/XEngine_ModuleConfigure.lib") #pragma comment(lib,"../../Debug/XEngine_ModuleProtocol.lib") @@ -202,6 +209,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../Debug/XEngine_ModuleHelp") #pragma comment(lib,"../../Debug/XEngine_ModuleQueue") #pragma comment(lib,"../../Debug/XEngine_InfoReport") +#pragma comment(lib,"../../Debug/XEngine_Verification") #endif #else #ifdef _M_X64 @@ -211,6 +219,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../x64/Release/XEngine_ModuleHelp") #pragma comment(lib,"../../x64/Release/XEngine_ModuleQueue") #pragma comment(lib,"../../x64/Release/XEngine_InfoReport") +#pragma comment(lib,"../../x64/Release/XEngine_Verification") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Release/XEngine_ModuleConfigure.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_ModuleProtocol.lib") @@ -218,6 +227,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../ARM64/Release/XEngine_ModuleHelp") #pragma comment(lib,"../../ARM64/Release/XEngine_ModuleQueue") #pragma comment(lib,"../../ARM64/Release/XEngine_InfoReport") +#pragma comment(lib,"../../ARM64/Release/XEngine_Verification") #elif _M_IX86 #pragma comment(lib,"../../Release/XEngine_ModuleConfigure.lib") #pragma comment(lib,"../../Release/XEngine_ModuleProtocol.lib") @@ -225,6 +235,7 @@ static int nRTPAIndex = 98; #pragma comment(lib,"../../Release/XEngine_ModuleHelp") #pragma comment(lib,"../../Release/XEngine_ModuleQueue") #pragma comment(lib,"../../Release/XEngine_InfoReport") +#pragma comment(lib,"../../Release/XEngine_Verification") #endif #endif #endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_HttpTask.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_HttpTask.cpp index 1eb9819..55d9613 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_HttpTask.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_HttpTask.cpp @@ -64,19 +64,120 @@ bool XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCXSTR LPCXSTR lpszMethodPost = _X("POST"); LPCXSTR lpszMethodGet = _X("GET"); LPCXSTR lpszMethodOPtion = _X("OPTION"); - XCHAR tszRVBuffer[4096]; - XCHAR tszSDBuffer[4096]; - XCHAR tszUrlName[128]; - RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam; - - memset(tszSDBuffer, '\0', sizeof(tszSDBuffer)); - memset(tszRVBuffer, '\0', sizeof(tszRVBuffer)); - memset(tszUrlName, '\0', sizeof(tszUrlName)); - memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM)); + XCHAR tszRVBuffer[4096] = {}; + XCHAR tszSDBuffer[4096] = {}; + XCHAR tszUrlName[128] = {}; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam = {}; st_HDRParam.nHttpCode = 200; //HTTP CODE码 st_HDRParam.bIsClose = true; //收到回复后就关闭 + //HTTP验证 + if (st_ServiceConfig.st_XVerification.bEnable) + { + int nVType = 0; + RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam = {}; + + st_HDRParam.nHttpCode = 401; + st_HDRParam.bIsClose = true; + st_HDRParam.bAuth = true; + //打包验证信息 + int nHDRLen = 0; + XCHAR tszHDRBuffer[XPATH_MAX] = {}; + if (1 == st_ServiceConfig.st_XVerification.nVType) + { + Verification_HTTP_BasicServerPacket(tszHDRBuffer, &nHDRLen); + } + else + { + XCHAR tszNonceStr[64] = {}; + XCHAR tszOpaqueStr[64] = {}; + Verification_HTTP_DigestServerPacket(tszHDRBuffer, &nHDRLen, tszNonceStr, tszOpaqueStr); + } + //后去验证方法 + if (!Verification_HTTP_GetType(*ppptszHDRList, nHDRCount, &nVType)) + { + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, NULL, 0, tszHDRBuffer); + XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,验证方式:%d,错误:%lX"), lpszClientAddr, st_ServiceConfig.st_XVerification.nVType, Verification_GetLastError()); + return false; + } + //验证方式是否一致 + if (st_ServiceConfig.st_XVerification.nVType != nVType) + { + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, NULL, 0, tszHDRBuffer); + XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,验证方式错误,请求:%d,需求:%d"), lpszClientAddr, nVType, st_ServiceConfig.st_XVerification.nVType); + return false; + } + bool bRet = false; + //通过什么方法获得用户密码 + if (_tcsxlen(st_ServiceConfig.st_XVerification.tszAPIUrl) > 0) + { + int nHTTPCode = 0; + int nMSGLen = 0; + XCLIENT_APIHTTP st_APIHttp = {}; + XCHAR* ptszMSGBuffer = NULL; + if (!APIClient_Http_Request(_X("GET"), st_ServiceConfig.st_XVerification.tszAPIUrl, NULL, &nHTTPCode, &ptszMSGBuffer, &nMSGLen, NULL, NULL, &st_APIHttp)) + { + st_HDRParam.nHttpCode = 500; + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_UNAUTHORIZE, "api server is down,cant verification"); + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); + XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,GET请求验证服务:%s 失败,错误码:%lX"), lpszClientAddr, st_ServiceConfig.st_XVerification.tszAPIUrl, APIClient_GetLastError()); + return false; + } + if (200 != nHTTPCode) + { + st_HDRParam.nHttpCode = 500; + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_UNAUTHORIZE, "api server is down,cant verification"); + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); + XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,GET请求验证服务:%s 失败,错误:%d"), lpszClientAddr, st_ServiceConfig.st_XVerification.tszAPIUrl, nHTTPCode); + return false; + } + XENGINE_PROTOCOL_USERAUTHEX st_UserAuth = {}; + if (!ModuleProtocol_Parse_HTTPParseAuth(ptszMSGBuffer, nMsgLen, &st_UserAuth)) + { + st_HDRParam.nHttpCode = 500; + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_UNAUTHORIZE, "api server reply failure,cant verification"); + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); + XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,返回内容:%s 错误,无法继续"), lpszClientAddr, ptszMSGBuffer); + BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMSGBuffer); + return false; + } + BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMSGBuffer); + if (1 == nVType) + { + bRet = Verification_HTTP_Basic(st_UserAuth.tszUserName, st_UserAuth.tszUserPass, *ppptszHDRList, nHDRCount); + } + else if (2 == nVType) + { + bRet = Verification_HTTP_Digest(st_UserAuth.tszUserName, st_UserAuth.tszUserPass, pSt_HTTPParam->tszHttpMethod, *ppptszHDRList, nHDRCount); + } + } + else + { + if (1 == nVType) + { + bRet = Verification_HTTP_Basic(st_ServiceConfig.st_XVerification.tszUserName, st_ServiceConfig.st_XVerification.tszUserPass, *ppptszHDRList, nHDRCount); + } + else if (2 == nVType) + { + bRet = Verification_HTTP_Digest(st_ServiceConfig.st_XVerification.tszUserName, st_ServiceConfig.st_XVerification.tszUserPass, pSt_HTTPParam->tszHttpMethod, *ppptszHDRList, nHDRCount); + } + } + + if (!bRet) + { + HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, NULL, 0, tszHDRBuffer); + NetCore_TCPXCore_SendEx(xhHttpSocket, lpszClientAddr, tszSDBuffer, nSDLen); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户验证失败,验证处理错误,可能用户密码登信息不匹配,类型:%d"), lpszClientAddr, nVType); + return false; + } + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,HTTP验证类型:%d 通过"), lpszClientAddr, nVType); + } XCHAR tszAPIType[128] = {}; XCHAR tszAPIVer[128] = {}; XCHAR tszAPIName[128] = {}; @@ -85,7 +186,7 @@ bool XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCXSTR HttpProtocol_ServerHelp_GetParament(pSt_HTTPParam->tszHttpUri, &pptszList, &nListCount, tszUrlName); if (nListCount < 1) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 400, "Bad Request,parament is incorrent"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_REQUEST_PARAMETER, "Bad Request,parament is incorrent"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); BaseLib_Memory_Free((XPPPMEM)&pptszList, nListCount); @@ -104,7 +205,7 @@ bool XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCXSTR if (0 != _tcsxnicmp(lpszFuncName, tszUrlName, _tcsxlen(lpszFuncName)) && 0 != _tcsxnicmp(lpszFunRtc, tszAPIType, _tcsxlen(lpszFunRtc))) { - ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 400, "Bad Request,parament is incorrent"); + ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, ERROR_SMS_PROTOCOL_REQUEST_PARAMETER, "Bad Request,parament is incorrent"); HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen); XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP); BaseLib_Memory_Free((XPPPMEM)&pptszList, nListCount); @@ -130,7 +231,6 @@ bool XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCXSTR { //获得函数名 BaseLib_String_GetKeyValue(pptszList[0], "=", tszKey, tszValue); - //获得函数名 //http://app.xyry.org:5501/api?function=forward&url=http://app.xyry.org if (0 == _tcsxnicmp(lpszFunctionStr, tszKey, _tcsxlen(lpszFunctionStr))) diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Network.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Network.cpp index 8a54ebb..fd24d66 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Network.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_Network.cpp @@ -271,8 +271,8 @@ void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart, { HLSProtocol_M3u8Packet_Delete(xhHLSFile, xhHLSToken, st_ServiceConfig.st_XPull.st_PullHls.bClear); } - XNETHANDLE xhDecodec = 0; - XNETHANDLE xhEncodec = 0; + XHANDLE xhDecodec = 0; + XHANDLE xhEncodec = 0; if (ModuleSession_PushStream_AudioCodecGet(lpszClientAddr, &xhDecodec, &xhEncodec)) { AudioCodec_Stream_Destroy(xhDecodec); diff --git a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_StreamMediaApp.cpp b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_StreamMediaApp.cpp index 7516980..957679b 100644 --- a/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_StreamMediaApp.cpp +++ b/XEngine_Source/XEngine_ServiceApp/XEngine_StreamMediaApp/XEngine_StreamMediaApp.cpp @@ -217,7 +217,7 @@ int main(int argc, char** argv) memset(&st_ServiceConfig, '\0', sizeof(XENGINE_SERVICECONFIG)); //pSt_VFile = _xtfopen("./1.h264", "wb"); - //pSt_AFile = _xtfopen("./1.opus", "wb"); + pSt_AFile = _xtfopen("./1.opus", "wb"); //初始化参数 if (!XEngine_Configure_Parament(argc, argv)) { diff --git a/XEngine_Source/XEngine_UserProtocol.h b/XEngine_Source/XEngine_UserProtocol.h index beb0800..29af3d9 100644 --- a/XEngine_Source/XEngine_UserProtocol.h +++ b/XEngine_Source/XEngine_UserProtocol.h @@ -61,6 +61,13 @@ typedef enum #define XENGINE_COMMUNICATION_PROTOCOL_OPERATOR_CODE_SMS_REPPULL 0x3008 #define XENGINE_COMMUNICATION_PROTOCOL_OPERATOR_CODE_SMS_STATPUSH 0x3009 //推流端状态推送协议 #define XENGINE_COMMUNICATION_PROTOCOL_OPERATOR_CODE_SMS_STATPULL 0x300A //拉流端状态推送协议 +/************************************************************************/ +/* HTTP错误定义 */ +/************************************************************************/ +#define ERROR_SMS_PROTOCOL_UNAUTHORIZE 0x001 //未验证 +#define ERROR_SMS_PROTOCOL_REQUEST_PARAMETER 0x002 //请求参数错误 +#define ERROR_SMS_PROTOCOL_NOTFOUND 0x003 //流未找到 +#define ERROR_SMS_PROTOCOL_NOTSUPPORT 0x004 //不支持的操作 /////////////////////////////////////////////////////////////////////////// // 导出的数据结构 ///////////////////////////////////////////////////////////////////////////