1.添加图片注册和前后板主题图片上传;2.修改mdns连接方式
This commit is contained in:
parent
9d506e1cfc
commit
d2bccd9c49
|
@ -42,22 +42,7 @@
|
|||
<ClCompile Include="SourceCode\Media\VideoDecoder\RingBuffer.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\ClientHandler.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\httpClient.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\abstractserver.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\bitmap.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\browser.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\cache.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\dns.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\hostname.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\mdns.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\message.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\prober.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\provider.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\query.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\record.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\resolver.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\server.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\service.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\servicemodel.cpp" />
|
||||
<ClCompile Include="SourceCode\Network\mdns\mdns.c" />
|
||||
<ClCompile Include="SourceCode\RecvDataHandler\RecvDataHandler.cpp" />
|
||||
<ClCompile Include="SourceCode\Widget\MainWidget.cpp">
|
||||
<DynamicSource Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">input</DynamicSource>
|
||||
|
@ -77,12 +62,14 @@
|
|||
<None Include="SourceCode\Json\JsonFile\backBoardOneClickTest.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\backBoardTest.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\backBoardUuid.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\backCmd_config.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\backDevInfo.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\factoryProductInfo.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontBoardFuncConfig.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontBoardLicense.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontBoardOneClickTest.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontBoardTest.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontCmd_config.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\frontDevInfo.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\funcConfig.json" />
|
||||
<None Include="SourceCode\Json\JsonFile\getPic.json" />
|
||||
|
@ -98,6 +85,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SourceCode\Json\readJsonFile.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\mdns.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\MdnsServiceThread.h" />
|
||||
<ClInclude Include="SourceCode\Widget\UI_Widget\UI_Name.h" />
|
||||
<QtMoc Include="SourceCode\LicenseGenerate\LicenseConfirmWindow.h" />
|
||||
<ClInclude Include="SourceCode\LicenseGenerate\LicenseGenerate.h" />
|
||||
|
@ -105,37 +94,8 @@
|
|||
<ClInclude Include="SourceCode\Media\Media.h" />
|
||||
<QtMoc Include="SourceCode\Network\ImageEnrollWindow.h" />
|
||||
<QtMoc Include="SourceCode\Network\PasswordEnrollWindow.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\servicemodel.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\abstractserver.h" />
|
||||
<QtMoc Include="SourceCode\Network\httpClient.h" />
|
||||
<QtMoc Include="SourceCode\Media\VideoDecoder\FocusWindow.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\bitmap.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\browser.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\cache.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\dns.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\hostname.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\mdns.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\message.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\prober.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\provider.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\qmdnsengine_export.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\query.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\record.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\resolver.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\server.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\service.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\bitmap_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\browser_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\cache_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\hostname_p.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\message_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\prober_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\provider_p.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\query_p.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\record_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\resolver_p.h" />
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\server_p.h" />
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\service_p.h" />
|
||||
<ClInclude Include="SourceCode\RecvDataHandler\MsgTpye.h" />
|
||||
<QtMoc Include="SourceCode\Media\VideoDecoder\FFmpegDecoder.h" />
|
||||
<ClInclude Include="SourceCode\Media\VideoDecoder\RingBuffer.h" />
|
||||
|
@ -231,22 +191,22 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/utf-8</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>D:\QT\qt\5.15.2\msvc2019_64\include\QtNetwork;D:\QT\qt\5.15.2\msvc2019_64\include\QtGui;D:\QT\qt\5.15.2\msvc2019_64\include\QtCore;D:\QT\qt\5.15.2\msvc2019_64\include\QtWidgets;D:\QT\qt\5.15.2\msvc2019_64\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>D:\QT\qt\5.15.2\msvc2019_64\include\QtNetwork;D:\QT\qt\5.15.2\msvc2019_64\include\QtGui;D:\QT\qt\5.15.2\msvc2019_64\include\QtCore;D:\QT\qt\5.15.2\msvc2019_64\include\QtWidgets;D:\QT\qt\5.15.2\msvc2019_64\include;E:\facttest\new_factest\FactoryTestTool\ThirdParty\libqrencode\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libYTDoorLockAuthTool.lib;Qt5Core.lib;Qt5Widgets.lib;Qt5Gui.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>D:\QT\qt\5.15.2\msvc2019_64\lib;.\ThirdParty\youtu_auth_tool\libs\windowsx64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libYTDoorLockAuthTool.lib;Qt5Core.lib;Qt5Widgets.lib;Qt5Gui.lib;ErWeiMaLib.lib;Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>D:\QT\qt\5.15.2\msvc2019_64\lib;.\ThirdParty\youtu_auth_tool\libs\windowsx64;E:\facttest\new_factest\FactoryTestTool\ThirdParty\libqrencode\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/utf-8</AdditionalOptions>
|
||||
<PreprocessorDefinitions>DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>D:\QT\qt\5.15.2\msvc2019_64\include\QtNetwork;D:\QT\qt\5.15.2\msvc2019_64\include\QtGui;D:\QT\qt\5.15.2\msvc2019_64\include\QtCore;D:\QT\qt\5.15.2\msvc2019_64\include\QtWidgets;D:\QT\qt\5.15.2\msvc2019_64\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>D:\QT\qt\5.15.2\msvc2019_64\include\QtNetwork;D:\QT\qt\5.15.2\msvc2019_64\include\QtGui;D:\QT\qt\5.15.2\msvc2019_64\include\QtCore;D:\QT\qt\5.15.2\msvc2019_64\include\QtWidgets;D:\QT\qt\5.15.2\msvc2019_64\include;E:\facttest\new_factest\FactoryTestTool\ThirdParty\libqrencode\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>libYTDoorLockAuthTool.lib;Qt5Core.lib;Qt5Widgets.lib;Qt5Gui.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>D:\QT\qt\5.15.2\msvc2019_64\lib;.\ThirdParty\youtu_auth_tool\libs\windowsx64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>libYTDoorLockAuthTool.lib;Qt5Core.lib;Qt5Widgets.lib;Qt5Gui.lib;ErWeiMaLib.lib;Iphlpapi.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>D:\QT\qt\5.15.2\msvc2019_64\lib;.\ThirdParty\youtu_auth_tool\libs\windowsx64;E:\facttest\new_factest\FactoryTestTool\ThirdParty\libqrencode\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
|
|
|
@ -26,60 +26,15 @@
|
|||
<ClCompile Include="SourceCode\LicenseGenerate\LicenseGenerate.cpp">
|
||||
<Filter>LicenseGenerate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\servicemodel.cpp">
|
||||
<Filter>Network\mdns</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\abstractserver.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\bitmap.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\browser.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\cache.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\dns.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\hostname.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\mdns.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\message.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\prober.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\provider.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\query.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\record.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\resolver.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\server.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\qmdnsengine\src\service.cpp">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Widget\UI_Widget\UI_Widget.cpp">
|
||||
<Filter>Widget\UI_Widget</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\httpClient.cpp">
|
||||
<Filter>Network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SourceCode\Network\mdns\mdns.c">
|
||||
<Filter>Network\mdns</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="SourceCode\Widget\MainWidget.h">
|
||||
|
@ -106,60 +61,15 @@
|
|||
<QtMoc Include="SourceCode\Network\PasswordEnrollWindow.h">
|
||||
<Filter>Network</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\servicemodel.h">
|
||||
<Filter>Network\mdns</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\abstractserver.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\browser.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\cache.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\hostname.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\prober.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\provider.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\resolver.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\include\server.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\browser_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\cache_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\hostname_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\prober_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\provider_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\resolver_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\qmdnsengine\src\server_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\httpClient.h">
|
||||
<Filter>Network</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Media\VideoDecoder\FocusWindow.h">
|
||||
<Filter>Media\VideoDecoder</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="SourceCode\Network\mdns\MdnsServiceThread.h">
|
||||
<Filter>Network\mdns</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include=".editorconfig" />
|
||||
|
@ -212,6 +122,12 @@
|
|||
<Filter>Json\JsonFile</Filter>
|
||||
</None>
|
||||
<None Include="UI_config.ini" />
|
||||
<None Include="SourceCode\Json\JsonFile\backCmd_config.json">
|
||||
<Filter>Json\JsonFile</Filter>
|
||||
</None>
|
||||
<None Include="SourceCode\Json\JsonFile\frontCmd_config.json">
|
||||
<Filter>Json\JsonFile</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Widget">
|
||||
|
@ -241,15 +157,6 @@
|
|||
<Filter Include="Network\mdns">
|
||||
<UniqueIdentifier>{3570ab1e-6ede-402b-8dd0-1c53afff0bd8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Network\mdns\qmdnsengine">
|
||||
<UniqueIdentifier>{d437b89e-76f2-495a-9434-e6ab8479c960}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Network\mdns\qmdnsengine\include">
|
||||
<UniqueIdentifier>{7f4c4097-0c9f-4b37-967c-5efae6108a91}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Network\mdns\qmdnsengine\src">
|
||||
<UniqueIdentifier>{e8857e15-2519-4a60-9fd5-eff901a76ba6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Widget\UI_Widget">
|
||||
<UniqueIdentifier>{ca263230-ea2f-4140-82aa-19b06eca1b1e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
@ -273,48 +180,12 @@
|
|||
<ClInclude Include="SourceCode\LicenseGenerate\LicenseGenerate.h">
|
||||
<Filter>LicenseGenerate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\bitmap.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\dns.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\mdns.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\message.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\query.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\record.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\service.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\bitmap_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\message_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\query_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\record_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\src\service_p.h">
|
||||
<Filter>Network\mdns\qmdnsengine\src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\qmdnsengine\include\qmdnsengine_export.h">
|
||||
<Filter>Network\mdns\qmdnsengine\include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Widget\UI_Widget\UI_Name.h">
|
||||
<Filter>Widget\UI_Widget</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SourceCode\Network\mdns\mdns.h">
|
||||
<Filter>Network\mdns</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="icon.rc" />
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"cmds": {
|
||||
"GET_FRONT_V851_VERSION": "0x0400",
|
||||
"GET_REAR_V851_VERSION": "0x0401",
|
||||
"START_PROCESS": "0x0500"
|
||||
}
|
||||
}
|
|
@ -61,7 +61,7 @@
|
|||
},
|
||||
{
|
||||
"cmd": "IMG_ENROLL",
|
||||
"val": 0,
|
||||
"val": "",
|
||||
"lable": "图片注册",
|
||||
"timeout": 2000
|
||||
},
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"cmds": {
|
||||
"FACE_ENROLL_SINGLE": "0x0200",
|
||||
"FACE_ENROLL": "0x0201",
|
||||
"HAND_ENROLL": "0x0202",
|
||||
"FACE_VERIFY": "0x0203",
|
||||
"HAND_VERIFY": "0x0204",
|
||||
"DEL_USER": "0x0205",
|
||||
"DEL_ALLUSER": "0x0206",
|
||||
"GET_USER": "0x0207",
|
||||
"GET_ALLUSER": "0x0208",
|
||||
"PASSWD_ENROLL": "0x0209",
|
||||
"IMG_ENROLL": "0x020A",
|
||||
|
||||
"GET_IMG": "0x0220",
|
||||
"START_VIDEO": "0x0221",
|
||||
"STOP_VIDEO": "0x0222",
|
||||
|
||||
"TOUCH_TEST": "0x0240",
|
||||
"MIC_TEST": "0x0241",
|
||||
"SPK_TEST": "0x0242",
|
||||
"RADAR_TEST": "0x0243",
|
||||
"NFC_TEST": "0x0244",
|
||||
"PR_SWITCH": "0x0245",
|
||||
"PS_TEST": "0x0246",
|
||||
"BACKLIGHT": "0x0247",
|
||||
"IR_LED": "0x0248",
|
||||
"UART_TEST": "0x0249",
|
||||
"PIR_TEST": "0x024A",
|
||||
|
||||
"FACE_VERIFY_THRES": "0x0300",
|
||||
"FACE_THRES_LEVEL": "0x0301",
|
||||
"FACE_LIVE_THRES": "0x0302",
|
||||
"FACE_ACC_THRES": "0x0303",
|
||||
"FACE_ACC_LEVEL": "0x0304",
|
||||
"FACE_DIS_RANGE": "0x0305",
|
||||
"FACE_ANGLE_RANGE": "0x0306",
|
||||
"HAND_VERIFY_THRES": "0x0307",
|
||||
"HANS_THRES_LEVEL": "0x0308",
|
||||
"HAND_LIVE_THRES": "0x0309",
|
||||
"USER_MAX_NUM": "0x030A",
|
||||
"ADMI_USER_MAX_NUM": "0x030B",
|
||||
"FACE_REPEAT": "0x030C",
|
||||
"HAND_REPEAT": "0x030D",
|
||||
|
||||
"SET_IP": "0x0320",
|
||||
"SET_PORT": "0x0321",
|
||||
|
||||
"SET_VOLUME": "0x0340",
|
||||
"SET_BACKLIGHT": "0x0341",
|
||||
"SET_RADAR_DIS": "0x0342",
|
||||
"SET_UART_BARTRATE": "0x0343",
|
||||
|
||||
"SET_LOG_LEVEL": "0x0360",
|
||||
|
||||
"GET_FRONT_V851_VERSION": "0x0400",
|
||||
"GET_FRONT_MCU_VERSION": "0x0401",
|
||||
"GET_FRONT_HW_VERSION": "0x0402",
|
||||
"GET_FRONT_ALGO_VERSION": "0x0403",
|
||||
"GET_FRONT_SN": "0x0404",
|
||||
|
||||
"GET_FRONT_HW_INFO": "0x0420",
|
||||
"WRITE_FRONT_LICENSE": "0x0421"
|
||||
}
|
||||
}
|
|
@ -82,3 +82,11 @@ QJsonArray readJson_getVideo() {
|
|||
QJsonArray readJson_factoryProductInfo() {
|
||||
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/factoryProductInfo.json");
|
||||
}
|
||||
|
||||
QJsonArray readJson_frontCmd_config() {
|
||||
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/frontCmd_config.json");
|
||||
}
|
||||
|
||||
QJsonArray readJson_backCmd_config() {
|
||||
return readJsonArrayFromFile("./SourceCode/Json/JsonFile/backCmd_config.json");
|
||||
}
|
||||
|
|
|
@ -12,12 +12,14 @@ QJsonArray readJson_frontBoardTest();
|
|||
QJsonArray readJson_frontBoardFuncConfig();
|
||||
QJsonArray readJson_frontDevInfo();
|
||||
QJsonArray readJson_frontLicense();
|
||||
QJsonArray readJson_frontCmd_config();
|
||||
|
||||
QJsonArray readJson_backBoardOneClickTest();
|
||||
QJsonArray readJson_backBoardTest();
|
||||
QJsonArray readJson_backBoardFuncConfig();
|
||||
QJsonArray readJson_backDevInfo();
|
||||
QJsonArray readJson_backUuid();
|
||||
QJsonArray readJson_backCmd_config();
|
||||
|
||||
QJsonArray readJson_factoryProductInfo();
|
||||
|
||||
|
@ -27,4 +29,7 @@ QJsonArray readJson_funcConfig();
|
|||
QJsonArray readJson_getPic();
|
||||
QJsonArray readJson_getVideo();
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // READJSONFILE_H
|
||||
|
|
Binary file not shown.
|
@ -112,7 +112,7 @@ QString ClientHandler::getCurrentFuncItemData() const
|
|||
QString ClientHandler::getCurrentItemLable() const
|
||||
{
|
||||
QString lable = currentItem.value("lable").toString();
|
||||
//qDebug() << "Getting current item lable:" << lable;
|
||||
qDebug() << "Getting current item lable:" << lable;
|
||||
return lable; // 返回当前项的 "data" 字段
|
||||
}
|
||||
|
||||
|
@ -157,13 +157,16 @@ void ClientHandler::sendDataToClient(const QByteArray& data)
|
|||
emit sendData(data, isBackBoardOrAllBoard);
|
||||
}
|
||||
|
||||
void ClientHandler::onCommandError() {
|
||||
isCommandError = true;
|
||||
}
|
||||
|
||||
void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, const QString text, const QString backBoardSn, const QString& itemType)
|
||||
{
|
||||
startReadVideoDataTimer(preVideoClientId);
|
||||
currentJson = jsonArray;
|
||||
currentJsonItem = itemIndex;
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
if (itemType == "License") {
|
||||
|
||||
}
|
||||
|
@ -260,6 +263,7 @@ void ClientHandler::sendJsonItem(const QJsonArray& jsonArray, int itemIndex, con
|
|||
}
|
||||
}
|
||||
QString itemData = QJsonDocument(currentItem).toJson();
|
||||
emit currentSendItem(currentItem["cmd"].toString());
|
||||
if (isBackBoardOrAllBoard) {
|
||||
emit sendDataToSomeClient(isBackBoardOrAllBoard, itemData.toUtf8());
|
||||
}
|
||||
|
@ -363,20 +367,21 @@ void ClientHandler::sendFrontItem(int itemIndex)
|
|||
return;
|
||||
}
|
||||
else {
|
||||
QString text = "";
|
||||
QString text = "";
|
||||
QJsonObject currentItem = frontBoardTest[itemIndex].toObject();
|
||||
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") {
|
||||
ImageEnrollWindow dialog;
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
text = dialog.getFilePath();
|
||||
QByteArray imageData = dialog.getImageData();
|
||||
if (!imageData.isEmpty()) {
|
||||
text = QString::fromUtf8(imageData);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
QString downloadUrl;
|
||||
QEventLoop loop;
|
||||
emit startImageSharing(IMG_ENROLL_W, IMG_ENROLL_H, "enroll", [&downloadUrl, &loop](QString responseUrl) {
|
||||
//qDebug() << "Received response from slot:" << responseUrl;
|
||||
downloadUrl = responseUrl; // 更新局部变量
|
||||
loop.quit(); // 退出事件循环
|
||||
});
|
||||
//loop.exec(); // 等待回调执行完成
|
||||
if (!downloadUrl.isEmpty()) {
|
||||
qDebug() << "Image available at:" << downloadUrl;
|
||||
}
|
||||
text = downloadUrl;
|
||||
}
|
||||
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
|
||||
DelUserWindow dialog;
|
||||
|
@ -412,18 +417,22 @@ void ClientHandler::sendBackItem(int itemIndex)
|
|||
else {
|
||||
QString text = "";
|
||||
QJsonObject currentItem = backBoardTest[itemIndex].toObject();
|
||||
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "IMG_ENROLL") {
|
||||
ImageEnrollWindow dialog;
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
text = dialog.getFilePath();
|
||||
QByteArray imageData = dialog.getImageData();
|
||||
if (!imageData.isEmpty()) {
|
||||
text = QString::fromUtf8(imageData);
|
||||
}
|
||||
if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "CHANGE_THEME") {
|
||||
QString downloadUrl;
|
||||
QEventLoop loop;
|
||||
emit startImageSharing(CHANGE_THEME_W, CHANGE_THEME_H, "theme", [&downloadUrl, &loop](QString responseUrl) {
|
||||
//qDebug() << "Received response from slot:" << responseUrl;
|
||||
downloadUrl = responseUrl; // 更新局部变量
|
||||
loop.quit(); // 退出事件循环
|
||||
});
|
||||
//loop.exec(); // 等待回调执行完成
|
||||
if (!downloadUrl.isEmpty()) {
|
||||
qDebug() << "Image available at:" << downloadUrl;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
text = downloadUrl;
|
||||
}
|
||||
else if (currentItem.contains("cmd") && currentItem["cmd"].toString() == "DEL_USER") {
|
||||
DelUserWindow dialog;
|
||||
|
@ -485,11 +494,13 @@ void ClientHandler::sendDevInfoItem()
|
|||
currentJson = backBoardDevInfoJson;
|
||||
currentJsonItem = currentBackBoardIndex;
|
||||
if (currentBackBoardIndex < backBoardDevInfoJson.size()) {
|
||||
isRecvVideoData = false;
|
||||
sendDevInfoJsonItem(backBoardDevInfoJson[currentBackBoardIndex ++].toObject(), 1);
|
||||
}
|
||||
else
|
||||
isPowerOnSend = false;
|
||||
|
||||
else {
|
||||
isRecvVideoData = true;
|
||||
isPowerOnSend = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentJson = frontBoardDevInfoJson;
|
||||
|
@ -688,10 +699,13 @@ void ClientHandler::onDataReceived()
|
|||
}
|
||||
}
|
||||
getCurrentItemLable();
|
||||
//qDebug() << "------- currentItem.value(timeout):" << currentItem.value("timeout").toInt();
|
||||
if ((currentItem.contains("timeout")) || (currentFuncItem.contains("timeout"))) {
|
||||
//qDebug() << "currentItem.contains(timeout):" << currentItem.contains("timeout");
|
||||
emit startTimeout(0);
|
||||
}
|
||||
QJsonObject currentTempItem = currentJson[currentItemIndex].toObject();
|
||||
//qDebug() << "---Received allData size:" << allData.size();
|
||||
if (!allData.isEmpty()) {
|
||||
emit dataReceived(getClientAddress(), allData, 0xFF, currentItemIndex, currentFuncItemIndex, getCurrentItemLable(), "", currentJson, currentJsonItem);
|
||||
if (!isSingleSend && !isPowerOnSend && (currentTempItem["cmd"] != "GET_IMG")) {
|
||||
|
@ -750,9 +764,12 @@ void ClientHandler::onDataReceived()
|
|||
if (preVideoClientId == clientId) {
|
||||
qDebug() << "-----------------" << preVideoClientId << "isRecvVideoData:" << isRecvVideoData;
|
||||
}
|
||||
socket->readAll();
|
||||
//QByteArray data = socket->readAll();
|
||||
//qDebug() << "--------- socket->readAll()" ;
|
||||
QByteArray AllData = socket->readAll();
|
||||
if (isCommandError) {
|
||||
isCommandError = false;
|
||||
emit dataReceived(getClientAddress(), AllData, 0xFF, currentItemIndex, currentFuncItemIndex, "", "", currentJson, currentJsonItem);
|
||||
}
|
||||
//qDebug() << "--------- AllData.size():" << AllData.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,11 +21,16 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QStorageInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QEventLoop>
|
||||
|
||||
#include "DelUserWindows.h"
|
||||
|
||||
#define TEST_TCP_MOVE_TO_MAIN 0
|
||||
#define GET_PIC_DATA_SIZE (480 * 640 * 1.5)
|
||||
#define IMG_ENROLL_W 480
|
||||
#define IMG_ENROLL_H 640
|
||||
#define CHANGE_THEME_W 720
|
||||
#define CHANGE_THEME_H 1280
|
||||
|
||||
class ClientHandler : public QObject, public QRunnable
|
||||
{
|
||||
|
@ -98,6 +103,7 @@ public:
|
|||
void setThreadPriority(QThread::Priority priority);
|
||||
|
||||
signals:
|
||||
void startImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback);
|
||||
// 数据接收信号
|
||||
void dataReceived(const QString& client, const QByteArray& data, unsigned char msg_id, int currentRecvItemIndex,
|
||||
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
|
||||
|
@ -119,6 +125,7 @@ signals:
|
|||
void stopReadTimer(int client_Id);
|
||||
void sendDataToSomeClient(int client_Id, const QByteArray& data);
|
||||
void openFocusWindowRequested(int itemIndex);
|
||||
void currentSendItem(const QString& text);
|
||||
|
||||
public slots:
|
||||
#if !TEST_TCP_MOVE_TO_MAIN
|
||||
|
@ -137,6 +144,7 @@ public slots:
|
|||
void processPendingData();
|
||||
void startReadVideoDataTimer(int client_Id);
|
||||
void stopReadVideoDataTimer(int client_Id);
|
||||
void onCommandError();
|
||||
|
||||
private:
|
||||
QTcpSocket* socket; // 客户端 socket
|
||||
|
@ -171,9 +179,10 @@ private:
|
|||
bool isSingleSend; // 单独点击按键发送的标志
|
||||
bool isClickedSend; // 点击按键发送的标志,没有点击不接收数据
|
||||
bool isRecvVideoData;
|
||||
bool isRecvImgData = false;
|
||||
bool isStartVideo = false;
|
||||
bool isPowerOnSend = false; // 上电发送设备信息
|
||||
bool isRecvImgData = false;
|
||||
bool isStartVideo = false;
|
||||
bool isPowerOnSend = false; // 上电发送设备信息
|
||||
bool isCommandError = false;
|
||||
//QTimer* timeoutTimer; // 超时定时器
|
||||
|
||||
int size;
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <signal.h>
|
||||
|
||||
#include "mdns.h"
|
||||
|
||||
// 添加一个类来运行 mDNS 服务
|
||||
class MdnsServiceThread : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MdnsServiceThread(const QString& hostname, const QString& serviceName, int servicePort, QObject* parent = nullptr)
|
||||
: QThread(parent),
|
||||
m_hostname(hostname),
|
||||
m_serviceName(serviceName),
|
||||
m_servicePort(servicePort) {}
|
||||
|
||||
void stop() {
|
||||
extern volatile sig_atomic_t running;
|
||||
running = 0; // 停止 mDNS 主循环
|
||||
m_running = false; // 设置运行标志为 false
|
||||
}
|
||||
|
||||
protected:
|
||||
void run() override {
|
||||
qDebug() << "Starting mDNS service...";
|
||||
extern volatile sig_atomic_t running; // 使用全局变量控制运行状态
|
||||
running = 1;
|
||||
|
||||
// 调用阻塞的 service_mdns 方法
|
||||
int result = service_mdns(m_hostname.toStdString().c_str(), m_serviceName.toStdString().c_str(), m_servicePort);
|
||||
if (result < 0) {
|
||||
qDebug() << "Failed to start mDNS service";
|
||||
}
|
||||
else {
|
||||
qDebug() << "mDNS service stopped";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_hostname;
|
||||
QString m_serviceName;
|
||||
int m_servicePort;
|
||||
bool m_running = true; // 默认运行状态
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_ABSTRACTSERVER_H
|
||||
#define QMDNSENGINE_ABSTRACTSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Message;
|
||||
|
||||
/**
|
||||
* @brief Base class for sending and receiving DNS messages
|
||||
*
|
||||
* Many of the other classes in this library require the ability to send and
|
||||
* receive DNS messages. By having them use this base class, they become far
|
||||
* easier to test. Any class derived from this one that implements the pure
|
||||
* virtual methods can be used for sending and receiving DNS messages.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT AbstractServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Abstract constructor
|
||||
*/
|
||||
explicit AbstractServer(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief Send a message to its provided destination
|
||||
*
|
||||
* The message should be sent over the IP protocol specified in the
|
||||
* message and to the target address and port specified in the message.
|
||||
*/
|
||||
virtual void sendMessage(const Message &message) = 0;
|
||||
|
||||
/**
|
||||
* @brief Send a message to the multicast address on each interface
|
||||
*
|
||||
* The message should be sent over both IPv4 and IPv6 on all interfaces.
|
||||
*/
|
||||
virtual void sendMessageToAll(const Message &message) = 0;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that a DNS message was received
|
||||
* @param message newly received message
|
||||
*/
|
||||
void messageReceived(const Message &message);
|
||||
|
||||
/**
|
||||
* @brief Indicate that an error has occurred
|
||||
* @param message brief description of the error
|
||||
*/
|
||||
void error(const QString &message);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_ABSTRACTSERVER_H
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BITMAP_H
|
||||
#define QMDNSENGINE_BITMAP_H
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QMDNSENGINE_EXPORT BitmapPrivate;
|
||||
|
||||
/**
|
||||
* @brief 256-bit bitmap
|
||||
*
|
||||
* Bitmaps are used in QMdnsEngine::NSEC records to indicate which records are
|
||||
* available. Bitmaps in mDNS records use only the first block (block 0).
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Bitmap
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an empty bitmap
|
||||
*/
|
||||
Bitmap();
|
||||
|
||||
/**
|
||||
* @brief Create a copy of an existing bitmap
|
||||
*/
|
||||
Bitmap(const Bitmap &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
Bitmap &operator=(const Bitmap &other);
|
||||
|
||||
/**
|
||||
* @brief Equality operator
|
||||
*/
|
||||
bool operator==(const Bitmap &other);
|
||||
|
||||
/**
|
||||
* @brief Destroy the bitmap
|
||||
*/
|
||||
virtual ~Bitmap();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the length of the block in bytes
|
||||
*
|
||||
* This method indicates how many bytes are pointed to by the data()
|
||||
* method.
|
||||
*/
|
||||
quint8 length() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve a pointer to the underlying data in the bitmap
|
||||
*
|
||||
* Use the length() method to determine how many bytes contain valid data.
|
||||
*/
|
||||
const quint8 *data() const;
|
||||
|
||||
/**
|
||||
* @brief Set the data to be stored in the bitmap
|
||||
*
|
||||
* The length parameter indicates how many bytes of data are valid. The
|
||||
* actual bytes are copied to the bitmap.
|
||||
*/
|
||||
void setData(quint8 length, const quint8 *data);
|
||||
|
||||
private:
|
||||
|
||||
BitmapPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BITMAP_H
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BROWSER_H
|
||||
#define QMDNSENGINE_BROWSER_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Cache;
|
||||
class Service;
|
||||
|
||||
class QMDNSENGINE_EXPORT BrowserPrivate;
|
||||
|
||||
/**
|
||||
* @brief %Browser for local services
|
||||
*
|
||||
* This class provides a simple way to discover services on the local network.
|
||||
* A cache may be provided in the constructor to store records for future
|
||||
* queries.
|
||||
*
|
||||
* To browse for services of any type:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Browser browser(&server, QMdnsEngine::MdnsBrowseType);
|
||||
* @endcode
|
||||
*
|
||||
* To browse for services of a specific type:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Browser browser(&server, "_http._tcp.local.");
|
||||
* @endcode
|
||||
*
|
||||
* When a service is found, the serviceAdded() signal is emitted:
|
||||
*
|
||||
* @code
|
||||
* connect(&browser, &QMdnsEngine::Browser::serviceAdded, [](const QMdnsEngine::Service &service) {
|
||||
* qDebug() << "Service added:" << service.name();
|
||||
* });
|
||||
* @endcode
|
||||
*
|
||||
* The serviceUpdated() and serviceRemoved() signals are emitted when services
|
||||
* are updated (their properties change) or are removed, respectively.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Browser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new browser instance
|
||||
* @param server server to use for receiving and sending mDNS messages
|
||||
* @param type service type to browse for
|
||||
* @param cache DNS cache to use or null to create one
|
||||
* @param parent QObject
|
||||
*/
|
||||
Browser(AbstractServer *server, const QByteArray &type, Cache *cache = 0, QObject *parent = 0);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that a new service has been added
|
||||
*
|
||||
* This signal is emitted when the PTR and SRV records for a service are
|
||||
* received. If TXT records are received later, the serviceUpdated()
|
||||
* signal will be emitted.
|
||||
*/
|
||||
void serviceAdded(const Service &service);
|
||||
|
||||
/**
|
||||
* @brief Indicate that the specified service was updated
|
||||
*
|
||||
* This signal is emitted when the SRV record for a service (identified by
|
||||
* its name and type) or a TXT record has changed.
|
||||
*/
|
||||
void serviceUpdated(const Service &service);
|
||||
|
||||
/**
|
||||
* @brief Indicate that the specified service was removed
|
||||
*
|
||||
* This signal is emitted when an essential record (PTR or SRV) is
|
||||
* expiring from the cache. This will also occur when an updated PTR or
|
||||
* SRV record is received with a TTL of 0.
|
||||
*/
|
||||
void serviceRemoved(const Service &service);
|
||||
|
||||
private:
|
||||
|
||||
BrowserPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BROWSER_H
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_CACHE_H
|
||||
#define QMDNSENGINE_CACHE_H
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Record;
|
||||
|
||||
class QMDNSENGINE_EXPORT CachePrivate;
|
||||
|
||||
/**
|
||||
* @brief %Cache for DNS records
|
||||
*
|
||||
* Records are added to the cache using the addRecord() method which are then
|
||||
* stored in the cache until they are considered to have expired, at which
|
||||
* point they are purged. The shouldQuery() signal is used to indicate when a
|
||||
* record is approaching expiry and the recordExpired() signal indicates when
|
||||
* a record has expired (at which point it is removed).
|
||||
*
|
||||
* The cache can be queried to retrieve one or more records matching a given
|
||||
* type. For example, to retrieve all TXT records that match a given name:
|
||||
*
|
||||
* @code
|
||||
* Cache cache;
|
||||
*
|
||||
* QList<QMdnsEngine::Record> records;
|
||||
* cache.lookupRecords("My Service._http._tcp.local.", QMdnsEngine::TXT, records);
|
||||
*
|
||||
* for (const QMdnsEngine::Record &record : records) {
|
||||
* qDebug() << "Record:" << record.name();
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* Alternatively, lookupRecord() can be used to find a single record.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Cache : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an empty cache.
|
||||
*/
|
||||
explicit Cache(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief Add a record to the cache
|
||||
* @param record add this record to the cache
|
||||
*
|
||||
* The TTL for the record will be added to the current time to calculate
|
||||
* when the record expires. Existing records of the same name and type
|
||||
* will be replaced, resetting their expiration.
|
||||
*/
|
||||
void addRecord(const Record &record);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a single record from the cache
|
||||
* @param name name of record to retrieve or null for any
|
||||
* @param type type of record to retrieve or ANY for all types
|
||||
* @param record storage for the record retrieved
|
||||
* @return true if a record was retrieved
|
||||
*
|
||||
* Some record types allow multiple records to be stored with identical
|
||||
* names and types. This method will only retrieve the first matching
|
||||
* record. Use lookupRecords() to obtain all of the records.
|
||||
*/
|
||||
bool lookupRecord(const QByteArray &name, quint16 type, Record &record) const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve multiple records from the cache
|
||||
* @param name name of records to retrieve or null for any
|
||||
* @param type type of records to retrieve or ANY for all types
|
||||
* @param records storage for the records retrieved
|
||||
* @return true if records were retrieved
|
||||
*/
|
||||
bool lookupRecords(const QByteArray &name, quint16 type, QList<Record> &records) const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that a record will expire soon and a new query should be issued
|
||||
* @param record reference to the record that will soon expire
|
||||
*
|
||||
* This signal is emitted when a record reaches approximately 50%, 85%,
|
||||
* 90%, and 95% of its lifetime.
|
||||
*/
|
||||
void shouldQuery(const Record &record);
|
||||
|
||||
/**
|
||||
* @brief Indicate that the specified record expired
|
||||
* @param record reference to the record that has expired
|
||||
*/
|
||||
void recordExpired(const Record &record);
|
||||
|
||||
private:
|
||||
|
||||
CachePrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_CACHE_H
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_DNS_H
|
||||
#define QMDNSENGINE_DNS_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Message;
|
||||
class Record;
|
||||
|
||||
enum {
|
||||
/// IPv4 address record
|
||||
A = 1,
|
||||
/// IPv6 address record
|
||||
AAAA = 28,
|
||||
/// Wildcard for cache lookups
|
||||
ANY = 255,
|
||||
/// List of records
|
||||
NSEC = 47,
|
||||
/// Pointer to hostname
|
||||
PTR = 12,
|
||||
/// %Service information
|
||||
SRV = 33,
|
||||
/// Arbitrary metadata
|
||||
TXT = 16
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parse a name from a raw DNS packet
|
||||
* @param packet raw DNS packet data
|
||||
* @param offset offset into the packet where the name begins
|
||||
* @param name reference to QByteArray to store the name in
|
||||
* @return true if no errors occurred
|
||||
*
|
||||
* The offset will be incremented by the number of bytes read. Name
|
||||
* compression requires access to the contents of the packet.
|
||||
*/
|
||||
QMDNSENGINE_EXPORT bool parseName(const QByteArray &packet, quint16 &offset, QByteArray &name);
|
||||
|
||||
/**
|
||||
* @brief Write a name to a raw DNS packet
|
||||
* @param packet raw DNS packet to write to
|
||||
* @param offset offset to update with the number of bytes written
|
||||
* @param name name to write to the packet
|
||||
* @param nameMap map of names already written to their offsets
|
||||
*
|
||||
* The offset will be incremented by the number of bytes read. The name map
|
||||
* will be updated with offsets of any names written so that it can be passed
|
||||
* to future invocations of this function.
|
||||
*/
|
||||
QMDNSENGINE_EXPORT void writeName(QByteArray &packet, quint16 &offset, const QByteArray &name, QMap<QByteArray, quint16> &nameMap);
|
||||
|
||||
/**
|
||||
* @brief Parse a record from a raw DNS packet
|
||||
* @param packet raw DNS packet data
|
||||
* @param offset offset into the packet where the record begins
|
||||
* @param record reference to Record to populate
|
||||
* @return true if no errors occurred
|
||||
*/
|
||||
QMDNSENGINE_EXPORT bool parseRecord(const QByteArray &packet, quint16 &offset, Record &record);
|
||||
|
||||
/**
|
||||
* @brief Write a record to a raw DNS packet
|
||||
* @param packet raw DNS packet to write to
|
||||
* @param offset offset to update with the number of bytes written
|
||||
* @param record record to write to the packet
|
||||
* @param nameMap map of names already written to their offsets
|
||||
*/
|
||||
QMDNSENGINE_EXPORT void writeRecord(QByteArray &packet, quint16 &offset, Record &record, QMap<QByteArray, quint16> &nameMap);
|
||||
|
||||
/**
|
||||
* @brief Populate a Message with data from a raw DNS packet
|
||||
* @param packet raw DNS packet data
|
||||
* @param message reference to Message to populate
|
||||
* @return true if no errors occurred
|
||||
*/
|
||||
QMDNSENGINE_EXPORT bool fromPacket(const QByteArray &packet, Message &message);
|
||||
|
||||
/**
|
||||
* @brief Create a raw DNS packet from a Message
|
||||
* @param message Message to create the packet from
|
||||
* @param packet storage for raw DNS packet
|
||||
*/
|
||||
QMDNSENGINE_EXPORT void toPacket(const Message &message, QByteArray &packet);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the string representation of a DNS type
|
||||
* @param type integer type
|
||||
* @return human-readable name for the type
|
||||
*/
|
||||
QMDNSENGINE_EXPORT QString typeName(quint16 type);
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_DNS_H
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_HOSTNAME_H
|
||||
#define QMDNSENGINE_HOSTNAME_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
|
||||
class QMDNSENGINE_EXPORT HostnamePrivate;
|
||||
|
||||
/**
|
||||
* @brief %Hostname reserved for exclusive use
|
||||
*
|
||||
* In order to provide services on the local network, a unique hostname must
|
||||
* be used. This class asserts a hostname (by first confirming that it is not
|
||||
* in use) and then responds to A and AAAA queries for the hostname.
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Hostname hostname(&server);
|
||||
*
|
||||
* connect(&hostname, &QMdnsEngine::Hostname::hostnameChanged, [](const QByteArray &hostname) {
|
||||
* qDebug() << "New hostname:" << hostname;
|
||||
* });
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Hostname : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new hostname
|
||||
*/
|
||||
Hostname(AbstractServer *server, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief Determine if a hostname has been registered
|
||||
*
|
||||
* A hostname is not considered registered until a probe for the desired
|
||||
* name has been completed and no matching records were received.
|
||||
*/
|
||||
bool isRegistered() const;
|
||||
|
||||
/**
|
||||
* @brief Retrieve the current hostname
|
||||
*
|
||||
* This value is only valid when isRegistered() returns true.
|
||||
*/
|
||||
QByteArray hostname() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that the current hostname has changed
|
||||
* @param hostname new hostname
|
||||
*/
|
||||
void hostnameChanged(const QByteArray &hostname);
|
||||
|
||||
private:
|
||||
|
||||
HostnamePrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_HOSTNAME_H
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_MDNS_H
|
||||
#define QMDNSENGINE_MDNS_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Standard port for mDNS
|
||||
*/
|
||||
QMDNSENGINE_EXPORT extern const quint16 MdnsPort;
|
||||
|
||||
/**
|
||||
* @brief Standard IPv4 address for mDNS
|
||||
*/
|
||||
QMDNSENGINE_EXPORT extern const QHostAddress MdnsIpv4Address;
|
||||
|
||||
/**
|
||||
* @brief Standard IPv6 address for mDNS
|
||||
*/
|
||||
QMDNSENGINE_EXPORT extern const QHostAddress MdnsIpv6Address;
|
||||
|
||||
/**
|
||||
* @brief Service type for browsing service types
|
||||
*/
|
||||
QMDNSENGINE_EXPORT extern const QByteArray MdnsBrowseType;
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_MDNS_H
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_MESSAGE_H
|
||||
#define QMDNSENGINE_MESSAGE_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Query;
|
||||
class Record;
|
||||
|
||||
class QMDNSENGINE_EXPORT MessagePrivate;
|
||||
|
||||
/**
|
||||
* @brief DNS message
|
||||
*
|
||||
* A DNS message consists of a header and zero or more queries and records.
|
||||
* Instances of this class are created and initialized by
|
||||
* [AbstractServer](@ref QMdnsEngine::AbstractServer) when messages are
|
||||
* received from the network.
|
||||
*
|
||||
* If a message is being constructed in reply to one received from the
|
||||
* network, the reply() method can be used to simplify initialization:
|
||||
*
|
||||
* @code
|
||||
* connect(&server, &QMdnsEngine::Server::messageReceived, [](const QMdnsEngine::Message &message) {
|
||||
* QMdnsEngine::Message reply;
|
||||
* reply.reply(message);
|
||||
* server.sendMessage(reply);
|
||||
* });
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Message
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an empty message
|
||||
*/
|
||||
Message();
|
||||
|
||||
/**
|
||||
* @brief Create a copy of an existing message
|
||||
*/
|
||||
Message(const Message &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
Message &operator=(const Message &other);
|
||||
|
||||
/**
|
||||
* @brief Destroy the message
|
||||
*/
|
||||
virtual ~Message();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the address for the message
|
||||
*
|
||||
* When receiving messages, this is the address that the message was
|
||||
* received from.
|
||||
*/
|
||||
QHostAddress address() const;
|
||||
|
||||
/**
|
||||
* @brief Set the address for the message
|
||||
*
|
||||
* When sending messages, this is the address that the message will be
|
||||
* sent to. QMdnsEngine::MdnsIpv4Address and QMdnsEngine::MdnsIpv6Address
|
||||
* can be used for mDNS messages.
|
||||
*/
|
||||
void setAddress(const QHostAddress &address);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the port for the message
|
||||
*
|
||||
* When receiving messages, this is the port that the message was received
|
||||
* from. For traditional queries, this will be an ephemeral port. For mDNS
|
||||
* queries, this will always equal QMdnsEngine::MdnsPort.
|
||||
*/
|
||||
quint16 port() const;
|
||||
|
||||
/**
|
||||
* @brief Set the port for the message
|
||||
*
|
||||
* When sending messages, this is the port that the message will be sent
|
||||
* to. This should be set to QMdnsEngine::MdnsPort unless the message is a
|
||||
* reply to a traditional DNS query.
|
||||
*/
|
||||
void setPort(quint16 port);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the transaction ID for the message
|
||||
*
|
||||
* This is always set to 1 for mDNS messages. Traditional DNS queries may
|
||||
* set this to an arbitrary integer.
|
||||
*/
|
||||
quint16 transactionId() const;
|
||||
|
||||
/**
|
||||
* @brief Set the transaction ID for the message
|
||||
*
|
||||
* The default transaction ID is 0. This value should not be changed
|
||||
* unless responding to a traditional DNS query.
|
||||
*/
|
||||
void setTransactionId(quint16 transactionId);
|
||||
|
||||
/**
|
||||
* @brief Determine if the message is a response
|
||||
*/
|
||||
bool isResponse() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the message is a response
|
||||
*/
|
||||
void setResponse(bool isResponse);
|
||||
|
||||
/**
|
||||
* @brief Determine if the message is truncated
|
||||
*/
|
||||
bool isTruncated() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether the message is truncated
|
||||
*/
|
||||
void setTruncated(bool isTruncated);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a list of queries in the message
|
||||
*/
|
||||
QList<Query> queries() const;
|
||||
|
||||
/**
|
||||
* @brief Add a query to the message
|
||||
*/
|
||||
void addQuery(const Query &query);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a list of records in the message
|
||||
*/
|
||||
QList<Record> records() const;
|
||||
|
||||
/**
|
||||
* @brief Add a record to the message
|
||||
*/
|
||||
void addRecord(const Record &record);
|
||||
|
||||
/**
|
||||
* @brief Reply to another message
|
||||
*
|
||||
* The message will be correctly initialized to respond to the other
|
||||
* message. This includes setting the target address, port, and
|
||||
* transaction ID.
|
||||
*/
|
||||
void reply(const Message &other);
|
||||
|
||||
private:
|
||||
|
||||
MessagePrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_MESSAGE_H
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROBER_H
|
||||
#define QMDNSENGINE_PROBER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Record;
|
||||
|
||||
class QMDNSENGINE_EXPORT ProberPrivate;
|
||||
|
||||
/**
|
||||
* @brief %Prober to confirm that a record is unique
|
||||
*
|
||||
* Before responding to queries for a record, its uniqueness on the network
|
||||
* must be confirmed. This class takes care of probing for existing records
|
||||
* that match and adjusts the record's name until a unique one is found.
|
||||
*
|
||||
* For example, to probe for a SRV record:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Record record;
|
||||
* record.setName("My Service._http._tcp.local.");
|
||||
* record.setType(QMdnsEngine::SRV);
|
||||
* record.setPort(1234);
|
||||
* record.setTarget(hostname.hostname());
|
||||
*
|
||||
* QMdnsEngine::Prober prober(&server, record);
|
||||
* connect(&prober, &QMdnsEngine::Prober::nameConfirmed, [](const QByteArray &name) {
|
||||
* qDebug() << "Name confirmed:" << name;
|
||||
* });
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Prober : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new prober
|
||||
*/
|
||||
Prober(AbstractServer *server, const Record &record, QObject *parent = 0);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that the name has been confirmed unique
|
||||
* @param name that was confirmed to be unique
|
||||
*/
|
||||
void nameConfirmed(const QByteArray &name);
|
||||
|
||||
private:
|
||||
|
||||
ProberPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROBER_H
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROVIDER_H
|
||||
#define QMDNSENGINE_PROVIDER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Hostname;
|
||||
class Service;
|
||||
|
||||
class QMDNSENGINE_EXPORT ProviderPrivate;
|
||||
|
||||
/**
|
||||
* @brief %Provider for a single mDNS service
|
||||
*
|
||||
* This class provide a [Service](@ref QMdnsEngine::Service) on the local
|
||||
* network by responding to the appropriate DNS queries. A hostname is
|
||||
* required for creating the SRV record.
|
||||
*
|
||||
* The provider needs to be given a reference to the service through the
|
||||
* update() method so that it can construct DNS records:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Service service;
|
||||
* service.setType("_http._tcp.local.");
|
||||
* service.setName("My Service");
|
||||
* service.setPort(1234);
|
||||
*
|
||||
* QMdnsEngine::Provider provider;
|
||||
* provider.update(service);
|
||||
* @endcode
|
||||
*
|
||||
* This method can also be used to update the provider's records.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Provider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new service provider
|
||||
*/
|
||||
Provider(AbstractServer *server, Hostname *hostname, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief Update the service with the provided information
|
||||
* @param service updated service description
|
||||
*
|
||||
* This class will not respond to any DNS queries until the hostname is
|
||||
* confirmed and this method is called.
|
||||
*/
|
||||
void update(const Service &service);
|
||||
|
||||
private:
|
||||
|
||||
ProviderPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROVIDER_H
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_EXPORT_H
|
||||
#define QMDNSENGINE_EXPORT_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#define BUILD_SHARED_LIBS
|
||||
#define QMDNSENGINE_LIBRARY
|
||||
#if defined(BUILD_SHARED_LIBS)
|
||||
# if defined(QMDNSENGINE_LIBRARY)
|
||||
# define QMDNSENGINE_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QMDNSENGINE_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QMDNSENGINE_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // QMDNSENGINE_EXPORT_H
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_QUERY_H
|
||||
#define QMDNSENGINE_QUERY_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QMDNSENGINE_EXPORT QueryPrivate;
|
||||
|
||||
/**
|
||||
* @brief DNS query
|
||||
*
|
||||
* This class represents a query for a DNS record. For example, to query for
|
||||
* the IPv4 address of a local host:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Query query;
|
||||
* query.setName("myserver.local.");
|
||||
* query.setType(QMdnsEngine::A);
|
||||
*
|
||||
* message.addQuery(query);
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Query
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an empty query
|
||||
*/
|
||||
Query();
|
||||
|
||||
/**
|
||||
* @brief Create a copy of an existing query
|
||||
*/
|
||||
Query(const Query &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
Query &operator=(const Query &other);
|
||||
|
||||
/**
|
||||
* @brief Destroy the query
|
||||
*/
|
||||
virtual ~Query();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the name being queried
|
||||
*/
|
||||
QByteArray name() const;
|
||||
|
||||
/**
|
||||
* @brief Set the name to query
|
||||
*/
|
||||
void setName(const QByteArray &name);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the type of record being queried
|
||||
*/
|
||||
quint16 type() const;
|
||||
|
||||
/**
|
||||
* @brief Set the type of record to query
|
||||
*
|
||||
* Constants, such as QMdnsEngine::SRV are provided for convenience.
|
||||
*/
|
||||
void setType(quint16 type);
|
||||
|
||||
/**
|
||||
* @brief Determine if a unicast response is desired
|
||||
*/
|
||||
bool unicastResponse() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether a unicast response is desired
|
||||
*/
|
||||
void setUnicastResponse(bool unicastResponse);
|
||||
|
||||
private:
|
||||
|
||||
QueryPrivate *const d;
|
||||
};
|
||||
|
||||
QMDNSENGINE_EXPORT QDebug operator<<(QDebug dbg, const Query &query);
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_QUERY_H
|
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RECORD_H
|
||||
#define QMDNSENGINE_RECORD_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
#include <QMap>
|
||||
|
||||
#include "bitmap.h"
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QMDNSENGINE_EXPORT RecordPrivate;
|
||||
|
||||
/**
|
||||
* @brief DNS record
|
||||
*
|
||||
* This class maintains information for an individual record. Not all record
|
||||
* types use every field.
|
||||
*
|
||||
* For example, to create a TXT record:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Record record;
|
||||
* record.setName("My Service._http._tcp.local.");
|
||||
* record.setType(QMdnsEngine::TXT);
|
||||
* record.addAttribute("a", "value1");
|
||||
* record.addAttribute("b", "value2");
|
||||
*
|
||||
* message.addRecord(record);
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Record
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an uninitialized record
|
||||
*/
|
||||
Record();
|
||||
|
||||
/**
|
||||
* @brief Create a copy of an existing record
|
||||
*/
|
||||
Record(const Record &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
Record &operator=(const Record &other);
|
||||
|
||||
/**
|
||||
* @brief Equality operator
|
||||
*/
|
||||
bool operator==(const Record &other) const;
|
||||
|
||||
/**
|
||||
* @brief Inequality operator
|
||||
*/
|
||||
bool operator!=(const Record &other) const;
|
||||
|
||||
/**
|
||||
* @brief Destroy the record
|
||||
*/
|
||||
virtual ~Record();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the name of the record
|
||||
*/
|
||||
QByteArray name() const;
|
||||
|
||||
/**
|
||||
* @brief Set the name of the record
|
||||
*/
|
||||
void setName(const QByteArray &name);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the type of the record
|
||||
*/
|
||||
quint16 type() const;
|
||||
|
||||
/**
|
||||
* @brief Set the type of the record
|
||||
*
|
||||
* For convenience, constants for types used by mDNS, such as
|
||||
* QMdnsEngine::A or QMdnsEngine::PTR, may be used here.
|
||||
*/
|
||||
void setType(quint16 type);
|
||||
|
||||
/**
|
||||
* @brief Determine whether to replace or append to existing records
|
||||
*
|
||||
* If true, this record replaces all previous records of the same name and
|
||||
* type rather than appending to them.
|
||||
*/
|
||||
bool flushCache() const;
|
||||
|
||||
/**
|
||||
* @brief Set whether to replace or append to existing records
|
||||
*/
|
||||
void setFlushCache(bool flushCache);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the TTL (time to live) for the record
|
||||
*/
|
||||
quint32 ttl() const;
|
||||
|
||||
/**
|
||||
* @brief Set the TTL (time to live) for the record
|
||||
*/
|
||||
void setTtl(quint32 ttl);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the address for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::A and QMdnsEngine::AAAA records.
|
||||
*/
|
||||
QHostAddress address() const;
|
||||
|
||||
/**
|
||||
* @brief Set the address for the record
|
||||
*/
|
||||
void setAddress(const QHostAddress &address);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the target for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::PTR and QMdnsEngine::SRV records.
|
||||
*/
|
||||
QByteArray target() const;
|
||||
|
||||
/**
|
||||
* @brief Set the target for the record
|
||||
*/
|
||||
void setTarget(const QByteArray &target);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the next domain name
|
||||
*
|
||||
* This field is used by QMdnsEngine::NSEC records.
|
||||
*/
|
||||
QByteArray nextDomainName() const;
|
||||
|
||||
/**
|
||||
* @brief Set the next domain name
|
||||
*/
|
||||
void setNextDomainName(const QByteArray &nextDomainName);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the priority for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::SRV records.
|
||||
*/
|
||||
quint16 priority() const;
|
||||
|
||||
/**
|
||||
* @brief Set the priority for the record
|
||||
*
|
||||
* Unless more than one QMdnsEngine::SRV record is being sent, this field
|
||||
* should be set to 0.
|
||||
*/
|
||||
void setPriority(quint16 priority);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the weight of the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::SRV records.
|
||||
*/
|
||||
quint16 weight() const;
|
||||
|
||||
/**
|
||||
* @brief Set the weight of the record
|
||||
*
|
||||
* Unless more than one QMdnsEngine::SRV record is being sent, this field
|
||||
* should be set to 0.
|
||||
*/
|
||||
void setWeight(quint16 weight);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the port for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::SRV records.
|
||||
*/
|
||||
quint16 port() const;
|
||||
|
||||
/**
|
||||
* @brief Set the port for the record
|
||||
*/
|
||||
void setPort(quint16 port);
|
||||
|
||||
/**
|
||||
* @brief Retrieve attributes for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::TXT records.
|
||||
*/
|
||||
QMap<QByteArray, QByteArray> attributes() const;
|
||||
|
||||
/**
|
||||
* @brief Set attributes for the record
|
||||
*/
|
||||
void setAttributes(const QMap<QByteArray, QByteArray> &attributes);
|
||||
|
||||
/**
|
||||
* @brief Add an attribute to the record
|
||||
*/
|
||||
void addAttribute(const QByteArray &key, const QByteArray &value);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the bitmap for the record
|
||||
*
|
||||
* This field is used by QMdnsEngine::NSEC records.
|
||||
*/
|
||||
Bitmap bitmap() const;
|
||||
|
||||
/**
|
||||
* @brief Set the bitmap for the record
|
||||
*/
|
||||
void setBitmap(const Bitmap &bitmap);
|
||||
|
||||
private:
|
||||
|
||||
RecordPrivate *const d;
|
||||
};
|
||||
|
||||
QMDNSENGINE_EXPORT QDebug operator<<(QDebug dbg, const Record &record);
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RECORD_H
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RESOLVER_H
|
||||
#define QMDNSENGINE_RESOLVER_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Cache;
|
||||
|
||||
class QMDNSENGINE_EXPORT ResolverPrivate;
|
||||
|
||||
/**
|
||||
* @brief %Resolver for services
|
||||
*
|
||||
* When [Browser](@ref QMdnsEngine::Browser) indicates that a new service has
|
||||
* been found, it becomes necessary to resolve the service in order to connect
|
||||
* to it. This class serves that role. A [Cache](@ref QMdnsEngine::Cache) can
|
||||
* optionally be provided to speed up the resolving process.
|
||||
*
|
||||
* For example, assuming that `record` is a SRV record:
|
||||
*
|
||||
* @code
|
||||
* QMdnsEngine::Resolver resolver(&server, record.target());
|
||||
* connect(&resolver, &QMdnsEngine::Resolver::resolved, [](const QHostAddress &address) {
|
||||
* qDebug() << "Address:" << address;
|
||||
* });
|
||||
* @endcode
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Resolver : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new resolver
|
||||
*/
|
||||
Resolver(AbstractServer *server, const QByteArray &name, Cache *cache = 0, QObject *parent = 0);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
/**
|
||||
* @brief Indicate that the host resolved to an address
|
||||
* @param address service address
|
||||
*
|
||||
* This signal will be emitted once for each resolved address. For
|
||||
* example, if a host provides both A and AAAA records, this signal will
|
||||
* be emitted twice.
|
||||
*/
|
||||
void resolved(const QHostAddress &address);
|
||||
|
||||
private:
|
||||
|
||||
ResolverPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RESOLVER_H
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVER_H
|
||||
#define QMDNSENGINE_SERVER_H
|
||||
|
||||
#include "abstractserver.h"
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Message;
|
||||
|
||||
class QMDNSENGINE_EXPORT ServerPrivate;
|
||||
|
||||
/**
|
||||
* @brief mDNS server
|
||||
*
|
||||
* This class provides an implementation of
|
||||
* [AbstractServer](@ref QMdnsEngine::AbstractServer) that uses all available
|
||||
* local network adapters to send and receive mDNS messages.
|
||||
*
|
||||
* The class takes care of watching for the addition and removal of network
|
||||
* interfaces, automatically joining multicast groups when new interfaces are
|
||||
* available.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Server : public AbstractServer
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create a new server
|
||||
*/
|
||||
explicit Server(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief Implementation of AbstractServer::sendMessage()
|
||||
*/
|
||||
virtual void sendMessage(const Message &message);
|
||||
|
||||
/**
|
||||
* @brief Implementation of AbstractServer::sendMessageToAll()
|
||||
*/
|
||||
virtual void sendMessageToAll(const Message &message);
|
||||
|
||||
private:
|
||||
|
||||
ServerPrivate *const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVER_H
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVICE_H
|
||||
#define QMDNSENGINE_SERVICE_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
|
||||
#include "qmdnsengine_export.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QMDNSENGINE_EXPORT ServicePrivate;
|
||||
|
||||
/**
|
||||
* @brief %Service available on the local network
|
||||
*
|
||||
* This class contains the descriptive information necessary to represent an
|
||||
* individual service made available to the local network. Instances are
|
||||
* provided by [Browser](@ref QMdnsEngine::Browser) as services are
|
||||
* discovered. Instances must be created and passed to
|
||||
* [Provider::update()](@ref QMdnsEngine::Provider::update) to provide a
|
||||
* service.
|
||||
*/
|
||||
class QMDNSENGINE_EXPORT Service
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Create an uninitialized service
|
||||
*/
|
||||
Service();
|
||||
|
||||
/**
|
||||
* @brief Create a copy of an existing service
|
||||
*/
|
||||
Service(const Service &other);
|
||||
|
||||
/**
|
||||
* @brief Assignment operator
|
||||
*/
|
||||
Service &operator=(const Service &other);
|
||||
|
||||
/**
|
||||
* @brief Equality operator
|
||||
*/
|
||||
bool operator==(const Service &other) const;
|
||||
|
||||
/**
|
||||
* @brief Inequality operator
|
||||
*/
|
||||
bool operator!=(const Service &other) const;
|
||||
|
||||
/**
|
||||
* @brief Destroy the service
|
||||
*/
|
||||
virtual ~Service();
|
||||
|
||||
/**
|
||||
* @brief Retrieve the service type
|
||||
*/
|
||||
QByteArray type() const;
|
||||
|
||||
/**
|
||||
* @brief Set the service type
|
||||
*
|
||||
* For example, an HTTP service might use "_http._tcp".
|
||||
*/
|
||||
void setType(const QByteArray &type);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the service name
|
||||
*/
|
||||
QByteArray name() const;
|
||||
|
||||
/**
|
||||
* @brief Set the service name
|
||||
*
|
||||
* This is combined with the service type and domain to form the FQDN for
|
||||
* the service.
|
||||
*/
|
||||
void setName(const QByteArray &name);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the hostname of the device providing the service
|
||||
*/
|
||||
QByteArray hostname() const;
|
||||
|
||||
/**
|
||||
* @brief Set the hostname of the device providing the service
|
||||
*/
|
||||
void setHostname(const QByteArray &hostname);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the service port
|
||||
*/
|
||||
quint16 port() const;
|
||||
|
||||
/**
|
||||
* @brief Set the service port
|
||||
*/
|
||||
void setPort(quint16 port);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the attributes for the service
|
||||
*
|
||||
* Boolean attributes will have null values (invoking QByteArray::isNull()
|
||||
* on the value will return true).
|
||||
*/
|
||||
QMap<QByteArray, QByteArray> attributes() const;
|
||||
|
||||
/**
|
||||
* @brief Set the attributes for the service
|
||||
*/
|
||||
void setAttributes(const QMap<QByteArray, QByteArray> &attributes);
|
||||
|
||||
/**
|
||||
* @brief Add an attribute to the service
|
||||
*/
|
||||
void addAttribute(const QByteArray &key, const QByteArray &value);
|
||||
|
||||
private:
|
||||
|
||||
ServicePrivate *const d;
|
||||
};
|
||||
|
||||
QMDNSENGINE_EXPORT QDebug operator<<(QDebug debug, const Service &service);
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVICE_H
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_EXPORT_H
|
||||
#define QMDNSENGINE_EXPORT_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(BUILD_SHARED_LIBS)
|
||||
# if defined(QMDNSENGINE_LIBRARY)
|
||||
# define QMDNSENGINE_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QMDNSENGINE_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define QMDNSENGINE_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // QMDNSENGINE_EXPORT_H
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
AbstractServer::AbstractServer(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/bitmap.h"
|
||||
|
||||
#include "bitmap_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
BitmapPrivate::BitmapPrivate()
|
||||
: length(0),
|
||||
data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
BitmapPrivate::~BitmapPrivate()
|
||||
{
|
||||
free();
|
||||
}
|
||||
|
||||
void BitmapPrivate::free()
|
||||
{
|
||||
if (data) {
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void BitmapPrivate::fromData(quint8 newLength, const quint8 *newData)
|
||||
{
|
||||
data = new quint8[newLength];
|
||||
for (int i = 0; i < newLength; ++i) {
|
||||
data[i] = newData[i];
|
||||
}
|
||||
length = newLength;
|
||||
}
|
||||
|
||||
Bitmap::Bitmap()
|
||||
: d(new BitmapPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Bitmap::Bitmap(const Bitmap &other)
|
||||
: d(new BitmapPrivate)
|
||||
{
|
||||
d->fromData(other.d->length, other.d->data);
|
||||
}
|
||||
|
||||
Bitmap &Bitmap::operator=(const Bitmap &other)
|
||||
{
|
||||
d->free();
|
||||
d->fromData(other.d->length, other.d->data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Bitmap::operator==(const Bitmap &other)
|
||||
{
|
||||
if (d->length != other.d->length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < d->length; ++i) {
|
||||
if (d->data[i] != other.d->data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bitmap::~Bitmap()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
quint8 Bitmap::length() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
const quint8 *Bitmap::data() const
|
||||
{
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void Bitmap::setData(quint8 length, const quint8 *data)
|
||||
{
|
||||
d->free();
|
||||
d->fromData(length, data);
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BITMAP_P_H
|
||||
#define QMDNSENGINE_BITMAP_P_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class BitmapPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
BitmapPrivate();
|
||||
virtual ~BitmapPrivate();
|
||||
|
||||
void free();
|
||||
void fromData(quint8 newLength, const quint8 *newData);
|
||||
|
||||
quint8 length;
|
||||
quint8 *data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BITMAP_P_H
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
#include "../include/browser.h"
|
||||
#include "../include/cache.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/mdns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/query.h"
|
||||
#include "../include/record.h"
|
||||
|
||||
#include "browser_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
BrowserPrivate::BrowserPrivate(Browser *browser, AbstractServer *server, const QByteArray &type, Cache *existingCache)
|
||||
: QObject(browser),
|
||||
server(server),
|
||||
type(type),
|
||||
cache(existingCache ? existingCache : new Cache(this)),
|
||||
q(browser)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &BrowserPrivate::onMessageReceived);
|
||||
connect(cache, &Cache::shouldQuery, this, &BrowserPrivate::onShouldQuery);
|
||||
connect(cache, &Cache::recordExpired, this, &BrowserPrivate::onRecordExpired);
|
||||
connect(&queryTimer, &QTimer::timeout, this, &BrowserPrivate::onQueryTimeout);
|
||||
connect(&serviceTimer, &QTimer::timeout, this, &BrowserPrivate::onServiceTimeout);
|
||||
|
||||
queryTimer.setInterval(60 * 1000);
|
||||
queryTimer.setSingleShot(true);
|
||||
|
||||
serviceTimer.setInterval(100);
|
||||
serviceTimer.setSingleShot(true);
|
||||
|
||||
// Immediately begin browsing for services
|
||||
onQueryTimeout();
|
||||
}
|
||||
|
||||
// TODO: multiple SRV records not supported
|
||||
|
||||
bool BrowserPrivate::updateService(const QByteArray &fqName)
|
||||
{
|
||||
// Split the FQDN into service name and type
|
||||
int index = fqName.indexOf('.');
|
||||
QByteArray serviceName = fqName.left(index);
|
||||
QByteArray serviceType = fqName.mid(index + 1);
|
||||
|
||||
// Immediately return if a PTR record does not exist
|
||||
Record ptrRecord;
|
||||
if (!cache->lookupRecord(serviceType, PTR, ptrRecord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a SRV record is missing, query for it (by returning true)
|
||||
Record srvRecord;
|
||||
if (!cache->lookupRecord(fqName, SRV, srvRecord)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Service service;
|
||||
service.setName(serviceName);
|
||||
service.setType(serviceType);
|
||||
service.setHostname(srvRecord.target());
|
||||
service.setPort(srvRecord.port());
|
||||
|
||||
// If TXT records are available for the service, add their values
|
||||
QList<Record> txtRecords;
|
||||
if (cache->lookupRecords(fqName, TXT, txtRecords)) {
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
for (const Record &record : qAsConst(txtRecords)) {
|
||||
for (auto i = record.attributes().constBegin();
|
||||
i != record.attributes().constEnd(); ++i) {
|
||||
attributes.insert(i.key(), i.value());
|
||||
}
|
||||
}
|
||||
service.setAttributes(attributes);
|
||||
}
|
||||
|
||||
// If the service existed, this is an update; otherwise it is a new
|
||||
// addition; emit the appropriate signal
|
||||
if (!services.contains(fqName)) {
|
||||
emit q->serviceAdded(service);
|
||||
} else if(services.value(fqName) != service) {
|
||||
emit q->serviceUpdated(service);
|
||||
}
|
||||
|
||||
services.insert(fqName, service);
|
||||
hostnames.insert(service.hostname());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BrowserPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool any = type == MdnsBrowseType;
|
||||
|
||||
// Use a set to track all services that are updated in the message to
|
||||
// prevent unnecessary queries for SRV and TXT records
|
||||
QSet<QByteArray> updateNames;
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
bool cacheRecord = false;
|
||||
|
||||
switch (record.type()) {
|
||||
case PTR:
|
||||
if (any && record.name() == MdnsBrowseType) {
|
||||
ptrTargets.insert(record.target());
|
||||
serviceTimer.start();
|
||||
cacheRecord = true;
|
||||
} else if (any || record.name() == type) {
|
||||
updateNames.insert(record.target());
|
||||
cacheRecord = true;
|
||||
}
|
||||
break;
|
||||
case SRV:
|
||||
case TXT:
|
||||
if (any || record.name().endsWith("." + type)) {
|
||||
updateNames.insert(record.name());
|
||||
cacheRecord = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cacheRecord) {
|
||||
cache->addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
// For each of the services marked to be updated, perform the update and
|
||||
// make a list of all missing SRV records
|
||||
QSet<QByteArray> queryNames;
|
||||
for (const QByteArray &name : qAsConst(updateNames)) {
|
||||
if (updateService(name)) {
|
||||
queryNames.insert(name);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache A / AAAA records after services are processed to ensure hostnames are known
|
||||
for (const Record &record : records) {
|
||||
bool cacheRecord = false;
|
||||
|
||||
switch (record.type()) {
|
||||
case A:
|
||||
case AAAA:
|
||||
cacheRecord = hostnames.contains(record.name());
|
||||
break;
|
||||
}
|
||||
if (cacheRecord) {
|
||||
cache->addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
// Build and send a query for all of the SRV and TXT records
|
||||
if (queryNames.count()) {
|
||||
Message queryMessage;
|
||||
for (const QByteArray &name : qAsConst(queryNames)) {
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(SRV);
|
||||
queryMessage.addQuery(query);
|
||||
query.setType(TXT);
|
||||
queryMessage.addQuery(query);
|
||||
}
|
||||
server->sendMessageToAll(queryMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::onShouldQuery(const Record &record)
|
||||
{
|
||||
// Assume that all messages in the cache are still in use (by the browser)
|
||||
// and attempt to renew them immediately
|
||||
|
||||
Query query;
|
||||
query.setName(record.name());
|
||||
query.setType(record.type());
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void BrowserPrivate::onRecordExpired(const Record &record)
|
||||
{
|
||||
// If the SRV record has expired for a service, then it must be
|
||||
// removed - TXT records on the other hand, cause an update
|
||||
|
||||
QByteArray serviceName;
|
||||
switch (record.type()) {
|
||||
case SRV:
|
||||
serviceName = record.name();
|
||||
break;
|
||||
case TXT:
|
||||
updateService(record.name());
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Service service = services.value(serviceName);
|
||||
if (!service.name().isNull()) {
|
||||
emit q->serviceRemoved(service);
|
||||
services.remove(serviceName);
|
||||
updateHostnames();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::onQueryTimeout()
|
||||
{
|
||||
Query query;
|
||||
query.setName(type);
|
||||
query.setType(PTR);
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
|
||||
// TODO: including too many records could cause problems
|
||||
|
||||
// Include PTR records for the target that are already known
|
||||
QList<Record> records;
|
||||
if (cache->lookupRecords(query.name(), PTR, records)) {
|
||||
for (const Record &record : qAsConst(records)) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
queryTimer.start();
|
||||
}
|
||||
|
||||
void BrowserPrivate::onServiceTimeout()
|
||||
{
|
||||
if (ptrTargets.count()) {
|
||||
Message message;
|
||||
for (const QByteArray &target : qAsConst(ptrTargets)) {
|
||||
|
||||
// Add a query for PTR records
|
||||
Query query;
|
||||
query.setName(target);
|
||||
query.setType(PTR);
|
||||
message.addQuery(query);
|
||||
|
||||
// Include PTR records for the target that are already known
|
||||
QList<Record> records;
|
||||
if (cache->lookupRecords(target, PTR, records)) {
|
||||
for (const Record &record : qAsConst(records)) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
ptrTargets.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserPrivate::updateHostnames()
|
||||
{
|
||||
hostnames.clear();
|
||||
|
||||
for (const auto& service : services) {
|
||||
hostnames.insert(service.hostname());
|
||||
}
|
||||
}
|
||||
|
||||
Browser::Browser(AbstractServer *server, const QByteArray &type, Cache *cache, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new BrowserPrivate(this, server, type, cache))
|
||||
{
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_BROWSER_P_H
|
||||
#define QMDNSENGINE_BROWSER_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../include/service.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Browser;
|
||||
class Cache;
|
||||
class Message;
|
||||
class Record;
|
||||
|
||||
class BrowserPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit BrowserPrivate(Browser *browser, AbstractServer *server, const QByteArray &type, Cache *existingCache);
|
||||
|
||||
bool updateService(const QByteArray &fqName);
|
||||
|
||||
AbstractServer *server;
|
||||
QByteArray type;
|
||||
|
||||
Cache *cache;
|
||||
QSet<QByteArray> ptrTargets;
|
||||
QMap<QByteArray, Service> services;
|
||||
QSet<QByteArray> hostnames;
|
||||
|
||||
QTimer queryTimer;
|
||||
QTimer serviceTimer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onShouldQuery(const Record &record);
|
||||
void onRecordExpired(const Record &record);
|
||||
|
||||
void onQueryTimeout();
|
||||
void onServiceTimeout();
|
||||
|
||||
private:
|
||||
void updateHostnames();
|
||||
|
||||
Browser *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_BROWSER_P_H
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QtGlobal>
|
||||
#if(QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
#include <QRandomGenerator>
|
||||
#define USE_QRANDOMGENERATOR
|
||||
#endif
|
||||
|
||||
#include "../include/cache.h"
|
||||
#include "../include/dns.h"
|
||||
|
||||
#include "cache_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
CachePrivate::CachePrivate(Cache *cache)
|
||||
: QObject(cache),
|
||||
q(cache)
|
||||
{
|
||||
connect(&timer, &QTimer::timeout, this, &CachePrivate::onTimeout);
|
||||
|
||||
timer.setSingleShot(true);
|
||||
}
|
||||
|
||||
void CachePrivate::onTimeout()
|
||||
{
|
||||
// Loop through all of the records in the cache, emitting the appropriate
|
||||
// signal when a trigger has passed, determining when the next trigger
|
||||
// will occur, and removing records that have expired
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QDateTime newNextTrigger;
|
||||
|
||||
for (auto i = entries.begin(); i != entries.end();) {
|
||||
|
||||
// Loop through the triggers and remove ones that have already
|
||||
// passed
|
||||
bool shouldQuery = false;
|
||||
for (auto j = i->triggers.begin(); j != i->triggers.end();) {
|
||||
if ((*j) <= now) {
|
||||
shouldQuery = true;
|
||||
j = i->triggers.erase(j);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If triggers remain, determine the next earliest one; if none
|
||||
// remain, the record has expired and should be removed
|
||||
if (i->triggers.length()) {
|
||||
if (newNextTrigger.isNull() || i->triggers.at(0) < newNextTrigger) {
|
||||
newNextTrigger = i->triggers.at(0);
|
||||
}
|
||||
if (shouldQuery) {
|
||||
emit q->shouldQuery(i->record);
|
||||
}
|
||||
++i;
|
||||
} else {
|
||||
emit q->recordExpired(i->record);
|
||||
i = entries.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
// If newNextTrigger contains a value, it will be the time for the next
|
||||
// trigger and the timer should be started again
|
||||
nextTrigger = newNextTrigger;
|
||||
if (!nextTrigger.isNull()) {
|
||||
timer.start(now.msecsTo(nextTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
Cache::Cache(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new CachePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
void Cache::addRecord(const Record &record)
|
||||
{
|
||||
// If a record exists that matches, remove it from the cache; if the TTL
|
||||
// is nonzero, it will be added back to the cache with updated times
|
||||
for (auto i = d->entries.begin(); i != d->entries.end();) {
|
||||
if ((record.flushCache() &&
|
||||
(*i).record.name() == record.name() &&
|
||||
(*i).record.type() == record.type()) ||
|
||||
(*i).record == record) {
|
||||
|
||||
// If the TTL is set to 0, indicate that the record was removed
|
||||
if (record.ttl() == 0) {
|
||||
emit recordExpired((*i).record);
|
||||
}
|
||||
|
||||
i = d->entries.erase(i);
|
||||
|
||||
// No need to continue further if the TTL was set to 0
|
||||
if (record.ttl() == 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the current time to calculate the triggers and add a random offset
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
#ifdef USE_QRANDOMGENERATOR
|
||||
qint64 random = QRandomGenerator::global()->bounded(20);
|
||||
#else
|
||||
qint64 random = qrand() % 20;
|
||||
#endif
|
||||
|
||||
QList<QDateTime> triggers{
|
||||
now.addMSecs(record.ttl() * 500 + random), // 50%
|
||||
now.addMSecs(record.ttl() * 850 + random), // 85%
|
||||
now.addMSecs(record.ttl() * 900 + random), // 90%
|
||||
now.addMSecs(record.ttl() * 950 + random), // 95%
|
||||
now.addSecs(record.ttl())
|
||||
};
|
||||
|
||||
// Append the record and its triggers
|
||||
d->entries.append({record, triggers});
|
||||
|
||||
// Check if the new record's first trigger is earlier than the next
|
||||
// scheduled trigger; if so, restart the timer
|
||||
if (d->nextTrigger.isNull() || triggers.at(0) < d->nextTrigger) {
|
||||
d->nextTrigger = triggers.at(0);
|
||||
d->timer.start(now.msecsTo(d->nextTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
bool Cache::lookupRecord(const QByteArray &name, quint16 type, Record &record) const
|
||||
{
|
||||
QList<Record> records;
|
||||
if (lookupRecords(name, type, records)) {
|
||||
record = records.at(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Cache::lookupRecords(const QByteArray &name, quint16 type, QList<Record> &records) const
|
||||
{
|
||||
bool recordsAdded = false;
|
||||
for (const CachePrivate::Entry &entry : d->entries) {
|
||||
if ((name.isNull() || entry.record.name() == name) &&
|
||||
(type == ANY || entry.record.type() == type)) {
|
||||
records.append(entry.record);
|
||||
recordsAdded = true;
|
||||
}
|
||||
}
|
||||
return recordsAdded;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_CACHE_P_H
|
||||
#define QMDNSENGINE_CACHE_P_H
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../include/record.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Cache;
|
||||
|
||||
class CachePrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Record record;
|
||||
QList<QDateTime> triggers;
|
||||
};
|
||||
|
||||
CachePrivate(Cache *cache);
|
||||
|
||||
QTimer timer;
|
||||
QList<Entry> entries;
|
||||
QDateTime nextTrigger;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Cache *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_CACHE_P_H
|
|
@ -1,379 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QtEndian>
|
||||
|
||||
#include "../include/bitmap.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/query.h"
|
||||
#include "../include/record.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
template<class T>
|
||||
bool parseInteger(const QByteArray &packet, quint16 &offset, T &value)
|
||||
{
|
||||
if (offset + sizeof(T) > static_cast<unsigned int>(packet.length())) {
|
||||
return false; // out-of-bounds
|
||||
}
|
||||
value = qFromBigEndian<T>(reinterpret_cast<const uchar*>(packet.constData() + offset));
|
||||
offset += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void writeInteger(QByteArray &packet, quint16 &offset, T value)
|
||||
{
|
||||
value = qToBigEndian<T>(value);
|
||||
packet.append(reinterpret_cast<const char*>(&value), sizeof(T));
|
||||
offset += sizeof(T);
|
||||
}
|
||||
|
||||
bool parseName(const QByteArray &packet, quint16 &offset, QByteArray &name)
|
||||
{
|
||||
quint16 offsetEnd = 0;
|
||||
quint16 offsetPtr = offset;
|
||||
forever {
|
||||
quint8 nBytes;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes)) {
|
||||
return false;
|
||||
}
|
||||
if (!nBytes) {
|
||||
break;
|
||||
}
|
||||
switch (nBytes & 0xc0) {
|
||||
case 0x00:
|
||||
if (offset + nBytes > packet.length()) {
|
||||
return false; // length exceeds message
|
||||
}
|
||||
name.append(packet.mid(offset, nBytes));
|
||||
name.append('.');
|
||||
offset += nBytes;
|
||||
break;
|
||||
case 0xc0:
|
||||
{
|
||||
quint8 nBytes2;
|
||||
quint16 newOffset;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes2)) {
|
||||
return false;
|
||||
}
|
||||
newOffset = ((nBytes & ~0xc0) << 8) | nBytes2;
|
||||
if (newOffset >= offsetPtr) {
|
||||
return false; // prevent infinite loop
|
||||
}
|
||||
offsetPtr = newOffset;
|
||||
if (!offsetEnd) {
|
||||
offsetEnd = offset;
|
||||
}
|
||||
offset = newOffset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false; // no other types supported
|
||||
}
|
||||
}
|
||||
if (offsetEnd) {
|
||||
offset = offsetEnd;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeName(QByteArray &packet, quint16 &offset, const QByteArray &name, QMap<QByteArray, quint16> &nameMap)
|
||||
{
|
||||
QByteArray fragment = name;
|
||||
if (fragment.endsWith('.')) {
|
||||
fragment.chop(1);
|
||||
}
|
||||
while (fragment.length()) {
|
||||
if (nameMap.contains(fragment)) {
|
||||
writeInteger<quint16>(packet, offset, nameMap.value(fragment) | 0xc000);
|
||||
return;
|
||||
}
|
||||
nameMap.insert(fragment, offset);
|
||||
int index = fragment.indexOf('.');
|
||||
if (index == -1) {
|
||||
index = fragment.length();
|
||||
}
|
||||
writeInteger<quint8>(packet, offset, index);
|
||||
packet.append(fragment.left(index));
|
||||
offset += index;
|
||||
fragment.remove(0, index + 1);
|
||||
}
|
||||
writeInteger<quint8>(packet, offset, 0);
|
||||
}
|
||||
|
||||
bool parseRecord(const QByteArray &packet, quint16 &offset, Record &record)
|
||||
{
|
||||
QByteArray name;
|
||||
quint16 type, class_, dataLen;
|
||||
quint32 ttl;
|
||||
if (!parseName(packet, offset, name) ||
|
||||
!parseInteger<quint16>(packet, offset, type) ||
|
||||
!parseInteger<quint16>(packet, offset, class_) ||
|
||||
!parseInteger<quint32>(packet, offset, ttl) ||
|
||||
!parseInteger<quint16>(packet, offset, dataLen)) {
|
||||
return false;
|
||||
}
|
||||
record.setName(name);
|
||||
record.setType(type);
|
||||
record.setFlushCache(class_ & 0x8000);
|
||||
record.setTtl(ttl);
|
||||
switch (type) {
|
||||
case A:
|
||||
{
|
||||
quint32 ipv4Addr;
|
||||
if (!parseInteger<quint32>(packet, offset, ipv4Addr)) {
|
||||
return false;
|
||||
}
|
||||
record.setAddress(QHostAddress(ipv4Addr));
|
||||
break;
|
||||
}
|
||||
case AAAA:
|
||||
{
|
||||
if (offset + 16 > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
record.setAddress(QHostAddress(
|
||||
reinterpret_cast<const quint8*>(packet.constData() + offset)
|
||||
));
|
||||
offset += 16;
|
||||
break;
|
||||
}
|
||||
case NSEC:
|
||||
{
|
||||
QByteArray nextDomainName;
|
||||
quint8 number;
|
||||
quint8 length;
|
||||
if (!parseName(packet, offset, nextDomainName) ||
|
||||
!parseInteger<quint8>(packet, offset, number) ||
|
||||
!parseInteger<quint8>(packet, offset, length) ||
|
||||
number != 0 ||
|
||||
offset + length > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
Bitmap bitmap;
|
||||
bitmap.setData(length, reinterpret_cast<const quint8*>(packet.constData() + offset));
|
||||
record.setNextDomainName(nextDomainName);
|
||||
record.setBitmap(bitmap);
|
||||
offset += length;
|
||||
break;
|
||||
}
|
||||
case PTR:
|
||||
{
|
||||
QByteArray target;
|
||||
if (!parseName(packet, offset, target)) {
|
||||
return false;
|
||||
}
|
||||
record.setTarget(target);
|
||||
break;
|
||||
}
|
||||
case SRV:
|
||||
{
|
||||
quint16 priority, weight, port;
|
||||
QByteArray target;
|
||||
if (!parseInteger<quint16>(packet, offset, priority) ||
|
||||
!parseInteger<quint16>(packet, offset, weight) ||
|
||||
!parseInteger<quint16>(packet, offset, port) ||
|
||||
!parseName(packet, offset, target)) {
|
||||
return false;
|
||||
}
|
||||
record.setPriority(priority);
|
||||
record.setWeight(weight);
|
||||
record.setPort(port);
|
||||
record.setTarget(target);
|
||||
break;
|
||||
}
|
||||
case TXT:
|
||||
{
|
||||
quint16 start = offset;
|
||||
while (offset < start + dataLen) {
|
||||
quint8 nBytes;
|
||||
if (!parseInteger<quint8>(packet, offset, nBytes) ||
|
||||
offset + nBytes > packet.length()) {
|
||||
return false;
|
||||
}
|
||||
if (nBytes == 0) {
|
||||
break;
|
||||
}
|
||||
QByteArray attr(packet.constData() + offset, nBytes);
|
||||
offset += nBytes;
|
||||
int splitIndex = attr.indexOf('=');
|
||||
if (splitIndex == -1) {
|
||||
record.addAttribute(attr, QByteArray());
|
||||
} else {
|
||||
record.addAttribute(attr.left(splitIndex), attr.mid(splitIndex + 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
offset += dataLen;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeRecord(QByteArray &packet, quint16 &offset, Record &record, QMap<QByteArray, quint16> &nameMap)
|
||||
{
|
||||
writeName(packet, offset, record.name(), nameMap);
|
||||
writeInteger<quint16>(packet, offset, record.type());
|
||||
writeInteger<quint16>(packet, offset, record.flushCache() ? 0x8001 : 1);
|
||||
writeInteger<quint32>(packet, offset, record.ttl());
|
||||
offset += 2;
|
||||
QByteArray data;
|
||||
switch (record.type()) {
|
||||
case A:
|
||||
writeInteger<quint32>(data, offset, record.address().toIPv4Address());
|
||||
break;
|
||||
case AAAA:
|
||||
{
|
||||
Q_IPV6ADDR ipv6Addr = record.address().toIPv6Address();
|
||||
data.append(reinterpret_cast<const char*>(&ipv6Addr), sizeof(Q_IPV6ADDR));
|
||||
offset += data.length();
|
||||
break;
|
||||
}
|
||||
case NSEC:
|
||||
{
|
||||
quint8 length = record.bitmap().length();
|
||||
writeName(data, offset, record.nextDomainName(), nameMap);
|
||||
writeInteger<quint8>(data, offset, 0);
|
||||
writeInteger<quint8>(data, offset, length);
|
||||
data.append(reinterpret_cast<const char*>(record.bitmap().data()), length);
|
||||
offset += length;
|
||||
break;
|
||||
}
|
||||
case PTR:
|
||||
writeName(data, offset, record.target(), nameMap);
|
||||
break;
|
||||
case SRV:
|
||||
writeInteger<quint16>(data, offset, record.priority());
|
||||
writeInteger<quint16>(data, offset, record.weight());
|
||||
writeInteger<quint16>(data, offset, record.port());
|
||||
writeName(data, offset, record.target(), nameMap);
|
||||
break;
|
||||
case TXT:
|
||||
if (!record.attributes().count()) {
|
||||
writeInteger<quint8>(data, offset, 0);
|
||||
break;
|
||||
}
|
||||
for (auto i = record.attributes().constBegin(); i != record.attributes().constEnd(); ++i) {
|
||||
QByteArray entry = i.value().isNull() ? i.key() : i.key() + "=" + i.value();
|
||||
writeInteger<quint8>(data, offset, entry.length());
|
||||
data.append(entry);
|
||||
offset += entry.length();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
offset -= 2;
|
||||
writeInteger<quint16>(packet, offset, data.length());
|
||||
packet.append(data);
|
||||
}
|
||||
|
||||
bool fromPacket(const QByteArray &packet, Message &message)
|
||||
{
|
||||
quint16 offset = 0;
|
||||
quint16 transactionId, flags, nQuestion, nAnswer, nAuthority, nAdditional;
|
||||
if (!parseInteger<quint16>(packet, offset, transactionId) ||
|
||||
!parseInteger<quint16>(packet, offset, flags) ||
|
||||
!parseInteger<quint16>(packet, offset, nQuestion) ||
|
||||
!parseInteger<quint16>(packet, offset, nAnswer) ||
|
||||
!parseInteger<quint16>(packet, offset, nAuthority) ||
|
||||
!parseInteger<quint16>(packet, offset, nAdditional)) {
|
||||
return false;
|
||||
}
|
||||
message.setTransactionId(transactionId);
|
||||
message.setResponse(flags & 0x8400);
|
||||
message.setTruncated(flags & 0x0200);
|
||||
for (int i = 0; i < nQuestion; ++i) {
|
||||
QByteArray name;
|
||||
quint16 type, class_;
|
||||
if (!parseName(packet, offset, name) ||
|
||||
!parseInteger<quint16>(packet, offset, type) ||
|
||||
!parseInteger<quint16>(packet, offset, class_)) {
|
||||
return false;
|
||||
}
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(type);
|
||||
query.setUnicastResponse(class_ & 0x8000);
|
||||
message.addQuery(query);
|
||||
}
|
||||
quint16 nRecord = nAnswer + nAuthority + nAdditional;
|
||||
for (int i = 0; i < nRecord; ++i) {
|
||||
Record record;
|
||||
if (!parseRecord(packet, offset, record)) {
|
||||
return false;
|
||||
}
|
||||
message.addRecord(record);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void toPacket(const Message &message, QByteArray &packet)
|
||||
{
|
||||
quint16 offset = 0;
|
||||
quint16 flags = (message.isResponse() ? 0x8400 : 0) |
|
||||
(message.isTruncated() ? 0x200 : 0);
|
||||
|
||||
qDebug() << "Flags set in toPacket:" << QString::number(flags, 16);
|
||||
|
||||
writeInteger<quint16>(packet, offset, message.transactionId());
|
||||
writeInteger<quint16>(packet, offset, flags);
|
||||
writeInteger<quint16>(packet, offset, message.queries().length());
|
||||
writeInteger<quint16>(packet, offset, message.records().length());
|
||||
writeInteger<quint16>(packet, offset, 0);
|
||||
writeInteger<quint16>(packet, offset, 0);
|
||||
QMap<QByteArray, quint16> nameMap;
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
writeName(packet, offset, query.name(), nameMap);
|
||||
writeInteger<quint16>(packet, offset, query.type());
|
||||
writeInteger<quint16>(packet, offset, query.unicastResponse() ? 0x8001 : 1);
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (Record record : records) {
|
||||
writeRecord(packet, offset, record, nameMap);
|
||||
}
|
||||
}
|
||||
|
||||
QString typeName(quint16 type)
|
||||
{
|
||||
switch (type) {
|
||||
case A: return "A";
|
||||
case AAAA: return "AAAA";
|
||||
case ANY: return "ANY";
|
||||
case NSEC: return "NSEC";
|
||||
case PTR: return "PTR";
|
||||
case SRV: return "SRV";
|
||||
case TXT: return "TXT";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QHostInfo>
|
||||
#include <QNetworkAddressEntry>
|
||||
#include <QNetworkInterface>
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/hostname.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/query.h"
|
||||
#include "../include/record.h"
|
||||
|
||||
#include "hostname_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
HostnamePrivate::HostnamePrivate(Hostname *hostname, AbstractServer *server)
|
||||
: QObject(hostname),
|
||||
server(server),
|
||||
q(hostname)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &HostnamePrivate::onMessageReceived);
|
||||
connect(®istrationTimer, &QTimer::timeout, this, &HostnamePrivate::onRegistrationTimeout);
|
||||
connect(&rebroadcastTimer, &QTimer::timeout, this, &HostnamePrivate::onRebroadcastTimeout);
|
||||
|
||||
registrationTimer.setInterval(2 * 1000);
|
||||
registrationTimer.setSingleShot(true);
|
||||
|
||||
rebroadcastTimer.setInterval(30 * 60 * 1000);
|
||||
rebroadcastTimer.setSingleShot(true);
|
||||
|
||||
// Immediately assert the hostname
|
||||
onRebroadcastTimeout();
|
||||
}
|
||||
|
||||
void HostnamePrivate::assertHostname()
|
||||
{
|
||||
// Begin with the local hostname and replace any "." with "-" (I'm looking
|
||||
// at you, macOS)
|
||||
QByteArray localHostname = QHostInfo::localHostName().toUtf8();
|
||||
localHostname = localHostname.replace('.', '-');
|
||||
|
||||
// If the suffix > 1, then append a "-2", "-3", etc. to the hostname to
|
||||
// aid in finding one that is unique and not in use
|
||||
hostname = (hostnameSuffix == 1 ? localHostname:
|
||||
localHostname + "-" + QByteArray::number(hostnameSuffix)) + ".local.";
|
||||
|
||||
// Compose a query for A and AAAA records matching the hostname
|
||||
Query ipv4Query;
|
||||
ipv4Query.setName(hostname);
|
||||
ipv4Query.setType(A);
|
||||
Query ipv6Query;
|
||||
ipv6Query.setName(hostname);
|
||||
ipv6Query.setType(AAAA);
|
||||
Message message;
|
||||
message.addQuery(ipv4Query);
|
||||
message.addQuery(ipv6Query);
|
||||
|
||||
server->sendMessageToAll(message);
|
||||
|
||||
// If no reply is received after two seconds, the hostname is available
|
||||
registrationTimer.start();
|
||||
}
|
||||
|
||||
bool HostnamePrivate::generateRecord(const QHostAddress &srcAddress, quint16 type, Record &record)
|
||||
{
|
||||
// Attempt to find the interface that corresponds with the provided
|
||||
// address and determine this device's address from the interface
|
||||
|
||||
const auto interfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &networkInterface : interfaces) {
|
||||
const auto entries = networkInterface.addressEntries();
|
||||
for (const QNetworkAddressEntry &entry : entries) {
|
||||
if (srcAddress.isInSubnet(entry.ip(), entry.prefixLength())) {
|
||||
for (const QNetworkAddressEntry &newEntry : entries) {
|
||||
QHostAddress address = newEntry.ip();
|
||||
if ((address.protocol() == QAbstractSocket::IPv4Protocol && type == A) ||
|
||||
(address.protocol() == QAbstractSocket::IPv6Protocol && type == AAAA)) {
|
||||
record.setName(hostname);
|
||||
record.setType(type);
|
||||
record.setAddress(address);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HostnamePrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (message.isResponse()) {
|
||||
if (hostnameRegistered) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if ((record.type() == A || record.type() == AAAA) && record.name() == hostname) {
|
||||
++hostnameSuffix;
|
||||
assertHostname();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hostnameRegistered) {
|
||||
return;
|
||||
}
|
||||
Message reply;
|
||||
reply.reply(message);
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
if ((query.type() == A || query.type() == AAAA) && query.name() == hostname) {
|
||||
Record record;
|
||||
if (generateRecord(message.address(), query.type(), record)) {
|
||||
reply.addRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reply.records().count()) {
|
||||
server->sendMessage(reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HostnamePrivate::onRegistrationTimeout()
|
||||
{
|
||||
hostnameRegistered = true;
|
||||
if (hostname != hostnamePrev) {
|
||||
emit q->hostnameChanged(hostname);
|
||||
}
|
||||
|
||||
// Re-assert the hostname in half an hour
|
||||
rebroadcastTimer.start();
|
||||
}
|
||||
|
||||
void HostnamePrivate::onRebroadcastTimeout()
|
||||
{
|
||||
hostnamePrev = hostname;
|
||||
hostnameRegistered = false;
|
||||
hostnameSuffix = 1;
|
||||
|
||||
assertHostname();
|
||||
}
|
||||
|
||||
Hostname::Hostname(AbstractServer *server, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new HostnamePrivate(this, server))
|
||||
{
|
||||
}
|
||||
|
||||
bool Hostname::isRegistered() const
|
||||
{
|
||||
return d->hostnameRegistered;
|
||||
}
|
||||
|
||||
QByteArray Hostname::hostname() const
|
||||
{
|
||||
return d->hostname;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_HOSTNAME_P_H
|
||||
#define QMDNSENGINE_HOSTNAME_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class QHostAddress;
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Hostname;
|
||||
class Message;
|
||||
class Record;
|
||||
|
||||
class HostnamePrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
HostnamePrivate(Hostname *hostname, AbstractServer *server);
|
||||
|
||||
void assertHostname();
|
||||
bool generateRecord(const QHostAddress &srcAddress, quint16 type, Record &record);
|
||||
|
||||
AbstractServer *server;
|
||||
|
||||
QByteArray hostnamePrev;
|
||||
QByteArray hostname;
|
||||
bool hostnameRegistered;
|
||||
int hostnameSuffix;
|
||||
|
||||
QTimer registrationTimer;
|
||||
QTimer rebroadcastTimer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onRegistrationTimeout();
|
||||
void onRebroadcastTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Hostname *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_HOSTNAME_P_H
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/mdns.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
const quint16 MdnsPort = 5353;
|
||||
const QHostAddress MdnsIpv4Address("224.0.0.251");
|
||||
const QHostAddress MdnsIpv6Address("ff02::fb");
|
||||
const QByteArray MdnsBrowseType("_services._dns-sd._udp.local.");
|
||||
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/mdns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/query.h"
|
||||
#include "../include/record.h"
|
||||
|
||||
#include "message_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
MessagePrivate::MessagePrivate()
|
||||
: port(0),
|
||||
transactionId(0),
|
||||
isResponse(false),
|
||||
isTruncated(false)
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message()
|
||||
: d(new MessagePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Message::Message(const Message &other)
|
||||
: d(new MessagePrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Message &Message::operator=(const Message &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QHostAddress Message::address() const
|
||||
{
|
||||
return d->address;
|
||||
}
|
||||
|
||||
void Message::setAddress(const QHostAddress &address)
|
||||
{
|
||||
d->address = address;
|
||||
}
|
||||
|
||||
quint16 Message::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Message::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
quint16 Message::transactionId() const
|
||||
{
|
||||
return d->transactionId;
|
||||
}
|
||||
|
||||
void Message::setTransactionId(quint16 transactionId)
|
||||
{
|
||||
d->transactionId = transactionId;
|
||||
}
|
||||
|
||||
bool Message::isResponse() const
|
||||
{
|
||||
return d->isResponse;
|
||||
}
|
||||
|
||||
void Message::setResponse(bool isResponse)
|
||||
{
|
||||
d->isResponse = isResponse;
|
||||
}
|
||||
|
||||
bool Message::isTruncated() const
|
||||
{
|
||||
return d->isTruncated;
|
||||
}
|
||||
|
||||
void Message::setTruncated(bool isTruncated)
|
||||
{
|
||||
d->isTruncated = isTruncated;
|
||||
}
|
||||
|
||||
QList<Query> Message::queries() const
|
||||
{
|
||||
return d->queries;
|
||||
}
|
||||
|
||||
void Message::addQuery(const Query &query)
|
||||
{
|
||||
d->queries.append(query);
|
||||
}
|
||||
|
||||
QList<Record> Message::records() const
|
||||
{
|
||||
return d->records;
|
||||
}
|
||||
|
||||
void Message::addRecord(const Record &record)
|
||||
{
|
||||
d->records.append(record);
|
||||
}
|
||||
|
||||
void Message::reply(const Message &other)
|
||||
{
|
||||
if (other.port() == MdnsPort) {
|
||||
if (other.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
setAddress(MdnsIpv4Address);
|
||||
} else {
|
||||
setAddress(MdnsIpv6Address);
|
||||
}
|
||||
} else {
|
||||
setAddress(other.address());
|
||||
}
|
||||
setPort(other.port());
|
||||
setTransactionId(other.transactionId());
|
||||
setResponse(true);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_MESSAGE_P_H
|
||||
#define QMDNSENGINE_MESSAGE_P_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QList>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Query;
|
||||
class Record;
|
||||
|
||||
class MessagePrivate
|
||||
{
|
||||
public:
|
||||
|
||||
MessagePrivate();
|
||||
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
quint16 transactionId;
|
||||
bool isResponse;
|
||||
bool isTruncated;
|
||||
QList<Query> queries;
|
||||
QList<Record> records;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_MESSAGE_P_H
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/prober.h"
|
||||
#include "../include/query.h"
|
||||
|
||||
#include "prober_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ProberPrivate::ProberPrivate(Prober *prober, AbstractServer *server, const Record &record)
|
||||
: QObject(prober),
|
||||
server(server),
|
||||
confirmed(false),
|
||||
proposedRecord(record),
|
||||
suffix(1),
|
||||
q(prober)
|
||||
{
|
||||
// All records should contain at least one "."
|
||||
int index = record.name().indexOf('.');
|
||||
name = record.name().left(index);
|
||||
type = record.name().mid(index);
|
||||
|
||||
connect(server, &AbstractServer::messageReceived, this, &ProberPrivate::onMessageReceived);
|
||||
connect(&timer, &QTimer::timeout, this, &ProberPrivate::onTimeout);
|
||||
|
||||
timer.setSingleShot(true);
|
||||
|
||||
assertRecord();
|
||||
}
|
||||
|
||||
void ProberPrivate::assertRecord()
|
||||
{
|
||||
// Use the current suffix to set the name of the proposed record
|
||||
QString tmpName = suffix == 1
|
||||
? QString("%1%2").arg(name, type.constData())
|
||||
: QString("%1-%2%3").arg(name.constData(), QByteArray::number(suffix), type);
|
||||
|
||||
proposedRecord.setName(tmpName.toUtf8());
|
||||
|
||||
// Broadcast a query for the proposed name (using an ANY query) and
|
||||
// include the proposed record in the query
|
||||
Query query;
|
||||
query.setName(proposedRecord.name());
|
||||
query.setType(ANY);
|
||||
Message message;
|
||||
message.addQuery(query);
|
||||
message.addRecord(proposedRecord);
|
||||
server->sendMessageToAll(message);
|
||||
// Wait two seconds to confirm it is unique
|
||||
timer.stop();
|
||||
timer.start(2 * 1000);
|
||||
}
|
||||
|
||||
void ProberPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
// If the response matches the proposed record, increment the suffix and
|
||||
// try with the new name
|
||||
//if (confirmed || !message.isResponse()) {
|
||||
if (confirmed) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record.name() == proposedRecord.name() && record.type() == proposedRecord.type()) {
|
||||
qDebug() << "Conflict detected for name:" << proposedRecord.name() << "with type:" << record.type();
|
||||
++suffix;
|
||||
assertRecord();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProberPrivate::onTimeout()
|
||||
{
|
||||
confirmed = true;
|
||||
emit q->nameConfirmed(proposedRecord.name());
|
||||
}
|
||||
|
||||
Prober::Prober(AbstractServer *server, const Record &record, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ProberPrivate(this, server, record))
|
||||
{
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROBER_P_H
|
||||
#define QMDNSENGINE_PROBER_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../include/record.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Message;
|
||||
class Prober;
|
||||
|
||||
class ProberPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ProberPrivate(Prober *prober, AbstractServer *server, const Record &record);
|
||||
|
||||
void assertRecord();
|
||||
|
||||
AbstractServer *server;
|
||||
QTimer timer;
|
||||
|
||||
bool confirmed;
|
||||
|
||||
Record proposedRecord;
|
||||
QByteArray name;
|
||||
QByteArray type;
|
||||
int suffix;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Prober *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROBER_P_H
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/hostname.h"
|
||||
#include "../include/mdns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/prober.h"
|
||||
#include "../include/provider.h"
|
||||
#include "../include/query.h"
|
||||
|
||||
#include "provider_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ProviderPrivate::ProviderPrivate(QObject *parent, AbstractServer *server, Hostname *hostname)
|
||||
: QObject(parent),
|
||||
server(server),
|
||||
hostname(hostname),
|
||||
prober(nullptr),
|
||||
initialized(false),
|
||||
confirmed(false)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &ProviderPrivate::onMessageReceived);
|
||||
connect(hostname, &Hostname::hostnameChanged, this, &ProviderPrivate::onHostnameChanged);
|
||||
|
||||
browsePtrProposed.setName(MdnsBrowseType);
|
||||
browsePtrProposed.setType(PTR);
|
||||
ptrProposed.setType(PTR);
|
||||
srvProposed.setType(SRV);
|
||||
txtProposed.setType(TXT);
|
||||
}
|
||||
|
||||
ProviderPrivate::~ProviderPrivate()
|
||||
{
|
||||
if (confirmed) {
|
||||
farewell();
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderPrivate::announce()
|
||||
{
|
||||
// Broadcast a message with each of the records
|
||||
Message message;
|
||||
message.setResponse(true);
|
||||
message.addRecord(ptrRecord);
|
||||
message.addRecord(srvRecord);
|
||||
message.addRecord(txtRecord);
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void ProviderPrivate::confirm()
|
||||
{
|
||||
// Confirm that the desired name is unique through probing
|
||||
|
||||
if (prober) {
|
||||
delete prober;
|
||||
}
|
||||
prober = new Prober(server, srvProposed, this);
|
||||
|
||||
connect(prober, &Prober::nameConfirmed, [this](const QByteArray &name) {
|
||||
// If existing records were confirmed, indicate that they are no
|
||||
// longer valid
|
||||
if (confirmed) {
|
||||
farewell();
|
||||
} else {
|
||||
confirmed = true;
|
||||
}
|
||||
// Update the proposed records
|
||||
ptrProposed.setTarget(name);
|
||||
srvProposed.setName(name);
|
||||
txtProposed.setName(name);
|
||||
|
||||
// Publish the proposed records and announce them
|
||||
publish();
|
||||
|
||||
delete prober;
|
||||
prober = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
void ProviderPrivate::farewell()
|
||||
{
|
||||
// Send a message indicating that the existing records are no longer valid
|
||||
// by setting their TTL to 0
|
||||
|
||||
ptrRecord.setTtl(0);
|
||||
srvRecord.setTtl(0);
|
||||
txtRecord.setTtl(0);
|
||||
announce();
|
||||
}
|
||||
|
||||
void ProviderPrivate::publish()
|
||||
{
|
||||
// Copy the proposed records over and announce them
|
||||
browsePtrRecord = browsePtrProposed;
|
||||
ptrRecord = ptrProposed;
|
||||
srvRecord = srvProposed;
|
||||
txtRecord = txtProposed;
|
||||
announce();
|
||||
|
||||
}
|
||||
|
||||
void ProviderPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!confirmed || message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
//qDebug() << "Failed to start server. Error:" << server->errorString();
|
||||
bool sendBrowsePtr = false;
|
||||
bool sendPtr = false;
|
||||
bool sendSrv = false;
|
||||
bool sendTxt = false;
|
||||
|
||||
// Determine which records to send based on the queries
|
||||
const auto queries = message.queries();
|
||||
for (const Query &query : queries) {
|
||||
if (query.type() == PTR && query.name() == MdnsBrowseType) {
|
||||
sendBrowsePtr = true;
|
||||
} else if (query.type() == PTR && query.name() == ptrRecord.name()) {
|
||||
sendPtr = true;
|
||||
} else if (query.type() == SRV && query.name() == srvRecord.name()) {
|
||||
sendSrv = true;
|
||||
} else if (query.type() == TXT && query.name() == txtRecord.name()) {
|
||||
sendTxt = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove records to send if they are already known
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record == ptrRecord) {
|
||||
sendPtr = false;
|
||||
} else if (record == srvRecord) {
|
||||
sendSrv = false;
|
||||
} else if (record == txtRecord) {
|
||||
sendTxt = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Include the SRV and TXT if the PTR is being sent
|
||||
if (sendPtr) {
|
||||
sendSrv = sendTxt = true;
|
||||
}
|
||||
|
||||
// If any records should be sent, compose a message reply
|
||||
if (sendBrowsePtr || sendPtr || sendSrv || sendTxt) {
|
||||
Message reply;
|
||||
reply.reply(message);
|
||||
if (sendBrowsePtr) {
|
||||
reply.addRecord(browsePtrRecord);
|
||||
}
|
||||
if (sendPtr) {
|
||||
reply.addRecord(ptrRecord);
|
||||
}
|
||||
if (sendSrv) {
|
||||
reply.addRecord(srvRecord);
|
||||
}
|
||||
if (sendTxt) {
|
||||
reply.addRecord(txtRecord);
|
||||
}
|
||||
server->sendMessage(reply);
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderPrivate::onHostnameChanged(const QByteArray &newHostname)
|
||||
{
|
||||
// Update the proposed SRV record
|
||||
srvProposed.setTarget(newHostname);
|
||||
|
||||
// If initialized, confirm the record
|
||||
if (initialized) {
|
||||
confirm();
|
||||
}
|
||||
}
|
||||
|
||||
Provider::Provider(AbstractServer *server, Hostname *hostname, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ProviderPrivate(this, server, hostname))
|
||||
{
|
||||
}
|
||||
|
||||
void Provider::update(const Service &service)
|
||||
{
|
||||
d->initialized = true;
|
||||
|
||||
// Clean the service name
|
||||
QByteArray serviceName = service.name();
|
||||
serviceName = serviceName.replace('.', '-');
|
||||
|
||||
// Update the proposed records
|
||||
QByteArray fqName = serviceName + "." + service.type();
|
||||
d->browsePtrProposed.setTarget(service.type());
|
||||
d->ptrProposed.setName(service.type());
|
||||
d->ptrProposed.setTarget(fqName);
|
||||
d->srvProposed.setName(fqName);
|
||||
d->srvProposed.setPort(service.port());
|
||||
d->srvProposed.setTarget(d->hostname->hostname());
|
||||
d->txtProposed.setName(fqName);
|
||||
d->txtProposed.setAttributes(service.attributes());
|
||||
// Assuming a valid hostname exists, check to see if the new service uses
|
||||
// a different name - if so, it must first be confirmed
|
||||
if (d->hostname == nullptr) {
|
||||
qDebug() << "hostname is nullptr";
|
||||
return;
|
||||
}
|
||||
bool registered = d->hostname->isRegistered();
|
||||
if(registered) {
|
||||
// 不确认服务名称,直接进行广播
|
||||
d->publish();
|
||||
//if (d->hostname->isRegistered()) {
|
||||
/*if (!d->confirmed || fqName != d->srvRecord.name()) {
|
||||
qDebug() << "confirm()";
|
||||
d->confirm();
|
||||
} else {
|
||||
qDebug() << "publish()";
|
||||
d->publish();
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_PROVIDER_P_H
|
||||
#define QMDNSENGINE_PROVIDER_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "../include/record.h"
|
||||
#include "../include/service.h"
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Hostname;
|
||||
class Message;
|
||||
class Prober;
|
||||
|
||||
class ProviderPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
ProviderPrivate(QObject *parent, AbstractServer *server, Hostname *hostname);
|
||||
virtual ~ProviderPrivate();
|
||||
|
||||
void announce();
|
||||
void confirm();
|
||||
void farewell();
|
||||
void publish();
|
||||
|
||||
AbstractServer *server;
|
||||
Hostname *hostname;
|
||||
Prober *prober;
|
||||
|
||||
Service service;
|
||||
bool initialized;
|
||||
bool confirmed;
|
||||
|
||||
Record browsePtrRecord;
|
||||
Record ptrRecord;
|
||||
Record srvRecord;
|
||||
Record txtRecord;
|
||||
|
||||
Record browsePtrProposed;
|
||||
Record ptrProposed;
|
||||
Record srvProposed;
|
||||
Record txtProposed;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onHostnameChanged(const QByteArray &hostname);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_PROVIDER_P_H
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "../include/dns.h"
|
||||
#include "../include/query.h"
|
||||
|
||||
#include "query_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
QueryPrivate::QueryPrivate()
|
||||
: type(0),
|
||||
unicastResponse(false)
|
||||
{
|
||||
}
|
||||
|
||||
Query::Query()
|
||||
: d(new QueryPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Query::Query(const Query &other)
|
||||
: d(new QueryPrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Query &Query::operator=(const Query &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Query::~Query()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Query::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Query::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
quint16 Query::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Query::setType(quint16 type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
bool Query::unicastResponse() const
|
||||
{
|
||||
return d->unicastResponse;
|
||||
}
|
||||
|
||||
void Query::setUnicastResponse(bool unicastResponse)
|
||||
{
|
||||
d->unicastResponse = unicastResponse;
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug dbg, const Query &query)
|
||||
{
|
||||
QDebugStateSaver saver(dbg);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
dbg.noquote().nospace() << "Query(" << typeName(query.type()) << " " << query.name() << ")";
|
||||
|
||||
return dbg;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_QUERY_P_H
|
||||
#define QMDNSENGINE_QUERY_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class QueryPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
QueryPrivate();
|
||||
|
||||
QByteArray name;
|
||||
quint16 type;
|
||||
bool unicastResponse;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_QUERY_P_H
|
|
@ -1,218 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "../include/dns.h"
|
||||
#include "../include/record.h"
|
||||
|
||||
#include "record_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
RecordPrivate::RecordPrivate()
|
||||
: type(0),
|
||||
flushCache(false),
|
||||
ttl(3600),
|
||||
priority(0),
|
||||
weight(0),
|
||||
port(0)
|
||||
{
|
||||
}
|
||||
|
||||
Record::Record()
|
||||
: d(new RecordPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Record::Record(const Record &other)
|
||||
: d(new RecordPrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Record &Record::operator=(const Record &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Record::operator==(const Record &other) const
|
||||
{
|
||||
return d->name == other.d->name &&
|
||||
d->type == other.d->type &&
|
||||
d->address == other.d->address &&
|
||||
d->target == other.d->target &&
|
||||
d->nextDomainName == other.d->nextDomainName &&
|
||||
d->priority == other.d->priority &&
|
||||
d->weight == other.d->weight &&
|
||||
d->port == other.d->port &&
|
||||
d->attributes == other.d->attributes &&
|
||||
d->bitmap == other.d->bitmap;
|
||||
}
|
||||
|
||||
bool Record::operator!=(const Record &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
Record::~Record()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Record::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Record::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
quint16 Record::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Record::setType(quint16 type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
bool Record::flushCache() const
|
||||
{
|
||||
return d->flushCache;
|
||||
}
|
||||
|
||||
void Record::setFlushCache(bool flushCache)
|
||||
{
|
||||
d->flushCache = flushCache;
|
||||
}
|
||||
|
||||
quint32 Record::ttl() const
|
||||
{
|
||||
return d->ttl;
|
||||
}
|
||||
|
||||
void Record::setTtl(quint32 ttl)
|
||||
{
|
||||
d->ttl = ttl;
|
||||
}
|
||||
|
||||
QHostAddress Record::address() const
|
||||
{
|
||||
return d->address;
|
||||
}
|
||||
|
||||
void Record::setAddress(const QHostAddress &address)
|
||||
{
|
||||
d->address = address;
|
||||
}
|
||||
|
||||
QByteArray Record::target() const
|
||||
{
|
||||
return d->target;
|
||||
}
|
||||
|
||||
void Record::setTarget(const QByteArray &target)
|
||||
{
|
||||
d->target = target;
|
||||
}
|
||||
|
||||
QByteArray Record::nextDomainName() const
|
||||
{
|
||||
return d->nextDomainName;
|
||||
}
|
||||
|
||||
void Record::setNextDomainName(const QByteArray &nextDomainName)
|
||||
{
|
||||
d->nextDomainName = nextDomainName;
|
||||
}
|
||||
|
||||
quint16 Record::priority() const
|
||||
{
|
||||
return d->priority;
|
||||
}
|
||||
|
||||
void Record::setPriority(quint16 priority)
|
||||
{
|
||||
d->priority = priority;
|
||||
}
|
||||
|
||||
quint16 Record::weight() const
|
||||
{
|
||||
return d->weight;
|
||||
}
|
||||
|
||||
void Record::setWeight(quint16 weight)
|
||||
{
|
||||
d->weight = weight;
|
||||
}
|
||||
|
||||
quint16 Record::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Record::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
QMap<QByteArray, QByteArray> Record::attributes() const
|
||||
{
|
||||
return d->attributes;
|
||||
}
|
||||
|
||||
void Record::setAttributes(const QMap<QByteArray, QByteArray> &attributes)
|
||||
{
|
||||
d->attributes = attributes;
|
||||
}
|
||||
|
||||
void Record::addAttribute(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
d->attributes.insert(key, value);
|
||||
}
|
||||
|
||||
Bitmap Record::bitmap() const
|
||||
{
|
||||
return d->bitmap;
|
||||
}
|
||||
|
||||
void Record::setBitmap(const Bitmap &bitmap)
|
||||
{
|
||||
d->bitmap = bitmap;
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug dbg, const Record &record)
|
||||
{
|
||||
QDebugStateSaver saver(dbg);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
dbg.noquote().nospace() << "Record(" << typeName(record.type()) << " " << record.name() << ")";
|
||||
|
||||
return dbg;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RECORD_P_H
|
||||
#define QMDNSENGINE_RECORD_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHostAddress>
|
||||
#include <QMap>
|
||||
|
||||
#include "../include/bitmap.h"
|
||||
|
||||
namespace QMdnsEngine {
|
||||
|
||||
class RecordPrivate
|
||||
{
|
||||
public:
|
||||
|
||||
RecordPrivate();
|
||||
|
||||
QByteArray name;
|
||||
quint16 type;
|
||||
bool flushCache;
|
||||
quint32 ttl;
|
||||
|
||||
QHostAddress address;
|
||||
QByteArray target;
|
||||
QByteArray nextDomainName;
|
||||
quint16 priority;
|
||||
quint16 weight;
|
||||
quint16 port;
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
Bitmap bitmap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RECORD_P_H
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "../include/abstractserver.h"
|
||||
#include "../include/dns.h"
|
||||
#include "../include/cache.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/query.h"
|
||||
#include "../include/record.h"
|
||||
#include "../include/resolver.h"
|
||||
|
||||
#include "resolver_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ResolverPrivate::ResolverPrivate(Resolver *resolver, AbstractServer *server, const QByteArray &name, Cache *cache)
|
||||
: QObject(resolver),
|
||||
server(server),
|
||||
name(name),
|
||||
cache(cache ? cache : new Cache(this)),
|
||||
q(resolver)
|
||||
{
|
||||
connect(server, &AbstractServer::messageReceived, this, &ResolverPrivate::onMessageReceived);
|
||||
connect(&timer, &QTimer::timeout, this, &ResolverPrivate::onTimeout);
|
||||
|
||||
// Query for new records
|
||||
query();
|
||||
|
||||
// Pull the existing records from the cache
|
||||
timer.setSingleShot(true);
|
||||
timer.start(0);
|
||||
}
|
||||
|
||||
QList<Record> ResolverPrivate::existing() const
|
||||
{
|
||||
QList<Record> records;
|
||||
cache->lookupRecords(name, A, records);
|
||||
cache->lookupRecords(name, AAAA, records);
|
||||
return records;
|
||||
}
|
||||
|
||||
void ResolverPrivate::query() const
|
||||
{
|
||||
Message message;
|
||||
|
||||
// Add a query for A and AAAA records
|
||||
Query query;
|
||||
query.setName(name);
|
||||
query.setType(A);
|
||||
message.addQuery(query);
|
||||
query.setType(AAAA);
|
||||
message.addQuery(query);
|
||||
|
||||
// Add existing (known) records to the query
|
||||
const auto records = existing();
|
||||
for (const Record &record : records) {
|
||||
message.addRecord(record);
|
||||
}
|
||||
|
||||
// Send the query
|
||||
server->sendMessageToAll(message);
|
||||
}
|
||||
|
||||
void ResolverPrivate::onMessageReceived(const Message &message)
|
||||
{
|
||||
if (!message.isResponse()) {
|
||||
return;
|
||||
}
|
||||
const auto records = message.records();
|
||||
for (const Record &record : records) {
|
||||
if (record.name() == name && (record.type() == A || record.type() == AAAA)) {
|
||||
cache->addRecord(record);
|
||||
if (!addresses.contains(record.address())) {
|
||||
emit q->resolved(record.address());
|
||||
addresses.insert(record.address());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResolverPrivate::onTimeout()
|
||||
{
|
||||
const auto records = existing();
|
||||
for (const Record &record : records) {
|
||||
emit q->resolved(record.address());
|
||||
}
|
||||
}
|
||||
|
||||
Resolver::Resolver(AbstractServer *server, const QByteArray &name, Cache *cache, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new ResolverPrivate(this, server, name, cache))
|
||||
{
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_RESOLVER_P_H
|
||||
#define QMDNSENGINE_RESOLVER_P_H
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class AbstractServer;
|
||||
class Cache;
|
||||
class Message;
|
||||
class Record;
|
||||
class Resolver;
|
||||
|
||||
class ResolverPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ResolverPrivate(Resolver *resolver, AbstractServer *server, const QByteArray &name, Cache *cache);
|
||||
|
||||
QList<Record> existing() const;
|
||||
void query() const;
|
||||
|
||||
AbstractServer *server;
|
||||
QByteArray name;
|
||||
Cache *cache;
|
||||
QSet<QHostAddress> addresses;
|
||||
QTimer timer;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onMessageReceived(const Message &message);
|
||||
void onTimeout();
|
||||
|
||||
private:
|
||||
|
||||
Resolver *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_RESOLVER_P_H
|
|
@ -1,137 +0,0 @@
|
|||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <cerrno>
|
||||
# include <cstring>
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QNetworkInterface>
|
||||
|
||||
#include "../include/dns.h"
|
||||
#include "../include/mdns.h"
|
||||
#include "../include/message.h"
|
||||
#include "../include/server.h"
|
||||
|
||||
#include "server_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ServerPrivate::ServerPrivate(Server *server)
|
||||
: QObject(server),
|
||||
q(server)
|
||||
{
|
||||
connect(&timer, &QTimer::timeout, this, &ServerPrivate::onTimeout);
|
||||
connect(&ipv4Socket, &QUdpSocket::readyRead, this, &ServerPrivate::onReadyRead);
|
||||
connect(&ipv6Socket, &QUdpSocket::readyRead, this, &ServerPrivate::onReadyRead);
|
||||
|
||||
timer.setInterval(60 * 1000);
|
||||
timer.setSingleShot(true);
|
||||
onTimeout();
|
||||
}
|
||||
|
||||
bool ServerPrivate::bindSocket(QUdpSocket &socket, const QHostAddress &address)
|
||||
{
|
||||
// Exit early if the socket is already bound
|
||||
if (socket.state() == QAbstractSocket::BoundState) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// I cannot find the correct combination of flags that allows the socket
|
||||
// to bind properly on Linux, so on that platform, we must manually create
|
||||
// the socket and initialize the QUdpSocket with it
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
if (!socket.bind(address, MdnsPort, QAbstractSocket::ShareAddress)) {
|
||||
int arg = 1;
|
||||
if (setsockopt(socket.socketDescriptor(), SOL_SOCKET, SO_REUSEADDR,
|
||||
reinterpret_cast<char*>(&arg), sizeof(int))) {
|
||||
emit q->error(strerror(errno));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (!socket.bind(address, MdnsPort, QAbstractSocket::ReuseAddressHint)) {
|
||||
emit q->error(socket.errorString());
|
||||
return false;
|
||||
}
|
||||
#ifdef Q_OS_UNIX
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ServerPrivate::onTimeout()
|
||||
{
|
||||
// A timer is used to run a set of operations once per minute; first, the
|
||||
// two sockets are bound - if this fails, another attempt is made once per
|
||||
// timeout; secondly, all network interfaces are enumerated; if the
|
||||
// interface supports multicast, the socket will join the mDNS multicast
|
||||
// groups
|
||||
|
||||
bool ipv4Bound = bindSocket(ipv4Socket, QHostAddress::AnyIPv4);
|
||||
bool ipv6Bound = bindSocket(ipv6Socket, QHostAddress::AnyIPv6);
|
||||
|
||||
if (ipv4Bound || ipv6Bound) {
|
||||
const auto interfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &networkInterface : interfaces) {
|
||||
if (networkInterface.flags() & QNetworkInterface::CanMulticast) {
|
||||
if (ipv4Bound) {
|
||||
ipv4Socket.joinMulticastGroup(MdnsIpv4Address, networkInterface);
|
||||
}
|
||||
if (ipv6Bound) {
|
||||
ipv6Socket.joinMulticastGroup(MdnsIpv6Address, networkInterface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timer.start();
|
||||
}
|
||||
|
||||
void ServerPrivate::onReadyRead()
|
||||
{
|
||||
// Read the packet from the socket
|
||||
QUdpSocket *socket = qobject_cast<QUdpSocket*>(sender());
|
||||
QByteArray packet;
|
||||
packet.resize(socket->pendingDatagramSize());
|
||||
QHostAddress address;
|
||||
quint16 port;
|
||||
socket->readDatagram(packet.data(), packet.size(), &address, &port);
|
||||
|
||||
// Attempt to decode the packet
|
||||
Message message;
|
||||
if (fromPacket(packet, message)) {
|
||||
message.setAddress(address);
|
||||
message.setPort(port);
|
||||
emit q->messageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
Server::Server(QObject *parent)
|
||||
: AbstractServer(parent),
|
||||
d(new ServerPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
void Server::sendMessage(const Message &message)
|
||||
{
|
||||
QByteArray packet;
|
||||
toPacket(message, packet);
|
||||
if (message.address().protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
d->ipv4Socket.writeDatagram(packet, message.address(), message.port());
|
||||
} else {
|
||||
d->ipv6Socket.writeDatagram(packet, message.address(), message.port());
|
||||
}
|
||||
}
|
||||
|
||||
void Server::sendMessageToAll(const Message &message)
|
||||
{
|
||||
QByteArray packet;
|
||||
toPacket(message, packet);
|
||||
//qDebug() << "packet:" << packet;
|
||||
qint64 sentBytes = d->ipv4Socket.writeDatagram(packet, MdnsIpv4Address, MdnsPort);
|
||||
qDebug() << "ipv4Socket sentBytes:" << sentBytes;
|
||||
sentBytes = d->ipv6Socket.writeDatagram(packet, MdnsIpv6Address, MdnsPort);
|
||||
qDebug() << "ipv6Socket sentBytes:" << sentBytes;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVER_P_H
|
||||
#define QMDNSENGINE_SERVER_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QUdpSocket>
|
||||
|
||||
class QHostAddress;
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class Server;
|
||||
|
||||
class ServerPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit ServerPrivate(Server *server);
|
||||
|
||||
bool bindSocket(QUdpSocket &socket, const QHostAddress &address);
|
||||
|
||||
QTimer timer;
|
||||
QUdpSocket ipv4Socket{ this };
|
||||
QUdpSocket ipv6Socket{ this };
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
void onTimeout();
|
||||
void onReadyRead();
|
||||
|
||||
private:
|
||||
|
||||
Server *const q;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVER_P_H
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../include/service.h"
|
||||
|
||||
#include "service_p.h"
|
||||
|
||||
using namespace QMdnsEngine;
|
||||
|
||||
ServicePrivate::ServicePrivate()
|
||||
{
|
||||
}
|
||||
|
||||
Service::Service()
|
||||
: d(new ServicePrivate)
|
||||
{
|
||||
}
|
||||
|
||||
Service::Service(const Service &other)
|
||||
: d(new ServicePrivate)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
Service &Service::operator=(const Service &other)
|
||||
{
|
||||
*d = *other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Service::operator==(const Service &other) const
|
||||
{
|
||||
return d->type == other.d->type &&
|
||||
d->name == other.d->name &&
|
||||
d->port == other.d->port &&
|
||||
d->attributes == other.d->attributes;
|
||||
}
|
||||
|
||||
bool Service::operator!=(const Service &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
Service::~Service()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
QByteArray Service::type() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Service::setType(const QByteArray &type)
|
||||
{
|
||||
d->type = type;
|
||||
}
|
||||
|
||||
QByteArray Service::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Service::setName(const QByteArray &name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
QByteArray Service::hostname() const
|
||||
{
|
||||
return d->hostname;
|
||||
}
|
||||
|
||||
void Service::setHostname(const QByteArray &hostname)
|
||||
{
|
||||
d->hostname = hostname;
|
||||
}
|
||||
|
||||
quint16 Service::port() const
|
||||
{
|
||||
return d->port;
|
||||
}
|
||||
|
||||
void Service::setPort(quint16 port)
|
||||
{
|
||||
d->port = port;
|
||||
}
|
||||
|
||||
QMap<QByteArray, QByteArray> Service::attributes() const
|
||||
{
|
||||
return d->attributes;
|
||||
}
|
||||
|
||||
void Service::setAttributes(const QMap<QByteArray, QByteArray> &attributes)
|
||||
{
|
||||
d->attributes = attributes;
|
||||
}
|
||||
|
||||
void Service::addAttribute(const QByteArray &key, const QByteArray &value)
|
||||
{
|
||||
d->attributes.insert(key, value);
|
||||
}
|
||||
|
||||
QDebug QMdnsEngine::operator<<(QDebug debug, const Service &service)
|
||||
{
|
||||
QDebugStateSaver saver(debug);
|
||||
Q_UNUSED(saver);
|
||||
|
||||
debug.noquote().nospace()
|
||||
<< "Service(name: " << service.name()
|
||||
<< ", type: " << service.type()
|
||||
<< ", hostname: " << service.hostname()
|
||||
<< ", port: " << service.port()
|
||||
<< ", attributes: " << service.attributes()
|
||||
<< ")";
|
||||
|
||||
return debug;
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Nathan Osman
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QMDNSENGINE_SERVICE_P_H
|
||||
#define QMDNSENGINE_SERVICE_P_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
|
||||
namespace QMdnsEngine
|
||||
{
|
||||
|
||||
class ServicePrivate
|
||||
{
|
||||
public:
|
||||
|
||||
ServicePrivate();
|
||||
|
||||
QByteArray type;
|
||||
QByteArray name;
|
||||
QByteArray hostname;
|
||||
quint16 port;
|
||||
QMap<QByteArray, QByteArray> attributes;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QMDNSENGINE_SERVICE_P_H
|
|
@ -1,36 +0,0 @@
|
|||
// servicemodel.cpp
|
||||
#include "servicemodel.h"
|
||||
|
||||
Q_DECLARE_METATYPE(QMdnsEngine::Service)
|
||||
|
||||
ServiceProvider::ServiceProvider(QObject* parent)
|
||||
: QObject(parent), mHostname(&mServer), mProvider(nullptr)
|
||||
{
|
||||
// Initialize the provider when the ServiceProvider is created
|
||||
}
|
||||
|
||||
void ServiceProvider::startServiceBroadcast(const QString& serviceName, const QString& serviceType, quint16 port)
|
||||
{
|
||||
if (mProvider) {
|
||||
delete mProvider;
|
||||
mProvider = nullptr;
|
||||
}
|
||||
// Set up the service with the specified name, type, and port
|
||||
mService.setName(serviceName.toUtf8());
|
||||
mService.setType(serviceType.toUtf8());
|
||||
mService.setPort(port);
|
||||
// Create a new provider for this service
|
||||
mProvider = new QMdnsEngine::Provider(&mServer, &mHostname, this);
|
||||
mProvider->update(mService);
|
||||
|
||||
qDebug() << "mDNS service broadcast started:" << serviceName << serviceType << "on port" << port;
|
||||
}
|
||||
|
||||
void ServiceProvider::stopServiceBroadcast()
|
||||
{
|
||||
if (mProvider) {
|
||||
delete mProvider;
|
||||
mProvider = nullptr;
|
||||
qDebug() << "mDNS service broadcast stopped.";
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// servicemodel.h
|
||||
#ifndef SERVICEMODEL_H
|
||||
#define SERVICEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "qmdnsengine/include/server.h"
|
||||
#include "qmdnsengine/include/hostname.h"
|
||||
#include "qmdnsengine/include/provider.h"
|
||||
#include "qmdnsengine/include/service.h"
|
||||
#include "qmdnsengine/include/message.h"
|
||||
#include "qmdnsengine/include/query.h"
|
||||
|
||||
class ServiceProvider : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ServiceProvider(QObject* parent = nullptr);
|
||||
|
||||
void startServiceBroadcast(const QString& serviceName, const QString& serviceType, quint16 port);
|
||||
void stopServiceBroadcast();
|
||||
|
||||
private:
|
||||
QMdnsEngine::Server mServer;
|
||||
QMdnsEngine::Hostname mHostname;
|
||||
QMdnsEngine::Provider* mProvider;
|
||||
QMdnsEngine::Service mService;
|
||||
};
|
||||
|
||||
#endif // SERVICEPROVIDER_H
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
#define SET_LOG_LEVEL 0x0360
|
||||
|
||||
// 前后板设备信息
|
||||
// 前板设备信息
|
||||
#define GET_FRONT_V851_VERSION 0x0400
|
||||
#define GET_FRONT_MCU_VERSION 0x0401
|
||||
#define GET_FRONT_HW_VERSION 0x0402
|
||||
|
@ -66,6 +66,7 @@
|
|||
#define GET_FRONT_HW_INFO 0x0420
|
||||
#define WRITE_FRONT_LICENSE 0x0421
|
||||
|
||||
// 后板设备信息
|
||||
#define GET_BACK_V851_VERSION 0x0450
|
||||
#define GET_BACK_806_VERSION 0x0451
|
||||
#define GET_BACK_HW_VERSION 0x0452
|
||||
|
@ -77,4 +78,5 @@
|
|||
|
||||
#define VIDEO_TEST 0x050A
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -108,8 +108,8 @@ void DataHandler::updateLineEdit(int msg_id, const QByteArray& actual_data) {
|
|||
|
||||
void DataHandler::clearAllRecvData() {
|
||||
allRecvData = QByteArray();
|
||||
remain = 0;
|
||||
dataLen = 0;
|
||||
remain = 0;
|
||||
dataLen = 0;
|
||||
}
|
||||
|
||||
// 处理接收到的数据
|
||||
|
@ -145,11 +145,20 @@ void DataHandler::handleData(const QString& client, const QByteArray& recv
|
|||
(static_cast<unsigned char>(buffer->at(7)) << 8) |
|
||||
(static_cast<unsigned char>(buffer->at(6)));
|
||||
//qDebug() << "---Received dataSize:" << dataSize;
|
||||
//qDebug() << "---Received buffer->size():" << buffer->size();
|
||||
//qDebug() << "---msg_id:" << QString::number(msg_id, 16).toUpper();
|
||||
// 第11字节为返回 OK/NG
|
||||
bool success = (static_cast<unsigned char>(buffer->at(10)) == 0x00);
|
||||
bool success = (static_cast<unsigned char>(buffer->at(10)) != 0x00);
|
||||
int totalSize = 10 + dataSize; // 数据头大小(10字节) + 实际数据大小
|
||||
|
||||
if (CurrentCommand == "GET_BACK_MAC") {
|
||||
//qDebug() << "--- getCommandNameFromValue:" << msg_id;
|
||||
if (!getCommandNameFromValue(msg_id)) {
|
||||
//qDebug() << "--- getCommandNameFromValue:" << msg_id;
|
||||
buffer->remove(0, buffer->size());
|
||||
emit commandError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buffer->size() >= totalSize) {
|
||||
// 调试查看收到的前19个字节
|
||||
/*for (int i = 0; i < 19; i++) {
|
||||
|
@ -158,7 +167,7 @@ void DataHandler::handleData(const QString& client, const QByteArray& recv
|
|||
QByteArray data = buffer->mid(11, dataSize);
|
||||
QString hexString = QString::fromUtf8(data.toHex().data());
|
||||
QByteArray actual_data = hexStringToByteArray(hexString);
|
||||
buffer->remove(0, totalSize); // 移除已处理的数据
|
||||
buffer->remove(0, totalSize); // 移除已处理的数据
|
||||
if(msg_id != 0x0040 && msg_id != START_VIDEO && msg_id != GET_IMG && msg_id != VIDEO_TEST &&
|
||||
msg_id != STOP_VIDEO) {
|
||||
qDebug() << "--- msg_id:" << msg_id;
|
||||
|
@ -167,7 +176,7 @@ void DataHandler::handleData(const QString& client, const QByteArray& recv
|
|||
(msg_id != 0x0021 || clientLastMsgId.value(client, 0) != 0x0021) &&
|
||||
(msg_id != START_VIDEO || clientLastMsgId.value(client, 0) != START_VIDEO)) {
|
||||
//qDebug() << "Emitting statusUpdated for client:" << client << "with msg_id:" << QString::number(msg_id, 16).toUpper();
|
||||
emit statusUpdated(client, true, jsonArray, itemJsonIndex);
|
||||
emit statusUpdated(client, success, jsonArray, itemJsonIndex);
|
||||
}
|
||||
clientLastMsgId[client] = msg_id;
|
||||
}
|
||||
|
@ -183,6 +192,68 @@ void DataHandler::handleData(const QString& client, const QByteArray& recv
|
|||
}
|
||||
}
|
||||
|
||||
void DataHandler::getCurrentSendItem(const QString& text) {
|
||||
CurrentCommand = text;
|
||||
}
|
||||
|
||||
// 初始化映射表
|
||||
std::map<QString, int> commandValueMap = {
|
||||
{"FACE_ENROLL_SINGLE", FACE_ENROLL_SINGLE},
|
||||
{"FACE_ENROLL", FACE_ENROLL},
|
||||
{"HAND_ENROLL", HAND_ENROLL},
|
||||
{"FACE_VERIFY", FACE_VERIFY},
|
||||
{"HAND_VERIFY", HAND_VERIFY},
|
||||
{"DEL_USER", DEL_USER},
|
||||
{"DEL_ALLUSER", DEL_ALLUSER},
|
||||
{"GET_USER", GET_USER},
|
||||
{"GET_ALLUSER", GET_ALLUSER},
|
||||
{"PASSWD_ENROLL", PASSWD_ENROLL},
|
||||
{"IMG_ENROLL", IMG_ENROLL},
|
||||
{"GET_IMG", GET_IMG},
|
||||
{"START_VIDEO", START_VIDEO},
|
||||
{"STOP_VIDEO", STOP_VIDEO},
|
||||
{"TOUCH_TEST", TOUCH_TEST},
|
||||
{"MIC_TEST", MIC_TEST},
|
||||
{"SPK_TEST", SPK_TEST},
|
||||
{"RADAR_TEST", RADAR_TEST},
|
||||
{"NFC_TEST", NFC_TEST},
|
||||
{"PR_SWITCH", PR_SWITCH},
|
||||
{"PS_TEST", PS_TEST},
|
||||
{"BACKLIGHT", BACKLIGHT},
|
||||
{"IR_LED", IR_LED},
|
||||
{"UART_TEST", UART_TEST},
|
||||
{"PIR_TEST", PIR_TEST},
|
||||
{"FACE_VERIFY_THRES", FACE_VERIFY_THRES},
|
||||
{"FACE_THRES_LEVEL", FACE_THRES_LEVEL},
|
||||
{"FACE_LIVE_THRES", FACE_LIVE_THRES},
|
||||
{"FACE_ACC_THRES", FACE_ACC_THRES},
|
||||
{"FACE_ACC_LEVEL", FACE_ACC_LEVEL},
|
||||
{"FACE_DIS_RANGE", FACE_DIS_RANGE},
|
||||
{"FACE_ANGLE_RANGE", FACE_ANGLE_RANGE},
|
||||
|
||||
{"GET_BACK_MAC", GET_BACK_MAC},
|
||||
{"WRITE_BACK_UID_SN", WRITE_BACK_UID_SN}
|
||||
};
|
||||
|
||||
bool DataHandler::getCommandNameFromValue(int receivedValue) {
|
||||
auto it = commandValueMap.find(CurrentCommand);
|
||||
if (it != commandValueMap.end()) {
|
||||
int expectedValue = it->second;
|
||||
if (expectedValue == receivedValue) {
|
||||
std::cout << "Match found: " << CurrentCommand.toStdString() << " corresponds to value " << std::hex << expectedValue << std::endl;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
std::cout << "Value mismatch: Expected " << std::hex << expectedValue << ", but received " << std::hex << receivedValue << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cout << "Unknown command: " << CurrentCommand.toStdString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DataHandler::initializeMsgIdToCmdMap() {
|
||||
msgIdToCmdMap[GET_FRONT_V851_VERSION] = "GET_FRONT_V851_VERSION";
|
||||
msgIdToCmdMap[GET_FRONT_MCU_VERSION] = "GET_FRONT_MCU_VERSION";
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define YUV420 1
|
||||
#define YUV422 2
|
||||
|
||||
#define BACK_MAC_ADDRESS_LEN 11
|
||||
#define BACK_MAC_ADDRESS_LEN 17
|
||||
|
||||
class DataHandler : public QObject
|
||||
{
|
||||
|
@ -48,6 +48,7 @@ public slots:
|
|||
void handleData(const QString& client, const QByteArray& data, int msg_id, int currentRecvItemIndex,
|
||||
int currentRecvFuncItemIndex, const QString& itemData, const QString& funcItemData,
|
||||
const QJsonArray& jsonArray, int itemJsonIndex);
|
||||
void getCurrentSendItem(const QString& text);
|
||||
signals:
|
||||
void statusUpdated(const QString& clientAddress, bool success, const QJsonArray& jsonArray, int itemJsonIndex);
|
||||
void updateLicenseHwInfoEdit(const QString& text);
|
||||
|
@ -57,6 +58,7 @@ signals:
|
|||
void updateVideoLabel(const QPixmap& pixmap);
|
||||
void updateVideoResolution(const QString& resolutionText);
|
||||
void picRecvFinished();
|
||||
void commandError();
|
||||
private:
|
||||
QJsonArray frontBoardOneClickTest; // 前板一键功能测试 JSON
|
||||
QJsonArray frontBoardTest; // 前板单项测试 JSON
|
||||
|
@ -91,8 +93,9 @@ private:
|
|||
QMap<int, QString> msgIdToCmdMap;
|
||||
QSize labelSize;
|
||||
bool isStartVideo = false;
|
||||
QString CurrentCommand = "";
|
||||
|
||||
// 如果接收十六进制数据,转为二进制
|
||||
bool getCommandNameFromValue(int receivedValue);
|
||||
QByteArray hexStringToByteArray(const QString& hexString);
|
||||
void showVideo(const QString& client, const QByteArray& valData);
|
||||
void clearAllRecvData();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MainWidget.cpp
|
||||
#include "MainWidget.h"
|
||||
|
||||
#include <qrencode.h>
|
||||
void onThreadFinished(QThread* thread, ClientHandler* handler, DataHandler* dataHandler)
|
||||
{
|
||||
qDebug() << "Thread finished. Deleting handler and thread.";
|
||||
|
@ -9,6 +9,25 @@ void onThreadFinished(QThread* thread, ClientHandler* handler, DataHandler* data
|
|||
thread->deleteLater();
|
||||
}
|
||||
|
||||
bool initializeMdns() {
|
||||
#ifdef _WIN32
|
||||
WORD versionWanted = MAKEWORD(1, 1);
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(versionWanted, &wsaData)) {
|
||||
qDebug() << "Failed to initialize WinSock";
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// 设置中断信号处理器
|
||||
signal(SIGINT, [](int signal) {
|
||||
qDebug() << "SIGINT received, cleaning up...";
|
||||
// 处理退出信号的资源释放逻辑(如果需要)
|
||||
});
|
||||
#endif
|
||||
qDebug() << "mDNS initialization completed.";
|
||||
return true;
|
||||
}
|
||||
|
||||
// 初始化 UI 组件和服务器
|
||||
MainWidget::MainWidget(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
|
@ -19,15 +38,16 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
lastClickedGetPicDevIndex(-1),
|
||||
lastClickedGetVideoCamIndex(-1),
|
||||
lastClickedGetVideoDevIndex(-1),
|
||||
mServiceProvider(new ServiceProvider(this)),
|
||||
//mServiceProvider(new ServiceProvider(this)),
|
||||
mdnsTimer(new QTimer(this)),
|
||||
httpClient(new HttpClient(this))
|
||||
httpClient(new HttpClient(this)),
|
||||
httpServer(new QTcpServer(this)),
|
||||
mdnsThread(nullptr)
|
||||
#if TEST_UDP_BROADCAST
|
||||
,multicastSocket(new QUdpSocket(this)),
|
||||
multicastTimer(new QTimer(this))
|
||||
#endif
|
||||
{
|
||||
|
||||
QString configFilePath = QDir::currentPath() + "/UI_config.ini";
|
||||
TOOL_UI = loadConfig(configFilePath);
|
||||
|
||||
|
@ -46,6 +66,12 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
UuidHwInfoEdit = new QTextEdit(this);
|
||||
|
||||
setupUI();
|
||||
// 初始化 mDNS
|
||||
if (!initializeMdns()) {
|
||||
qDebug() << "Failed to initialize mDNS. Exiting...";
|
||||
return;
|
||||
}
|
||||
setupHttpServer();
|
||||
// 打印线程池状态信息
|
||||
setupTimerForThreadPoolInfo();
|
||||
server = new QTcpServer(this);
|
||||
|
@ -58,6 +84,7 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
QHostAddress clientIp = socket->peerAddress();
|
||||
quint16 clientPort = socket->peerPort();
|
||||
QString ipString = clientIp.toString();
|
||||
isReplyOrTimeout = true;
|
||||
if (ipString.startsWith("::ffff:")) {
|
||||
ipString = ipString.mid(7);
|
||||
}
|
||||
|
@ -67,14 +94,16 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
|
||||
|
||||
if (ipString.startsWith("10.10.10")) {
|
||||
//if (1) {
|
||||
qDebug() << "The client IP address is front board !!!";
|
||||
isBackBoardOrAllBoard = 0;
|
||||
}
|
||||
else {
|
||||
onDisconnectClient(clientId - 1);
|
||||
qDebug() << "The client IP address is back board or all board";
|
||||
isBackBoardOrAllBoard = clientId;
|
||||
}
|
||||
stopMdnsService();
|
||||
//stopMdnsService();
|
||||
connectedClientsCount ++;
|
||||
updateServerButtonText();
|
||||
|
||||
|
@ -126,12 +155,14 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
connect(handler, &ClientHandler::HandleInvalidOperate, this, &MainWidget::onHandleInvalidOperate);
|
||||
connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected);
|
||||
connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
|
||||
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
|
||||
//connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
|
||||
|
||||
dataHandlers[clientId] = dataHandler;
|
||||
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
|
||||
connect(dataHandler, &DataHandler::picRecvFinished, handler, &ClientHandler::onPicRecvFinished);
|
||||
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
|
||||
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
|
||||
connect(handler, &ClientHandler::currentSendItem, dataHandler, &DataHandler::getCurrentSendItem);
|
||||
connect(dataHandler, &DataHandler::picRecvFinished, handler, &ClientHandler::onPicRecvFinished);
|
||||
connect(dataHandler, &DataHandler::commandError, handler, &ClientHandler::onCommandError);
|
||||
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
|
||||
// 当线程结束时删除 handler
|
||||
connect(thread, &QThread::finished, this, [=]() {
|
||||
onThreadFinished(thread, handler, dataHandler);
|
||||
|
@ -163,7 +194,9 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
clientReadTimers[clientId] = readTimer;
|
||||
|
||||
connect(handler, &ClientHandler::sendDataToSomeClient, this, &MainWidget::sendDataToClient);
|
||||
if (isBackBoardOrAllBoard == 1) {
|
||||
connect(handler, &ClientHandler::startImageSharing, this, &MainWidget::onStartImageSharing);
|
||||
|
||||
if (isBackBoardOrAllBoard != 0) {
|
||||
handler->sendDevInfoItem();
|
||||
}
|
||||
}
|
||||
|
@ -178,8 +211,6 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
|
||||
connectionStatusCheckTimer = new QTimer(this);
|
||||
connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus);
|
||||
//connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态
|
||||
connect(mdnsTimer, &QTimer::timeout, this, &MainWidget::startMdnsService);
|
||||
|
||||
#if TEST_UDP_BROADCAST
|
||||
// 设置组播地址
|
||||
|
@ -205,15 +236,6 @@ MainWidget::MainWidget(QWidget* parent) :
|
|||
|
||||
MainWidget::~MainWidget()
|
||||
{
|
||||
#if TEST_UDP_BROADCAST
|
||||
multicastTimer->stop();
|
||||
multicastSocket->leaveMulticastGroup(QHostAddress("224.0.0.251"));
|
||||
multicastSocket->close();
|
||||
#endif
|
||||
if (mdnsTimer->isActive()) {
|
||||
mdnsTimer->stop();
|
||||
}
|
||||
delete mdnsTimer;
|
||||
stopMdnsService();
|
||||
for (auto timer : clientReadTimers) {
|
||||
timer->stop();
|
||||
|
@ -283,7 +305,7 @@ void MainWidget::onClientDisconnected(ClientHandler* handler)
|
|||
|
||||
// 更新连接数并更新按键文本
|
||||
connectedClientsCount--;
|
||||
qDebug() << " connectedClientsCount :" << connectedClientsCount;
|
||||
//qDebug() << " connectedClientsCount :" << connectedClientsCount;
|
||||
if (nextClientId <= 2) nextClientId --;
|
||||
deviceConnected = true;
|
||||
|
||||
|
@ -311,6 +333,60 @@ void MainWidget::onClientDisconnected(ClientHandler* handler)
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::onDisconnectClient(int clientId)
|
||||
{
|
||||
for (ClientHandler* handler : clients) {
|
||||
if (handler->getClientId() == clientId) {
|
||||
// 断开与该客户端的连接
|
||||
if (clientTimers.contains(clientId)) {
|
||||
QTimer* timer = clientTimers[clientId];
|
||||
timer->stop();
|
||||
delete timer;
|
||||
clientTimers.remove(clientId);
|
||||
}
|
||||
clients.removeOne(handler);
|
||||
handler->deleteLater();
|
||||
|
||||
if (dataHandlers.contains(clientId)) {
|
||||
DataHandler* dataHandler = dataHandlers[clientId];
|
||||
dataHandlers.remove(clientId); // 从容器中移除
|
||||
dataHandler->deleteLater(); // 延迟删除 DataHandler 对象
|
||||
}
|
||||
int count = 200;
|
||||
int preVideoId = handler->preVideoClientId;
|
||||
int boardTpye = isBackBoardOrAllBoard;
|
||||
while (count--);
|
||||
qDebug() << " preVideoClientId :" << preVideoId;
|
||||
qDebug() << " clientId :" << clientId;
|
||||
if ((boardTpye != 0) || (preVideoId == clientId)) {
|
||||
qDebug() << "Current path: " << QDir::currentPath();
|
||||
QString filePath = QDir::currentPath() + "/add1.h264";
|
||||
if (QFile::exists(filePath)) {
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
qDebug() << "File add1.h264 cleared successfully.";
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to clear file add1.h264:" << file.errorString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "File add1.h264 does not exist.";
|
||||
}
|
||||
}
|
||||
connectedClientsCount--;
|
||||
//qDebug() << " connectedClientsCount :" << connectedClientsCount;
|
||||
updateServerButtonText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
stopMdnsService();
|
||||
//if (connectedClientsCount == 0) {
|
||||
// // 启动 mDNS 服务广播
|
||||
// startMdnsService();
|
||||
//}
|
||||
}
|
||||
|
||||
// 更新按键文本的函数
|
||||
void MainWidget::updateServerButtonText()
|
||||
{
|
||||
|
@ -428,6 +504,201 @@ void MainWidget::setupUI()
|
|||
connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged);
|
||||
}
|
||||
|
||||
void MainWidget::onStartImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback) {
|
||||
imagePath = QFileDialog::getOpenFileName(this, "选择图片", QDir::homePath(), "Images (*.png *.jpg *.jpeg)");
|
||||
|
||||
if (imagePath.isEmpty()) {
|
||||
qDebug() << "No image selected.";
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载图片并获取尺寸
|
||||
QImage image(imagePath);
|
||||
if (image.isNull()) {
|
||||
qDebug() << "Failed to load image.";
|
||||
return;
|
||||
}
|
||||
QSize imageSize = image.size();
|
||||
qDebug() << "Original image dimensions:" << imageSize.width() << "x" << imageSize.height();
|
||||
// 判断是否需要裁剪
|
||||
if (imageSize.width() > width || imageSize.height() > height) {
|
||||
int x = (imageSize.width() - width) / 2; // 左右裁剪
|
||||
int y = (imageSize.height() - height) / 2; // 上下裁剪
|
||||
|
||||
// 裁剪图片中间部分
|
||||
image = image.copy(x, y, width, height);
|
||||
qDebug() << "Cropped image dimensions:" << image.width() << "x" << image.height();
|
||||
}
|
||||
else if(imageSize.width() < width || imageSize.height() < height) {
|
||||
isReplyOrTimeout = true;
|
||||
QString info = QString("您选择的图片尺寸小于 %1 x %2,请重新操作并选择正确的尺寸的图片!!!").arg(width).arg(height);
|
||||
LicenseConfirmWindow dialog(info);
|
||||
dialog.exec();
|
||||
callback("");
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存裁剪后的图片到服务器目录
|
||||
QString croppedImagePath = QCoreApplication::applicationDirPath() + QString("/%1_image.jpg").arg(img_type);
|
||||
if (!image.save(croppedImagePath, "JPEG")) {
|
||||
qDebug() << "Failed to save cropped image.";
|
||||
return;
|
||||
}
|
||||
qDebug() << "Cropped image saved to:" << croppedImagePath;
|
||||
|
||||
// 更新服务使用裁剪后的图片路径
|
||||
this->imagePath = croppedImagePath;
|
||||
|
||||
// 获取本地 IP 地址
|
||||
QString localIP;
|
||||
QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
|
||||
for (const QHostAddress& addr : addresses) {
|
||||
if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost) {
|
||||
localIP = addr.toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (localIP.isEmpty()) {
|
||||
qDebug() << "Failed to determine local IP address.";
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建下载 URL
|
||||
QString downloadUrl = QString("http://%1:%2/%3_image.jpg").arg(localIP).arg(serverPort).arg(img_type);
|
||||
qDebug() << "Download URL:" << downloadUrl;
|
||||
|
||||
// 回调返回下载地址
|
||||
callback(downloadUrl);
|
||||
}
|
||||
|
||||
void MainWidget::setupHttpServer() {
|
||||
connect(httpServer, &QTcpServer::newConnection, this, [this]() {
|
||||
QTcpSocket* clientSocket = httpServer->nextPendingConnection();
|
||||
connect(clientSocket, &QTcpSocket::readyRead, this, [this, clientSocket]() {
|
||||
handleHttpRequest(clientSocket);
|
||||
});
|
||||
});
|
||||
|
||||
if (!httpServer->listen(QHostAddress::Any, serverPort)) {
|
||||
qDebug() << "Failed to start HTTP server:" << httpServer->errorString();
|
||||
}
|
||||
else {
|
||||
qDebug() << "HTTP server started on port" << serverPort;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::handleHttpRequest(QTcpSocket* clientSocket) {
|
||||
QByteArray requestData = clientSocket->readAll();
|
||||
qDebug() << "HTTP Request:" << requestData;
|
||||
|
||||
if (imagePath.isEmpty()) {
|
||||
clientSocket->write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
|
||||
clientSocket->disconnectFromHost();
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(imagePath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
clientSocket->write("HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n");
|
||||
clientSocket->disconnectFromHost();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray imageData = file.readAll();
|
||||
file.close();
|
||||
|
||||
QString response = QString("HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: %1\r\n\r\n")
|
||||
.arg(imageData.size());
|
||||
clientSocket->write(response.toUtf8());
|
||||
clientSocket->write(imageData);
|
||||
clientSocket->disconnectFromHost();
|
||||
}
|
||||
|
||||
|
||||
//void MainWidget::setupHttpServer() {
|
||||
// connect(httpServer, &QTcpServer::newConnection, this, [this]() {
|
||||
// QTcpSocket* clientSocket = httpServer->nextPendingConnection();
|
||||
// connect(clientSocket, &QTcpSocket::readyRead, this, [this, clientSocket]() {
|
||||
// handleHttpRequest(clientSocket);
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// if (!httpServer->listen(QHostAddress::Any, serverPort)) {
|
||||
// qDebug() << "Failed to start HTTP server:" << httpServer->errorString();
|
||||
// }
|
||||
// else {
|
||||
// qDebug() << "HTTP server started on port" << serverPort;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void MainWidget::handleHttpRequest(QTcpSocket* clientSocket) {
|
||||
// QByteArray requestData = clientSocket->readAll();
|
||||
// //qDebug() << "HTTP Request:" << requestData;
|
||||
// if (imagePath.isEmpty()) {
|
||||
// clientSocket->write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
|
||||
// clientSocket->disconnectFromHost();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// QFile file(imagePath);
|
||||
// if (!file.open(QIODevice::ReadOnly)) {
|
||||
// clientSocket->write("HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n\r\n");
|
||||
// clientSocket->disconnectFromHost();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// QByteArray imageData = file.readAll();
|
||||
// file.close();
|
||||
//
|
||||
// QString response = QString("HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: %1\r\n\r\n")
|
||||
// .arg(imageData.size());
|
||||
// clientSocket->write(response.toUtf8());
|
||||
// clientSocket->write(imageData);
|
||||
// clientSocket->disconnectFromHost();
|
||||
//}
|
||||
//
|
||||
////注意事项
|
||||
////端口冲突:确保 8080 端口未被其他程序占用,可以更换为其他端口。
|
||||
////防火墙规则:确保防火墙允许外部设备访问该端口。
|
||||
////图片格式:上述代码默认处理 PNG/JPG/JPEG 格式,如果需要支持其他格式,可根据 MIME 类型调整 Content - Type
|
||||
//void MainWidget::onStartImageSharing(int width, int height, std::function<void(QString)> callback) {
|
||||
// imagePath = QFileDialog::getOpenFileName(this, "选择图片", QDir::homePath(), "Images (*.png *.jpg *.jpeg)");
|
||||
//
|
||||
// if (imagePath.isEmpty()) {
|
||||
// qDebug() << "No image selected.";
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 加载图片并获取尺寸
|
||||
// QImage image(imagePath);
|
||||
// if (image.isNull()) {
|
||||
// qDebug() << "Failed to load image.";
|
||||
// return;
|
||||
// }
|
||||
// QSize imageSize = image.size();
|
||||
// qDebug() << "Image dimensions:" << imageSize.width() << "x" << imageSize.height();
|
||||
//
|
||||
// QString localIP;
|
||||
// QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
|
||||
// for (const QHostAddress& addr : addresses) {
|
||||
// if (addr.protocol() == QAbstractSocket::IPv4Protocol && addr != QHostAddress::LocalHost) {
|
||||
// localIP = addr.toString();
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (localIP.isEmpty()) {
|
||||
// qDebug() << "Failed to determine local IP address.";
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// QString downloadUrl = QString("http://%1:%2/").arg(localIP).arg(serverPort);
|
||||
// qDebug() << "Download URL:" << downloadUrl;
|
||||
//
|
||||
// callback(downloadUrl);
|
||||
//}
|
||||
|
||||
// 服务器响应
|
||||
void MainWidget::onHttpRequestFinished(const QJsonObject& response)
|
||||
{
|
||||
|
@ -501,9 +772,10 @@ QString calculateSignature(const QMap<QString, QString>& params, const QString&
|
|||
|
||||
// 3. 构造 BaseString
|
||||
//QString baseString = params["batch"] + params["label"] + params["model"] + params["request_id"] + params["timestamp"] + params["factory_id"];
|
||||
QString baseString = "1TEST_SL100_20240826SL100" + request_id + timestamp + "TEST";
|
||||
//QString baseString = "1TEST_SL100_20240826SL100" + request_id + timestamp + FACTORY_ID;
|
||||
QString baseString = QString::number(BATCH) + QString(LABEL) + QString(MODEL) + request_id + timestamp + QString(FACTORY_ID);
|
||||
qDebug() << "baseString:" << baseString;
|
||||
|
||||
|
||||
// 4. 构造 stringToSign
|
||||
QString stringToSign = httpMethod + "&" + baseString + "&" + canonicalizedQueryString.replace("+", "%20");
|
||||
qDebug() << "stringToSign:" << stringToSign;
|
||||
|
@ -513,10 +785,10 @@ QString calculateSignature(const QMap<QString, QString>& params, const QString&
|
|||
|
||||
// 请求头
|
||||
void prepareRequestHeaders(QNetworkRequest& request, const QString& sign, const QString& request_id) {
|
||||
request.setRawHeader("factory_id", "TEST");
|
||||
request.setRawHeader("label", "TEST_SL100_20240826");
|
||||
request.setRawHeader("batch", QString::number(1).toUtf8());
|
||||
request.setRawHeader("model", "SL100");
|
||||
request.setRawHeader("factory_id", QByteArray(FACTORY_ID));
|
||||
request.setRawHeader("label", QByteArray(LABEL));
|
||||
request.setRawHeader("batch", QString::number(BATCH).toUtf8());
|
||||
request.setRawHeader("model", QByteArray(MODEL));
|
||||
request.setRawHeader("timestamp", QString::number(QDateTime::currentSecsSinceEpoch()).toUtf8());
|
||||
request.setRawHeader("request_id", request_id.toUtf8());
|
||||
request.setRawHeader("sign", sign.toUtf8());
|
||||
|
@ -602,8 +874,6 @@ void MainWidget::FactoryToolSendPostTestToHttpServer() {
|
|||
{"id", "123456"},
|
||||
{"location", "allMachine"}
|
||||
};
|
||||
//QString itemString = "function=faceVerify,result=false,msg=timeout";
|
||||
//QString itemString = "function=faceVerify,result=false,msg=timeout";
|
||||
QString itemString = "[{\"function\":\"faceVerify\",\"msg\":\"timeout\",\"result\":false}]";
|
||||
params["items"] = itemString;
|
||||
|
||||
|
@ -724,25 +994,28 @@ void MainWidget::setupTimerForThreadPoolInfo()
|
|||
|
||||
void MainWidget::readJsonConfig()
|
||||
{
|
||||
frontBoardOneClickTest = readJson_frontBoardOneClickTest();
|
||||
frontBoardTest = readJson_frontBoardTest();
|
||||
frontBoardFuncConfig = readJson_frontBoardFuncConfig();
|
||||
frontBoardDevInfoJson = readJson_frontDevInfo();
|
||||
frontBoardLicenseJson = readJson_frontLicense();
|
||||
frontBoardOneClickTest = readJson_frontBoardOneClickTest();
|
||||
frontBoardTest = readJson_frontBoardTest();
|
||||
frontBoardFuncConfig = readJson_frontBoardFuncConfig();
|
||||
frontBoardDevInfoJson = readJson_frontDevInfo();
|
||||
frontBoardLicenseJson = readJson_frontLicense();
|
||||
//frontBoardCmdConfigJson = readJson_frontCmd_config();
|
||||
|
||||
backBoardOneClickTest = readJson_backBoardOneClickTest();
|
||||
backBoardTest = readJson_backBoardTest();
|
||||
backBoardFuncConfig = readJson_backBoardFuncConfig();
|
||||
backBoardDevInfoJson = readJson_backDevInfo();
|
||||
backBoardUuidJson = readJson_backUuid();
|
||||
backBoardOneClickTest = readJson_backBoardOneClickTest();
|
||||
backBoardTest = readJson_backBoardTest();
|
||||
backBoardFuncConfig = readJson_backBoardFuncConfig();
|
||||
backBoardDevInfoJson = readJson_backDevInfo();
|
||||
backBoardUuidJson = readJson_backUuid();
|
||||
//backBoardCmdConfigJson = readJson_backCmd_config();
|
||||
|
||||
factoryProductInfo = readJson_factoryProductInfo();
|
||||
factoryProductInfo = readJson_factoryProductInfo();
|
||||
|
||||
testJsonConfig = readJson_testConfig();
|
||||
funcJsonConfig = readJson_funcConfig();
|
||||
|
||||
getPicJson = readJson_getPic();
|
||||
getVideoJson = readJson_getVideo();
|
||||
|
||||
}
|
||||
|
||||
void MainWidget::onSelectFileButtonClicked()
|
||||
|
@ -813,32 +1086,6 @@ void MainWidget::scrollToBottom()
|
|||
statusListWidget->scrollToBottom();
|
||||
}
|
||||
|
||||
void MainWidget::onDisconnectClient(int clientId)
|
||||
{
|
||||
for (ClientHandler* handler : clients) {
|
||||
if (handler->getClientId() == clientId) {
|
||||
// 断开与该客户端的连接
|
||||
handler->getSocket()->disconnectFromHost();
|
||||
handler->getSocket()->waitForDisconnected();
|
||||
clients.removeOne(handler);
|
||||
if (clientTimers.contains(clientId)) {
|
||||
QTimer* timer = clientTimers[clientId];
|
||||
timer->stop();
|
||||
delete timer;
|
||||
clientTimers.remove(clientId);
|
||||
}
|
||||
handler->deleteLater();
|
||||
connectedClientsCount --;
|
||||
updateServerButtonText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connectedClientsCount == 0) {
|
||||
// 启动 mDNS 服务广播
|
||||
startMdnsService();
|
||||
}
|
||||
}
|
||||
|
||||
QString formatLicenseKey(const QString& licenseKey) {
|
||||
QString formattedKey;
|
||||
qDebug() << "licenseKey.length():" << licenseKey.length();
|
||||
|
@ -1061,27 +1308,41 @@ void MainWidget::onUuidButtonClicked()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWidget::startMdnsService()
|
||||
{
|
||||
QDateTime currentTime = QDateTime::currentDateTime();
|
||||
QString formattedTime = currentTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
|
||||
qDebug() << "[" << formattedTime << "]:" << "Start Mdns Broadcast Service";
|
||||
QString serviceName = "SL100 FactoryTool Mdns Broadcast Service";
|
||||
QString serviceType = "_myservice._tcp.local";
|
||||
quint16 port = TCP_CONNECT_PORT;
|
||||
mServiceProvider->startServiceBroadcast(serviceName, serviceType, port);
|
||||
void MainWidget::startMdnsService() {
|
||||
const char* hostname = "SL100-FactoryTool-Mdns";
|
||||
const char* service_name = "_myservice._tcp.local.";
|
||||
int service_port = TCP_CONNECT_PORT;
|
||||
|
||||
if (!mdnsTimer->isActive()) {
|
||||
mdnsTimer->start(1000);
|
||||
// 如果线程已经存在且正在运行,先停止
|
||||
if (mdnsThread && mdnsThread->isRunning()) {
|
||||
qDebug() << "Stopping previous mDNS service thread...";
|
||||
mdnsThread->stop();
|
||||
mdnsThread->quit();
|
||||
mdnsThread->wait();
|
||||
delete mdnsThread;
|
||||
}
|
||||
|
||||
// 创建新的线程并启动
|
||||
mdnsThread = new MdnsServiceThread(hostname, service_name, service_port, this);
|
||||
connect(mdnsThread, &QThread::finished, mdnsThread, &QObject::deleteLater); // 确保线程资源释放
|
||||
mdnsThread->start();
|
||||
}
|
||||
|
||||
void MainWidget::stopMdnsService()
|
||||
{
|
||||
if (mdnsTimer->isActive()) {
|
||||
mdnsTimer->stop(); // 停止定时器
|
||||
void MainWidget::stopMdnsService() {
|
||||
if (mdnsThread) {
|
||||
qDebug() << "Stopping mDNS service...";
|
||||
mdnsThread->stop(); // 通知线程退出
|
||||
if (mdnsThread->isRunning()) {
|
||||
mdnsThread->quit(); // 退出线程事件循环
|
||||
mdnsThread->wait(); // 等待线程完全退出
|
||||
}
|
||||
delete mdnsThread; // 释放线程资源
|
||||
mdnsThread = nullptr;
|
||||
qDebug() << "mDNS service stopped.";
|
||||
}
|
||||
else {
|
||||
qDebug() << "mDNS service is not running.";
|
||||
}
|
||||
mServiceProvider->stopServiceBroadcast();
|
||||
}
|
||||
|
||||
// 处理开始服务器按键点击事件
|
||||
|
@ -1409,10 +1670,11 @@ void MainWidget::onSendFrontFuncItemClicked()
|
|||
QPushButton* button = qobject_cast<QPushButton*>(sender());
|
||||
int itemIndex = button->property("frontBoardFuncConfig").toInt();
|
||||
for (ClientHandler* handler : clients) {
|
||||
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
|
||||
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
|
||||
QString text = frontFuncConfigLineEdit->text();
|
||||
qDebug() << "Text in frontFuncConfigLineEdit:" << text;
|
||||
handler->sendFrontFuncItem(itemIndex, text);
|
||||
isReplyOrTimeout = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1429,10 +1691,11 @@ void MainWidget::onSendBackFuncItemClicked()
|
|||
QPushButton* button = qobject_cast<QPushButton*>(sender());
|
||||
int itemIndex = button->property("backBoardFuncConfig").toInt();
|
||||
for (ClientHandler* handler : clients) {
|
||||
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
|
||||
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
|
||||
QString text = backFuncConfigLineEdit->text();
|
||||
qDebug() << "Text in backFuncConfigLineEdit:" << text;
|
||||
handler->sendBackFuncItem(itemIndex, text);
|
||||
isReplyOrTimeout = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1451,8 +1714,9 @@ void MainWidget::onSendFrontItemClicked()
|
|||
QPushButton* button = qobject_cast<QPushButton*>(sender());
|
||||
int itemIndex = button->property("frontBoardTest").toInt();
|
||||
for (ClientHandler* handler : clients) {
|
||||
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
|
||||
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
|
||||
handler->sendFrontItem(itemIndex);
|
||||
isReplyOrTimeout = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1470,8 +1734,9 @@ void MainWidget::onSendBackItemClicked()
|
|||
QPushButton* button = qobject_cast<QPushButton*>(sender());
|
||||
int itemIndex = button->property("backBoardTest").toInt();
|
||||
for (ClientHandler* handler : clients) {
|
||||
if ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId)) {
|
||||
if (isReplyOrTimeout && ((isBackBoardOrAllBoard) || (handler->getClientId() == handler->controlClientId))) {
|
||||
handler->sendBackItem(itemIndex);
|
||||
isReplyOrTimeout = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1484,6 +1749,7 @@ void MainWidget::onSendBackItemClicked()
|
|||
|
||||
void MainWidget::onStatusUpdated(const QString& client, bool success, const QJsonArray& jsonArray, int itemJsonIndex)
|
||||
{
|
||||
isReplyOrTimeout = true;
|
||||
int clientId = -1;
|
||||
QString label;
|
||||
for (ClientHandler* handler : clients) {
|
||||
|
|
|
@ -44,22 +44,29 @@
|
|||
#include <QMessageAuthenticationCode>
|
||||
#include <QCoreApplication>
|
||||
#include <QSettings>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
|
||||
#include "./UI_Widget/UI_Name.h"
|
||||
#include "../Json/readJsonFile.h"
|
||||
#include "../RecvDataHandler/RecvDataHandler.h"
|
||||
#include "../LicenseGenerate/LicenseGenerate.h"
|
||||
#include "../LicenseGenerate/LicenseConfirmWindow.h"
|
||||
#include "../Network/mdns/servicemodel.h"
|
||||
//#include "../Network/mdns/servicemodel.h"
|
||||
#include "../Network/ClientHandler.h"
|
||||
#include "../Network/httpClient.h"
|
||||
#include "../Network/mdns/MdnsServiceThread.h"
|
||||
#include "../Network/mdns/mdns.h"
|
||||
|
||||
#include "../Network/mdns/qmdnsengine/include/server.h"
|
||||
#include "../Network/mdns/qmdnsengine/include/hostname.h"
|
||||
#include "../Network/mdns/qmdnsengine/include/provider.h"
|
||||
#include "../Network/mdns/qmdnsengine/include/service.h"
|
||||
#include "../Network/mdns/qmdnsengine/include/message.h"
|
||||
#include "../Network/mdns/qmdnsengine/include/query.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/server.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/hostname.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/provider.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/service.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/message.h"
|
||||
//#include "../Network/mdns/qmdnsengine/include/query.h"
|
||||
|
||||
#define TEST_UDP_BROADCAST 0 // 用于测试 UDP 组播实现 mdns 功能 非标准 mdns
|
||||
#define MANUAL_UPLOAD_LICENSE 0 // 打开手动上传 License的功能
|
||||
|
@ -70,6 +77,12 @@
|
|||
|
||||
#define NEW_MAP 1
|
||||
|
||||
|
||||
#define FACTORY_ID "TEST" // 工厂ID
|
||||
#define LABEL "TEST_SL100_20240826" // 出货标签
|
||||
#define BATCH 1 // 出货批次
|
||||
#define MODEL "SL100" // 出货型号
|
||||
|
||||
class MainWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -79,6 +92,8 @@ public:
|
|||
explicit MainWidget(QWidget* parent = nullptr);
|
||||
~MainWidget();
|
||||
|
||||
void startHttpServer(const QString& imagePath);
|
||||
|
||||
signals:
|
||||
void openFocusWindowRequested(int itemIndex);
|
||||
|
||||
|
@ -86,6 +101,8 @@ private slots:
|
|||
// 发送HTTP请求
|
||||
//void onSomeButtonClicked();
|
||||
// 处理HTTP响应
|
||||
// 启动图片共享服务
|
||||
void onStartImageSharing(int width, int height, QString img_type, std::function<void(QString)> callback);
|
||||
void onHttpRequestFinished(const QJsonObject& response);
|
||||
// 处理HTTP错误
|
||||
void onHttpRequestError(const QString& errorString);
|
||||
|
@ -187,11 +204,13 @@ private:
|
|||
QJsonArray frontBoardFuncConfig; // 前板功能配置参数 JSON
|
||||
QJsonArray frontBoardDevInfoJson; // 前板设备信息参数 JSON
|
||||
QJsonArray frontBoardLicenseJson; // 前板License JSON
|
||||
QJsonArray frontBoardCmdConfigJson;
|
||||
QJsonArray backBoardOneClickTest; // 后板一键功能测试 JSON
|
||||
QJsonArray backBoardTest; // 后板单项测试 JSON
|
||||
QJsonArray backBoardFuncConfig; // 后板功能配置参数 JSON
|
||||
QJsonArray backBoardDevInfoJson; // 后板设备信息参数 JSON
|
||||
QJsonArray backBoardUuidJson; // 后板UUID JSON
|
||||
QJsonArray backBoardCmdConfigJson;
|
||||
QJsonArray factoryProductInfo; // 整机:工厂生产信息
|
||||
QJsonArray testJsonConfig; // 功能测试区 JSON 配置
|
||||
QJsonArray funcJsonConfig; // 功能配置区 JSON 配置
|
||||
|
@ -213,6 +232,7 @@ private:
|
|||
bool deviceConnected = false; // 判断是否有设备连接过
|
||||
bool isSendingAll; // 一键功能测试 状态
|
||||
bool checkBoxState = true;
|
||||
bool isReplyOrTimeout = true;
|
||||
|
||||
QJsonObject licenseDataArray; // 用于保存从服务器获取的 data 字段对象
|
||||
|
||||
|
@ -266,7 +286,7 @@ private:
|
|||
QMap<int, QTimer*> clientReadTimers;
|
||||
QMap<int, ClientHandler*> clients_1;
|
||||
|
||||
ServiceProvider* mServiceProvider;
|
||||
//ServiceProvider* mServiceProvider;
|
||||
QTimer* mdnsTimer;
|
||||
void startMdnsService();
|
||||
void stopMdnsService();
|
||||
|
@ -274,6 +294,14 @@ private:
|
|||
QUdpSocket* multicastSocket;
|
||||
QTimer* multicastTimer;
|
||||
#endif
|
||||
|
||||
QTcpServer* httpServer; // HTTP 服务器
|
||||
QString imagePath; // 当前选择的图片路径
|
||||
quint16 serverPort = 8080; // HTTP 服务器端口
|
||||
|
||||
void setupHttpServer(); // 初始化 HTTP 服务器
|
||||
void handleHttpRequest(QTcpSocket* clientSocket); // 处理 HTTP 请求
|
||||
MdnsServiceThread* mdnsThread; // mDNS 线程指针
|
||||
};
|
||||
|
||||
#endif // MAINWIDGET_H
|
||||
|
|
|
@ -41,10 +41,12 @@ UI_config loadConfig(const QString& filePath)
|
|||
{
|
||||
UI_config config;
|
||||
QMap<QString, QString> settings = parseIniFile(filePath);
|
||||
|
||||
// 可直接修改 UI_config.ini 文件
|
||||
// 如果删除 UI_config.ini 文件中的 Labels 项,则使用如下代码的默认命名配置
|
||||
// Labels 项 默认命名配置
|
||||
config.SL100_FACTORY_TOOL_W = settings.value("Window/width", "1340").toInt();
|
||||
config.SL100_FACTORY_TOOL_H = settings.value("Window/height", "900").toInt();
|
||||
config.TOOL_VERSION = settings.value("Labels/tool_version", "SL100 工厂产测工具 - V0.0.8");
|
||||
config.TOOL_VERSION = settings.value("Labels/tool_version", "SL100 工厂产测工具 - V0.0.10");
|
||||
config.START_LISTENING = settings.value("Labels/start_listening", "开始监听\n(Start Listening...)");
|
||||
config.ONE_CLICKED_TEST = settings.value("Labels/one_clicked_test", "一键功能测试");
|
||||
config.FRONT_BOARD_NAME = settings.value("Labels/front_board_name", "前 板");
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
device ID: 1 - Item 2: 停止视频 ---> OK
|
||||
device ID: 1 - Item 2: 停止视频 ---> OK
|
||||
device ID: 1 - Item 2: 停止视频 ---> OK
|
||||
device ID: 1 - Item 2: 停止视频 ---> OK
|
||||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 1: get_hw_info ---> OK
|
||||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 2: 人脸多角度注册 ---> NG
|
||||
device ID: 1 - Item 3: 掌静脉注册 ---> NG
|
||||
device ID: 1 - Item 4: 人脸识别 ---> NG
|
||||
device ID: 1 - Item 5: 掌静脉识别 ---> NG
|
||||
device ID: 1 - Item 6: 删除用户 ---> NG
|
||||
device ID: 1 - Item 7: 删除所有用户 ---> NG
|
||||
device ID: 1 - Item 8: 获取用户 ---> NG
|
||||
device ID: 1 - Item 9: 获取所有用户 ---> NG
|
||||
device ID: 1 - Item 10: 密码注册 ---> NG
|
||||
device ID: 1 - Item 11: 图片注册 ---> NG
|
||||
device ID: 1 - Item 12: 左边镜头取图 ---> OK
|
||||
device ID: 1 - Item 13: 右边镜头取图 ---> OK
|
||||
device ID: 1 - Item 14: 前触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 15: MIC测试 ---> NG
|
||||
device ID: 1 - Item 16: SPK测试 ---> NG
|
||||
device ID: 1 - Item 17: 雷达测试 ---> NG
|
||||
device ID: 1 - Item 18: NFC测试 ---> NG
|
||||
device ID: 1 - Item 19: 防撬开关 ---> NG
|
||||
device ID: 1 - Item 20: 光敏测试 ---> NG
|
||||
device ID: 1 - Item 21: 前屏背光测试 ---> NG
|
||||
device ID: 1 - Item 22: IR灯开 ---> OK
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 25: PIR测试 ---> NG
|
||||
device ID:-1 ---> All 25 items test completed !!!
|
|
@ -1,18 +0,0 @@
|
|||
device ID: 1 - Item 1: V851测试SPK ---> NG
|
||||
device ID: 1 - Item 2: 806测试SPK ---> NG
|
||||
device ID: 1 - Item 3: MIC测试 ---> NG
|
||||
device ID: 1 - Item 4: 开锁测试 ---> NG
|
||||
device ID: 1 - Item 5: 关锁测试 ---> NG
|
||||
device ID: 1 - Item 6: 开锁按键测试 ---> NG
|
||||
device ID: 1 - Item 7: 关锁按键测试 ---> NG
|
||||
device ID: 1 - Item 8: 猫眼按键测试 ---> NG
|
||||
device ID: 1 - Item 9: 后屏背光测试 ---> NG
|
||||
device ID: 1 - Item 10: 后触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 11: 开猫眼测试 ---> NG
|
||||
device ID: 1 - Item 12: 串口测试 ---> NG
|
||||
device ID: 1 - Item 13: 开启视频 ---> NG
|
||||
device ID: 1 - Item 14: 关闭视频 ---> NG
|
||||
device ID: 1 - Item 15: wifi信号测试 ---> NG
|
||||
device ID: 1 - Item 16: 进入配网测试 ---> NG
|
||||
device ID: 1 - Item 17: 联网测试 ---> NG
|
||||
device ID:-1 ---> All 17 items test completed !!!
|
|
@ -1,26 +0,0 @@
|
|||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 2: 人脸多角度注册 ---> NG
|
||||
device ID: 1 - Item 3: 掌静脉注册 ---> NG
|
||||
device ID: 1 - Item 4: 人脸识别 ---> NG
|
||||
device ID: 1 - Item 5: 掌静脉识别 ---> NG
|
||||
device ID: 1 - Item 6: 删除用户 ---> NG
|
||||
device ID: 1 - Item 7: 删除所有用户 ---> NG
|
||||
device ID: 1 - Item 8: 获取用户 ---> NG
|
||||
device ID: 1 - Item 9: 获取所有用户 ---> NG
|
||||
device ID: 1 - Item 10: 密码注册 ---> NG
|
||||
device ID: 1 - Item 11: 图片注册 ---> NG
|
||||
device ID: 1 - Item 12: 左边镜头取图 ---> OK
|
||||
device ID: 1 - Item 13: 右边镜头取图 ---> OK
|
||||
device ID: 1 - Item 14: 前触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 15: MIC测试 ---> NG
|
||||
device ID: 1 - Item 16: SPK测试 ---> NG
|
||||
device ID: 1 - Item 17: 雷达测试 ---> NG
|
||||
device ID: 1 - Item 18: NFC测试 ---> NG
|
||||
device ID: 1 - Item 19: 防撬开关 ---> NG
|
||||
device ID: 1 - Item 20: 光敏测试 ---> NG
|
||||
device ID: 1 - Item 21: 前屏背光测试 ---> NG
|
||||
device ID: 1 - Item 22: IR灯开 ---> OK
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 25: PIR测试 ---> NG
|
||||
device ID:-1 ---> All 25 items test completed !!!
|
|
@ -1,26 +0,0 @@
|
|||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 2: 人脸多角度注册 ---> NG
|
||||
device ID: 1 - Item 3: 掌静脉注册 ---> NG
|
||||
device ID: 1 - Item 4: 人脸识别 ---> NG
|
||||
device ID: 1 - Item 5: 掌静脉识别 ---> NG
|
||||
device ID: 1 - Item 6: 删除用户 ---> NG
|
||||
device ID: 1 - Item 7: 删除所有用户 ---> NG
|
||||
device ID: 1 - Item 8: 获取用户 ---> NG
|
||||
device ID: 1 - Item 9: 获取所有用户 ---> NG
|
||||
device ID: 1 - Item 10: 密码注册 ---> NG
|
||||
device ID: 1 - Item 11: 图片注册 ---> NG
|
||||
device ID: 1 - Item 12: 左边镜头取图 ---> OK
|
||||
device ID: 1 - Item 13: 右边镜头取图 ---> OK
|
||||
device ID: 1 - Item 14: 前触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 15: MIC测试 ---> NG
|
||||
device ID: 1 - Item 16: SPK测试 ---> NG
|
||||
device ID: 1 - Item 17: 雷达测试 ---> NG
|
||||
device ID: 1 - Item 18: NFC测试 ---> NG
|
||||
device ID: 1 - Item 19: 防撬开关 ---> NG
|
||||
device ID: 1 - Item 20: 光敏测试 ---> NG
|
||||
device ID: 1 - Item 21: 前屏背光测试 ---> NG
|
||||
device ID: 1 - Item 22: IR灯开 ---> OK
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 25: PIR测试 ---> NG
|
||||
device ID:-1 ---> All 25 items test completed !!!
|
|
@ -1,32 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
||||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 2: 人脸多角度注册 ---> NG
|
||||
device ID: 1 - Item 3: 掌静脉注册 ---> NG
|
||||
device ID: 1 - Item 4: 人脸识别 ---> NG
|
||||
device ID: 1 - Item 5: 掌静脉识别 ---> NG
|
||||
device ID: 1 - Item 6: 删除用户 ---> NG
|
||||
device ID: 1 - Item 7: 删除所有用户 ---> NG
|
||||
device ID: 1 - Item 8: 获取用户 ---> NG
|
||||
device ID: 1 - Item 9: 获取所有用户 ---> NG
|
||||
device ID: 1 - Item 10: 密码注册 ---> NG
|
||||
device ID: 1 - Item 11: 图片注册 ---> NG
|
||||
device ID: 1 - Item 12: 左边镜头取图 ---> OK
|
||||
device ID: 1 - Item 13: 右边镜头取图 ---> OK
|
||||
device ID: 1 - Item 14: 前触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 15: MIC测试 ---> NG
|
||||
device ID: 1 - Item 16: SPK测试 ---> NG
|
||||
device ID: 1 - Item 17: 雷达测试 ---> NG
|
||||
device ID: 1 - Item 18: NFC测试 ---> NG
|
||||
device ID: 1 - Item 19: 防撬开关 ---> NG
|
||||
device ID: 1 - Item 20: 光敏测试 ---> NG
|
||||
device ID: 1 - Item 21: 前屏背光测试 ---> NG
|
||||
device ID: 1 - Item 22: IR灯开 ---> OK
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 25: PIR测试 ---> NG
|
||||
device ID:-1 ---> All 25 items test completed !!!
|
|
@ -1,9 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,32 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
||||
device ID: 1 - Item 1: 人脸单角度注册 ---> NG
|
||||
device ID: 1 - Item 2: 人脸多角度注册 ---> NG
|
||||
device ID: 1 - Item 3: 掌静脉注册 ---> NG
|
||||
device ID: 1 - Item 4: 人脸识别 ---> NG
|
||||
device ID: 1 - Item 5: 掌静脉识别 ---> NG
|
||||
device ID: 1 - Item 6: 删除用户 ---> NG
|
||||
device ID: 1 - Item 7: 删除所有用户 ---> NG
|
||||
device ID: 1 - Item 8: 获取用户 ---> NG
|
||||
device ID: 1 - Item 9: 获取所有用户 ---> NG
|
||||
device ID: 1 - Item 10: 密码注册 ---> NG
|
||||
device ID: 1 - Item 11: 图片注册 ---> NG
|
||||
device ID: 1 - Item 12: 左边镜头取图 ---> OK
|
||||
device ID: 1 - Item 13: 右边镜头取图 ---> OK
|
||||
device ID: 1 - Item 14: 前触摸屏测试 ---> NG
|
||||
device ID: 1 - Item 15: MIC测试 ---> NG
|
||||
device ID: 1 - Item 16: SPK测试 ---> NG
|
||||
device ID: 1 - Item 17: 雷达测试 ---> NG
|
||||
device ID: 1 - Item 18: NFC测试 ---> NG
|
||||
device ID: 1 - Item 19: 防撬开关 ---> NG
|
||||
device ID: 1 - Item 20: 光敏测试 ---> NG
|
||||
device ID: 1 - Item 21: 前屏背光测试 ---> NG
|
||||
device ID: 1 - Item 22: IR灯开 ---> OK
|
||||
device ID: 1 - Item 23: IR灯关 ---> OK
|
||||
device ID: 1 - Item 24: 串口测试 ---> NG
|
||||
device ID: 1 - Item 25: PIR测试 ---> NG
|
||||
device ID:-1 ---> All 25 items test completed !!!
|
|
@ -1,7 +0,0 @@
|
|||
device ID: 1 - Item 1: 启动视频 ---> NG
|
||||
device ID: 3 - Item 1: 启动视频 ---> OK
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,7 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 3 - Item 1: 启动视频 ---> OK
|
||||
device ID: 1 - Item 1: 启动视频 ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,10 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
||||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -1,4 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> OK
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> OK
|
||||
device ID: 1 - Item 4: 算法版本: ---> OK
|
||||
device ID: 1 - Item 5: SN号: ---> OK
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> OK
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> OK
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> OK
|
||||
device ID: 1 - Item 4: 算法版本: ---> OK
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> OK
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> OK
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> OK
|
||||
device ID: 1 - Item 4: 算法版本: ---> OK
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> OK
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> OK
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> OK
|
||||
device ID: 1 - Item 4: 算法版本: ---> OK
|
||||
device ID: 1 - Item 5: SN号: ---> OK
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,6 +0,0 @@
|
|||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -1,7 +0,0 @@
|
|||
No device is connected !!!
|
||||
device ID: 1 - Item 1: 前板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 前板MCU版本: ---> NG
|
||||
device ID: 1 - Item 3: 前板硬件版本: ---> NG
|
||||
device ID: 1 - Item 4: 算法版本: ---> NG
|
||||
device ID: 1 - Item 5: SN号: ---> NG
|
||||
device ID:-1 ---> All 5 items test completed !!!
|
|
@ -0,0 +1,8 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
||||
device ID: 2 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 2 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 2 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-2 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
|
@ -0,0 +1,4 @@
|
|||
device ID: 1 - Item 1: 后板V851版本: ---> NG
|
||||
device ID: 1 - Item 2: 后板806版本: ---> NG
|
||||
device ID: 1 - Item 3: 后板硬件版本: ---> NG
|
||||
device ID:-1 ---> All 3 items test completed !!!
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue