From b59c6c743d245e24c826543743d4219b4a164c1a Mon Sep 17 00:00:00 2001 From: Duc Date: Fri, 14 Mar 2025 07:47:07 -0700 Subject: [PATCH] Initial check-in --- .gitattributes | 63 +++ .gitignore | 368 +++++++++++++++++- HWIL_Assistant/HWIL_Assistant_Linux.pro | 129 ++++++ .../git_scripts/ignore_a_tracked_file.sh | 11 + .../list_tracked_files_under_master_branch.sh | 3 + .../git_scripts/unignore_a_tracked_file.sh | 11 + HWIL_Assistant/readme.txt | 4 + .../AreYouThereCmdMessage.cpp | 106 +++++ .../AreYouThereCmdMessage.hpp | 118 ++++++ .../AreYouThereRspMessage.cpp | 106 +++++ .../AreYouThereRspMessage.hpp | 120 ++++++ .../AutomationMsgHandler.cpp | 177 +++++++++ .../AutomationMsgHandler.hpp | 114 ++++++ .../AutomationMsgParser.cpp | 168 ++++++++ .../AutomationMsgParser.hpp | 94 +++++ .../AutomationMessages/GenericRspMessage.cpp | 103 +++++ .../AutomationMessages/GenericRspMessage.hpp | 138 +++++++ .../KwScenarioStartedMessage.cpp | 146 +++++++ .../KwScenarioStartedMessage.hpp | 134 +++++++ .../KwScenarioStoppedMessage.cpp | 208 ++++++++++ .../KwScenarioStoppedMessage.hpp | 132 +++++++ .../src/AutomationMessages/Message.cpp | 175 +++++++++ .../src/AutomationMessages/Message.hpp | 257 ++++++++++++ .../src/AutomationMessages/MessageHeader.cpp | 86 ++++ .../src/AutomationMessages/MessageHeader.hpp | 163 ++++++++ .../src/AutomationMessages/MessageIDs.hpp | 33 ++ .../WaitForLastTaskCompletionCmdMessage.cpp | 83 ++++ .../WaitForLastTaskCompletionCmdMessage.hpp | 121 ++++++ HWIL_Assistant/src/Comm/UdpSocket.cpp | 201 ++++++++++ HWIL_Assistant/src/Comm/UdpSocket.hpp | 97 +++++ HWIL_Assistant/src/Comm/UdpSocketMgr.cpp | 95 +++++ HWIL_Assistant/src/Comm/UdpSocketMgr.hpp | 100 +++++ HWIL_Assistant/src/Common/Constants.cpp | 3 + HWIL_Assistant/src/Common/Constants.hpp | 32 ++ HWIL_Assistant/src/Common/Util.cpp | 159 ++++++++ HWIL_Assistant/src/Common/Util.hpp | 52 +++ .../src/Config/ConfigFileManager.cpp | 69 ++++ .../src/Config/ConfigFileManager.hpp | 122 ++++++ HWIL_Assistant/src/Config/config.ini | 68 ++++ HWIL_Assistant/src/LinuxProc.cpp | 320 +++++++++++++++ HWIL_Assistant/src/LinuxProc.hpp | 165 ++++++++ .../src/Misc/GUTS_Assistant.desktop | 10 + HWIL_Assistant/src/Misc/assistant.png | Bin 0 -> 35063 bytes .../src/Threads/FileTransferThread.cpp | 319 +++++++++++++++ .../src/Threads/FileTransferThread.hpp | 207 ++++++++++ .../src/Threads/NetworkingThread.cpp | 40 ++ .../src/Threads/NetworkingThread.hpp | 63 +++ HWIL_Assistant/src/Threads/RunAppThread.cpp | 168 ++++++++ HWIL_Assistant/src/Threads/RunAppThread.hpp | 111 ++++++ HWIL_Assistant/src/UI/FileTransferDialog.cpp | 133 +++++++ HWIL_Assistant/src/UI/FileTransferDialog.hpp | 188 +++++++++ HWIL_Assistant/src/UI/FileTransferDialog.ui | 240 ++++++++++++ HWIL_Assistant/src/UI/MainWindow.cpp | 102 +++++ HWIL_Assistant/src/UI/MainWindow.h | 36 ++ HWIL_Assistant/src/UI/mainwindow.ui | 42 ++ HWIL_Assistant/src/main.cpp | 43 ++ 56 files changed, 6547 insertions(+), 9 deletions(-) create mode 100644 .gitattributes create mode 100644 HWIL_Assistant/HWIL_Assistant_Linux.pro create mode 100644 HWIL_Assistant/git_scripts/ignore_a_tracked_file.sh create mode 100644 HWIL_Assistant/git_scripts/list_tracked_files_under_master_branch.sh create mode 100644 HWIL_Assistant/git_scripts/unignore_a_tracked_file.sh create mode 100644 HWIL_Assistant/readme.txt create mode 100644 HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/GenericRspMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/GenericRspMessage.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/Message.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/Message.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/MessageHeader.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/MessageHeader.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/MessageIDs.hpp create mode 100644 HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.cpp create mode 100644 HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.hpp create mode 100644 HWIL_Assistant/src/Comm/UdpSocket.cpp create mode 100644 HWIL_Assistant/src/Comm/UdpSocket.hpp create mode 100644 HWIL_Assistant/src/Comm/UdpSocketMgr.cpp create mode 100644 HWIL_Assistant/src/Comm/UdpSocketMgr.hpp create mode 100644 HWIL_Assistant/src/Common/Constants.cpp create mode 100644 HWIL_Assistant/src/Common/Constants.hpp create mode 100644 HWIL_Assistant/src/Common/Util.cpp create mode 100644 HWIL_Assistant/src/Common/Util.hpp create mode 100644 HWIL_Assistant/src/Config/ConfigFileManager.cpp create mode 100644 HWIL_Assistant/src/Config/ConfigFileManager.hpp create mode 100644 HWIL_Assistant/src/Config/config.ini create mode 100644 HWIL_Assistant/src/LinuxProc.cpp create mode 100644 HWIL_Assistant/src/LinuxProc.hpp create mode 100644 HWIL_Assistant/src/Misc/GUTS_Assistant.desktop create mode 100644 HWIL_Assistant/src/Misc/assistant.png create mode 100644 HWIL_Assistant/src/Threads/FileTransferThread.cpp create mode 100644 HWIL_Assistant/src/Threads/FileTransferThread.hpp create mode 100644 HWIL_Assistant/src/Threads/NetworkingThread.cpp create mode 100644 HWIL_Assistant/src/Threads/NetworkingThread.hpp create mode 100644 HWIL_Assistant/src/Threads/RunAppThread.cpp create mode 100644 HWIL_Assistant/src/Threads/RunAppThread.hpp create mode 100644 HWIL_Assistant/src/UI/FileTransferDialog.cpp create mode 100644 HWIL_Assistant/src/UI/FileTransferDialog.hpp create mode 100644 HWIL_Assistant/src/UI/FileTransferDialog.ui create mode 100644 HWIL_Assistant/src/UI/MainWindow.cpp create mode 100644 HWIL_Assistant/src/UI/MainWindow.h create mode 100644 HWIL_Assistant/src/UI/mainwindow.ui create mode 100644 HWIL_Assistant/src/main.cpp diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore index c674098..2f8bb17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,365 @@ -# ---> Linux +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +/HWIL_Assistant/src/CommonLib/ + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* *~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk -# KDE directory preferences -.directory +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ -# Linux trash folder which might appear on any partition or disk -.Trash-* +# RIA/Silverlight projects +Generated_Code/ -# .nfs files are created when an open file is removed but is still being accessed -.nfs* +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd diff --git a/HWIL_Assistant/HWIL_Assistant_Linux.pro b/HWIL_Assistant/HWIL_Assistant_Linux.pro new file mode 100644 index 0000000..b2e9070 --- /dev/null +++ b/HWIL_Assistant/HWIL_Assistant_Linux.pro @@ -0,0 +1,129 @@ +QT += core gui +QT += network +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG(debug, debug|release){ + DESTDIR = build_x64_debug +} else { + DESTDIR = build_x64_release +} + +OBJECTS_DIR = $${DESTDIR}/OBJ +MOC_DIR = $${DESTDIR}/MOC +RCC_DIR = $${DESTDIR}/RCC +UI_DIR = $${DESTDIR}/UI + +TARGET = HWIL_Assistant +CONFIG += c++11 + +DEFINES += LINUX_PLATFORM + +QT += testlib + +SOURCES += \ + src/Comm/UdpSocketMgr.cpp \ + src/AutomationMessages/AreYouThereCmdMessage.cpp \ + src/AutomationMessages/AreYouThereRspMessage.cpp \ + src/AutomationMessages/AutomationMsgHandler.cpp \ + src/AutomationMessages/AutomationMsgParser.cpp \ + src/AutomationMessages/GenericRspMessage.cpp \ + src/AutomationMessages/KwScenarioStartedMessage.cpp \ + src/AutomationMessages/KwScenarioStoppedMessage.cpp \ + src/AutomationMessages/Message.cpp \ + src/AutomationMessages/MessageHeader.cpp \ + src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.cpp \ + src/Comm/UdpSocket.cpp \ + src/CommonLib/Exceptions/Exception.cpp \ + src/CommonLib/Exceptions/TimeoutError.cpp \ + src/CommonLib/Lib/Condition.cpp \ + src/Common/Constants.cpp \ + src/CommonLib/Lib/ErrorLog.cpp \ + src/CommonLib/Lib/EventNames.cpp \ + src/CommonLib/Lib/IniFile.cpp \ + src/CommonLib/Lib/LockMutex.cpp \ + src/CommonLib/Lib/Mutex.cpp \ + src/CommonLib/Lib/OSObject.cpp \ + src/CommonLib/Lib/Util/DateTimeUtil.cpp \ + src/CommonLib/Lib/Util/FileSystemUtil.cpp \ + src/CommonLib/Lib/Util/MiscUtil.cpp \ + src/CommonLib/Lib/Util/StringUtil.cpp \ + src/CommonLib/Proc/Proc.cpp \ + src/CommonLib/Lib/Timestamp.cpp \ + src/Common/Util.cpp \ + src/CommonLib/Threading/Thread.cpp \ + src/Config/ConfigFileManager.cpp \ + src/LinuxProc.cpp \ + src/Threads/FileTransferThread.cpp \ + src/Threads/NetworkingThread.cpp \ + src/Threads/RunAppThread.cpp \ + src/UI/FileTransferDialog.cpp \ + src/UI/MainWindow.cpp \ + src/main.cpp \ + +HEADERS += \ + src/Comm/UdpSocketMgr.hpp \ + src/AutomationMessages/AreYouThereCmdMessage.hpp \ + src/AutomationMessages/AreYouThereRspMessage.hpp \ + src/AutomationMessages/AutomationMsgHandler.hpp \ + src/AutomationMessages/AutomationMsgParser.hpp \ + src/AutomationMessages/GenericRspMessage.hpp \ + src/AutomationMessages/KwScenarioStartedMessage.hpp \ + src/AutomationMessages/KwScenarioStoppedMessage.hpp \ + src/AutomationMessages/Message.hpp \ + src/AutomationMessages/MessageHeader.hpp \ + src/AutomationMessages/MessageIDs.hpp \ + src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.hpp \ + src/Comm/UdpSocket.hpp \ + src/CommonLib/Exceptions/Exception.hpp \ + src/CommonLib/Exceptions/TimeoutError.hpp \ + src/CommonLib/Lib/Condition.hpp \ + src/Common/Constants.hpp \ + src/CommonLib/Lib/CustomDataTypes.hpp \ + src/CommonLib/Lib/ErrorLog.hpp \ + src/CommonLib/Lib/EventNames.hpp \ + src/CommonLib/Lib/IniFile.hpp \ + src/CommonLib/Lib/LockMutex.hpp \ + src/CommonLib/Lib/Mutex.hpp \ + src/CommonLib/Lib/OSObject.hpp \ + src/CommonLib/Lib/Util/DateTimeUtil.hpp \ + src/CommonLib/Lib/Util/FileSystemUtil.hpp \ + src/CommonLib/Lib/Util/MiscUtil.hpp \ + src/CommonLib/Lib/Util/StringUtil.hpp \ + src/CommonLib/Proc/Proc.hpp \ + src/CommonLib/Lib/Timestamp.hpp \ + src/Common/Util.hpp \ + src/CommonLib/Threading/Thread.hpp \ + src/Config/ConfigFileManager.hpp \ + src/LinuxProc.hpp \ + src/Threads/FileTransferThread.hpp \ + src/Threads/NetworkingThread.hpp \ + src/Threads/RunAppThread.hpp \ + src/UI/FileTransferDialog.hpp \ + src/UI/MainWindow.h + +FORMS += \ + src/UI/FileTransferDialog.ui \ + src/UI/mainwindow.ui + +INCLUDEPATH += src/ \ + src/UI/ \ + src/Computers/ \ + src/Comm/ \ + src/Config/ \ + src/Threads/ \ + src/CommonLib/Comm/ \ + src/CommonLib/Exceptions/ \ + src/CommonLib/Lib/ \ + src/CommonLib/Lib/Util/ \ + src/CommonLib/Proc/ \ + src/CommonLib/Threading/ \ + src/Common/ \ + src/AutomationMessages/ + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +DISTFILES += \ + src/Config/config.ini diff --git a/HWIL_Assistant/git_scripts/ignore_a_tracked_file.sh b/HWIL_Assistant/git_scripts/ignore_a_tracked_file.sh new file mode 100644 index 0000000..06dc9d6 --- /dev/null +++ b/HWIL_Assistant/git_scripts/ignore_a_tracked_file.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +length=${#1}; + +if [[ $length -eq 0 ]] +then + echo "Please specify a tracked file to ignore"; + exit 1 +fi + +git update-index --skip-worktree $1 diff --git a/HWIL_Assistant/git_scripts/list_tracked_files_under_master_branch.sh b/HWIL_Assistant/git_scripts/list_tracked_files_under_master_branch.sh new file mode 100644 index 0000000..4f89f50 --- /dev/null +++ b/HWIL_Assistant/git_scripts/list_tracked_files_under_master_branch.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +git ls-tree -r master --name-only diff --git a/HWIL_Assistant/git_scripts/unignore_a_tracked_file.sh b/HWIL_Assistant/git_scripts/unignore_a_tracked_file.sh new file mode 100644 index 0000000..4415a6c --- /dev/null +++ b/HWIL_Assistant/git_scripts/unignore_a_tracked_file.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +length=${#1}; + +if [[ $length -eq 0 ]] +then + echo "Please specify a tracked file to ignore"; + exit 1 +fi + +git update-index --no-skip-worktree $1 diff --git a/HWIL_Assistant/readme.txt b/HWIL_Assistant/readme.txt new file mode 100644 index 0000000..45010fc --- /dev/null +++ b/HWIL_Assistant/readme.txt @@ -0,0 +1,4 @@ +Before building, go to project settings -> Build Settings and disable Shadow Build +Shadow Build will put all build output files in a location outside of project folder relative to home directory + +This project is set to output files in the project folder so we can easily locate the files diff --git a/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.cpp b/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.cpp new file mode 100644 index 0000000..9b3edef --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.cpp @@ -0,0 +1,106 @@ +#include +#include +#include "AreYouThereCmdMessage.hpp" +#include "Exception.hpp" +#include "Util.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "AreYouThereRspMessage.hpp" +#include "Condition.hpp" +#include "UdpSocketMgr.hpp" + +#include +#include +#include +#include +//------------------------------------------------------------------------ + +AreYouThereCmdMessage::AreYouThereCmdMessage(): + Message(MessageIDs::ARE_YOU_THERE_CMD, "ARE_YOU_THERE_CMD") +{ +} + +//------------------------------------------------------------------------ + +AreYouThereCmdMessage::AreYouThereCmdMessage(const AreYouThereCmdMessage& copy) : + Message(copy) +{ +} + +//------------------------------------------------------------------------ + +AreYouThereCmdMessage::~AreYouThereCmdMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* AreYouThereCmdMessage::cloneSelf() +{ + AreYouThereCmdMessage* pMsg = new AreYouThereCmdMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void AreYouThereCmdMessage::executeMessage() +{ + try + { + Condition& commandExecutingEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTTION_IN_PROGRESS); + Condition& completeEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE); + + completeEvent.reset(); + if (commandExecutingEvent.timedWait(0,0)) // a command is current executing + { + completeEvent.wait(); // wait until current command finish executing + } + + // signal this command is currently executing to prevent any other command from executing + commandExecutingEvent.signal(); + + AreYouThereRspMessage rsp(QCoreApplication::applicationFilePath().toStdString()); + + UdpSocketMgr::Instance().sendAMessage(rsp); + + commandExecutingEvent.reset(); + completeEvent.signal(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void AreYouThereCmdMessage::formatData(unsigned char* pData) +{ + // Here's how the data is formatted + // each data item is preceded by a 4-byte header which tells us the size of the data item + // 1 data item will have [header][data] + // 2 data items will have [header][data][header][data] + unsigned int dataLen = 0; + + // we want update total size of the entire message + m_header.setMessageLength(static_cast(dataLen)); + m_header.format(pData); +} + +//------------------------------------------------------------------------ + +void AreYouThereCmdMessage::parseData(const unsigned char*) +{ +} + +//------------------------------------------------------------------------ + +std::string AreYouThereCmdMessage::toString() const +{ + std::stringstream ss; + + ss << Message::toString() << ". No member data"; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.hpp b/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.hpp new file mode 100644 index 0000000..e0a7fb4 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AreYouThereCmdMessage.hpp @@ -0,0 +1,118 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class AreYouThereCmdMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: AreYouThereCmdMessage + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AreYouThereCmdMessage(); + + //>--------------------------------------------------------------------------- + // Function: AreYouThereCmdMessage + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AreYouThereCmdMessage(const AreYouThereCmdMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~AreYouThereCmdMessage + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~AreYouThereCmdMessage(); + + //>--------------------------------------------------------------------------- + // Function: ExecuteMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: ToString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + +protected: + //>--------------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char* pData); + +private: + // do not allow + AreYouThereCmdMessage &operator=(const AreYouThereCmdMessage &rhs); +}; diff --git a/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.cpp b/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.cpp new file mode 100644 index 0000000..9871751 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.cpp @@ -0,0 +1,106 @@ +#include +#include +#include "AreYouThereRspMessage.hpp" +#include "Exception.hpp" +#include "StringUtil.hpp" +#include "MiscUtil.hpp" +#include "FileSystemUtil.hpp" +#include "Proc.hpp" +#include "IniFile.hpp" +#include "GenericRspMessage.hpp" +#include "Condition.hpp" +#include "Proc.hpp" +#include "UdpSocketMgr.hpp" + +#include +#include +#include +#include +//------------------------------------------------------------------------ + +AreYouThereRspMessage::AreYouThereRspMessage(std::string appPath): + Message(MessageIDs::ARE_YOU_THERE_RSP, "ARE_YOU_THERE_RSP"), + m_appPath(appPath) +{ +} + +//------------------------------------------------------------------------ + +AreYouThereRspMessage::AreYouThereRspMessage(const AreYouThereRspMessage& copy) : + Message(copy), + m_appPath(copy.m_appPath) +{ +} + +//------------------------------------------------------------------------ + +AreYouThereRspMessage::~AreYouThereRspMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* AreYouThereRspMessage::cloneSelf() +{ + AreYouThereRspMessage* pMsg = new AreYouThereRspMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void AreYouThereRspMessage::executeMessage() +{ + std::map users = Util::Misc::GetUsersOfRunningProcess(Util::FileSystem::ExtractFilename(m_appPath)); + // an instance of the this app is already running, we want to quit this instance + throw Exception(Q_FUNC_INFO, "An instance of this application is already running by " + users.begin()->second + " (PID: " + users.begin()->first + ")"); +} + +//------------------------------------------------------------------------ + +void AreYouThereRspMessage::formatData(unsigned char* pData) +{ + // Here's how the data is formatted + // each data item is preceded by a 4-byte header which tells us the size of the data item + // 1 data item will have [header][data] + // 2 data items will have [header][data][header][data] + unsigned int dataLen = 0; + const unsigned char* pTempDataStart = pData + getHeaderLength(); + + buildByteArray(&pTempDataStart, m_appPath.c_str(), m_appPath.length(), dataLen); + + // we want update total size of the entire message + m_header.setMessageLength(static_cast(dataLen)); + m_header.format(pData); +} + +//------------------------------------------------------------------------ + +void AreYouThereRspMessage::parseData(const unsigned char* pData) +{ + bool selfThrown = false; + const unsigned char* pTempDataStart = pData; + const unsigned char* pTempDataEnd = pData + m_header.getMessageLength() - m_header.getHeaderLength() - 1; + + int sizeOfData = 0; + try { + sizeOfData = getNextDataItem(&pTempDataStart, pTempDataEnd, sizeOfData); + m_appPath = Util::Strings::ByteArrayToString(const_cast(pTempDataStart), sizeOfData); + + } catch (Exception& e) { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//------------------------------------------------------------------------ + +std::string AreYouThereRspMessage::toString() const +{ + std::stringstream ss; + + ss << Message::toString() << "AppPath: " << m_appPath; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.hpp b/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.hpp new file mode 100644 index 0000000..be8c636 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AreYouThereRspMessage.hpp @@ -0,0 +1,120 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class AreYouThereRspMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: AreYouThereRspMessage + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AreYouThereRspMessage(std::string appPath = ""); + + //>--------------------------------------------------------------------------- + // Function: AreYouThereRspMessage + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AreYouThereRspMessage(const AreYouThereRspMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~AreYouThereRspMessage + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~AreYouThereRspMessage(); + + //>--------------------------------------------------------------------------- + // Function: ExecuteMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: ToString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + +protected: + //>--------------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char* pData); + +private: + // do not allow + AreYouThereRspMessage &operator=(const AreYouThereRspMessage &rhs); + + std::string m_appPath; +}; diff --git a/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.cpp b/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.cpp new file mode 100644 index 0000000..d6a6b69 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "AutomationMsgHandler.hpp" +#include "Exception.hpp" +#include "MessageHeader.hpp" +#include "MessageIDs.hpp" +#include "ErrorLog.hpp" +#include "Util.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "GenericRspMessage.hpp" +#include "Condition.hpp" + +#include "AreYouThereCmdMessage.hpp" +#include "WaitForLastTaskCompletionCmdMessage.hpp" +#include "KwScenarioStartedMessage.hpp" +#include "KwScenarioStoppedMessage.hpp" + +//----------------------------------------------------------------------------- + +AutomationMsgHandler::AutomationMsgHandler() +{ +} + +//----------------------------------------------------------------------------- + +AutomationMsgHandler::~AutomationMsgHandler(){} + +//----------------------------------------------------------------------------- + +AutomationMsgHandler& AutomationMsgHandler::instance() +{ + static AutomationMsgHandler handler; + return handler; +} + +//----------------------------------------------------------------------------- + +void AutomationMsgHandler::handleMsg(const unsigned char* pData, const unsigned int& id) +{ + try + { + MessageIDs::MsgIds msgId = (MessageIDs::MsgIds)id; + + if (msgId != MessageIDs::WAIT_FOR_COMPLETION_CMD) + WaitForLastTaskCompletionCmdMessage::s_commandCompletionSuccess = true; + + if (msgId == MessageIDs::ARE_YOU_THERE_CMD) + { + handleAreYouThereMessage(pData); + } + else if (msgId == MessageIDs::SCENARIO_STARTED_CMD) + { + handleKwScenarioStartedCMessage(pData); + } + else if (msgId == MessageIDs::SCENARIO_STOPPED_CMD) + { + handleKwScenarioStoppedCMessage(pData); + } + else if (msgId == MessageIDs::WAIT_FOR_COMPLETION_CMD) + { + handleWaitForLastTaskCompletionMessage(pData); + } + else + { + std::stringstream ss; + ss << "unknown message id: " << id; + + throw Exception (Q_FUNC_INFO, ss.str()); + } + } + catch (Exception& e) + { + LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTTION_IN_PROGRESS).reset(); + LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE).signal(); + + WaitForLastTaskCompletionCmdMessage::s_commandCompletionSuccess = false; + + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgHandler::handleAreYouThereMessage(const unsigned char* pData) +{ + try { + AreYouThereCmdMessage cmd; + + cmd.parse(pData); + + if (LinuxProc::Instance().getConfig().getBool("GENERAL", "VERBOSE_LOGGING")) + ErrorLog::Instance().log(cmd.toString(), false, ErrorLog::INFO); + + cmd.executeMessage(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgHandler::handleKwScenarioStartedCMessage(const unsigned char *pData) +{ + try { + KwScenarioStartedMessage cmd; + + cmd.parse(pData); + + if (LinuxProc::Instance().getConfig().getBool("GENERAL", "VERBOSE_LOGGING")) + ErrorLog::Instance().log(cmd.toString(), false, ErrorLog::INFO); + + cmd.executeMessage(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgHandler::handleKwScenarioStoppedCMessage(const unsigned char *pData) +{ + try { + KwScenarioStoppedMessage cmd; + + cmd.parse(pData); + + if (LinuxProc::Instance().getConfig().getBool("GENERAL", "VERBOSE_LOGGING")) + ErrorLog::Instance().log(cmd.toString(), false, ErrorLog::INFO); + + cmd.executeMessage(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgHandler::handleWaitForLastTaskCompletionMessage(const unsigned char* pData) +{ + try { + WaitForLastTaskCompletionCmdMessage cmd; + + cmd.parse(pData); + + if (LinuxProc::Instance().getConfig().getBool("GENERAL", "VERBOSE_LOGGING")) + ErrorLog::Instance().log(cmd.toString(), false, ErrorLog::INFO); + + cmd.executeMessage(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} diff --git a/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.hpp b/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.hpp new file mode 100644 index 0000000..e78173f --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AutomationMsgHandler.hpp @@ -0,0 +1,114 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "MessageIDs.hpp" +#include + +class AutomationMsgHandler +{ +public: + //>--------------------------------------------------------------------------- + // Function: instance + // + // Purpose: singleton + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + static AutomationMsgHandler& instance(); + + //>--------------------------------------------------------------------------- + // Function: ~Proc + // + // Purpose: Destroyer + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + ~AutomationMsgHandler(); + + //>--------------------------------------------------------------------------- + // Function: parseMsg + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void handleMsg(const unsigned char* pData, const unsigned int& id); + + private: + //>--------------------------------------------------------------------------- + // Function: AutomationMsgHandler + // + // Purpose: Ctor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AutomationMsgHandler(); + + //>--------------------------------------------------------------------------- + // Function: HandleMoveGutsVideosToSubFolderMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void handleAreYouThereMessage(const unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: HandleKwScenarioStartedCMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void handleKwScenarioStartedCMessage(const unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: HandleKwScenarioStoppedCMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void handleKwScenarioStoppedCMessage(const unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: HandleWaitForLastTaskCompletionMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void handleWaitForLastTaskCompletionMessage(const unsigned char* pData); +}; + diff --git a/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.cpp b/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.cpp new file mode 100644 index 0000000..c35b0de --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "AutomationMsgParser.hpp" +#include "Exception.hpp" +#include "MessageHeader.hpp" +#include "MessageIDs.hpp" +#include "ErrorLog.hpp" +#include "StringUtil.hpp" + +//----------------------------------------------------------------------------- + +AutomationMsgParser::AutomationMsgParser() +{ + gatherCmdMessageIds(); +} + +//----------------------------------------------------------------------------- + +AutomationMsgParser::~AutomationMsgParser(){} + +//----------------------------------------------------------------------------- + +AutomationMsgParser& AutomationMsgParser::instance() +{ + static AutomationMsgParser parser; + return parser; +} + +//----------------------------------------------------------------------------- + +void AutomationMsgParser::gatherCmdMessageIds() +{ + try { + msgIdsVec.push_back(MessageIDs::ARE_YOU_THERE_CMD); + msgIdsVec.push_back(MessageIDs::SCENARIO_STARTED_CMD); + msgIdsVec.push_back(MessageIDs::SCENARIO_STOPPED_CMD); + + msgIdsVec.push_back(MessageIDs::WAIT_FOR_COMPLETION_CMD); + msgIdsVec.push_back(MessageIDs::GENERIC_RSP); + msgIdsVec.push_back(MessageIDs::ARE_YOU_THERE_RSP); + + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgParser::parseMsg(unsigned char* pData, unsigned int numBytes, unsigned int* pMsgId) +{ + bool selfThrown = false; + try + { + MessageHeader header; + + if (numBytes < header.getHeaderLength()) + { + std::stringstream ss; + ss << "Number of bytes received: " << numBytes << ". Expected minimum: " << header.getHeaderLength(); + + selfThrown = true; + throw Exception(Q_FUNC_INFO, ss.str()); + } + + // check to see if we recognize the header + unsigned int msgId = 0; + unsigned int msgLen = 0; + + memcpy(&msgId, &pData[0], 4); + memcpy(&msgLen, &pData[4], 4); + + if (std::find(msgIdsVec.begin(), msgIdsVec.end(), msgId) == msgIdsVec.end()) + { + std::stringstream ss; + ss << "unexpected msg id: " << msgId; + + selfThrown = true; + throw Exception(Q_FUNC_INFO, ss.str()); + } + + if ( msgLen != numBytes) + { + std::stringstream ss; + ss << "Number of bytes received: " << numBytes << ". Expected only: " << msgLen; + + selfThrown = true; + throw Exception(Q_FUNC_INFO, ss.str()); + } + + if (numBytes > header.getHeaderLength()) + verifyDataFormat(pData, numBytes); + + *pMsgId = msgId; + } + catch (Exception& e) + { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +void AutomationMsgParser::verifyDataFormat(unsigned char* pData, unsigned int numBytes) +{ + MessageHeader header; + bool selfThrown = false; + unsigned char* pTempDataStart = pData + header.getHeaderLength(); + unsigned char* pTempDataEnd = pData + numBytes - 1; + + // data format is + // [data header - 4 bytes][data - variable size] + // [data header][data][data header][data][data header][data][data header][data] + const unsigned int DATA_HEADER_LENGTH = 4; + + try { + std::stringstream ssError; + + ssError << "Data structure is incorrect. Data: " << Util::Strings::ByteArrayToHexString(pData+header.getHeaderLength(), numBytes - header.getHeaderLength()); + + // want to make sure data size is at least 5 bytes + if (pTempDataStart+DATA_HEADER_LENGTH > pTempDataEnd) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, ssError.str()); + } + + while (pTempDataStart < pTempDataEnd) + { + unsigned int dataSize = *(reinterpret_cast(pTempDataStart)); + + if (dataSize == 0) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, ssError.str()); + + } + + pTempDataStart += DATA_HEADER_LENGTH + dataSize; + + if (pTempDataStart-1 > pTempDataEnd) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, ssError.str()); + } + else if (pTempDataStart-1 == pTempDataEnd) + break; + } + } + catch (Exception& e) + { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + diff --git a/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.hpp b/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.hpp new file mode 100644 index 0000000..bb2808b --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/AutomationMsgParser.hpp @@ -0,0 +1,94 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "MessageIDs.hpp" +#include + +class AutomationMsgParser +{ +public: + //>--------------------------------------------------------------------------- + // Function: instance + // + // Purpose: singleton + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + static AutomationMsgParser& instance(); + + //>--------------------------------------------------------------------------- + // Function: ~Proc + // + // Purpose: Destroyer + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + ~AutomationMsgParser(); + + //>--------------------------------------------------------------------------- + // Function: parseMsg + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void parseMsg(unsigned char* pData, unsigned int numBytes,unsigned int* pMsgId); + + private: + //>--------------------------------------------------------------------------- + // Function: AutomationMsgParser + // + // Purpose: Ctor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + AutomationMsgParser(); + + //>--------------------------------------------------------------------------- + // Function: gatherCmdMessageIds + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void gatherCmdMessageIds(); + + //>--------------------------------------------------------------------------- + // Function: verifyDataFormat + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void verifyDataFormat(unsigned char* pData, unsigned int numBytes); + + std::vector msgIdsVec; +}; + diff --git a/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.cpp b/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.cpp new file mode 100644 index 0000000..bbe5048 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.cpp @@ -0,0 +1,103 @@ +#include +#include +#include "GenericRspMessage.hpp" +#include "Exception.hpp" + +//------------------------------------------------------------------------ + +GenericRspMessage::GenericRspMessage(const bool& wasCommandSuccessful): + Message(MessageIDs::GENERIC_RSP, "GENERIC_RSP", sizeof(MessageStruct)), + m_messageStruct() +{ + m_messageStruct.wasCommandSuccessful = static_cast(wasCommandSuccessful); +} + +//------------------------------------------------------------------------ + +GenericRspMessage::GenericRspMessage(const GenericRspMessage& copy) : + Message(copy), + m_messageStruct(copy.m_messageStruct) +{ +} + +//------------------------------------------------------------------------ + +GenericRspMessage::~GenericRspMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* GenericRspMessage::cloneSelf() +{ + GenericRspMessage* pMsg = new GenericRspMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void GenericRspMessage::executeMessage() +{ + try + { + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void GenericRspMessage::formatData(unsigned char* pData) +{ + // Here's how the data is formatted + // each data item is preceded by a 4-byte header which tells us the size of the data item + // 1 data item will have [header][data] + // 2 data items will have [header][data][header][data] + unsigned int dataLen = 0; + const unsigned char* pTempDataStart = pData + getHeaderLength(); + + buildByteArray(&pTempDataStart, reinterpret_cast(&m_messageStruct.wasCommandSuccessful), sizeof(m_messageStruct.wasCommandSuccessful), dataLen); + + // we want update total size of the entire message + m_header.setMessageLength(static_cast(dataLen)); + m_header.format(pData); +} + +//------------------------------------------------------------------------ + +void GenericRspMessage::parseData(const unsigned char* pData) +{ + bool selfThrown = false; + const unsigned char* pTempDataStart = pData; + const unsigned char* pTempDataEnd = pData + m_header.getMessageLength() - m_header.getHeaderLength() - 1; + std::stringstream ss; + + int sizeOfData = 0; + try { + sizeOfData = getNextDataItem(&pTempDataStart, pTempDataEnd, sizeOfData); + // make sure byte number match between what we're expected and what we receive + compareByteNumber(sizeof(m_messageStruct.wasCommandSuccessful), sizeOfData); + memcpy(&m_messageStruct.wasCommandSuccessful, pTempDataStart, sizeOfData); + + } + catch (Exception & e) { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//------------------------------------------------------------------------ + +std::string GenericRspMessage::toString() const +{ + std::stringstream ss; + + ss << Message::toString() << "wasCommandSuccessful: " << m_messageStruct.wasCommandSuccessful; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.hpp b/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.hpp new file mode 100644 index 0000000..c1b1766 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/GenericRspMessage.hpp @@ -0,0 +1,138 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class GenericRspMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: GenericRspMessage + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + GenericRspMessage(const bool& wasCommandSuccessful); + + //>--------------------------------------------------------------------------- + // Function: GenericRspMessage + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + GenericRspMessage(const GenericRspMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~GenericRspMessage + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~GenericRspMessage(); + + //>--------------------------------------------------------------------------- + // Function: getSuccessfulFlag + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + bool getSuccessfulFlag(){return static_cast(m_messageStruct.wasCommandSuccessful);} + + //>--------------------------------------------------------------------------- + // Function: executeMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: toString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + +protected: + //>--------------------------------------------------------------------------- + // Function: cloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: formatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: parseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char* pData); + +private: + // do not allow + GenericRspMessage &operator=(const GenericRspMessage &rhs); + +#pragma pack(1) + struct MessageStruct + { + unsigned int wasCommandSuccessful; + }; +#pragma pack() + + MessageStruct m_messageStruct; +}; diff --git a/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.cpp b/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.cpp new file mode 100644 index 0000000..bbbb955 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.cpp @@ -0,0 +1,146 @@ +#include +#include + +#include "KwScenarioStartedMessage.hpp" +#include "Exception.hpp" +#include "FileSystemUtil.hpp" +#include "Util.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "GenericRspMessage.hpp" +#include "Condition.hpp" +#include "RunAppThread.hpp" +#include "MainWindow.h" +#include "UdpSocketMgr.hpp" + +#include +#include +#include + +Thread* KwScenarioStartedMessage::ms_runAppThread = 0; + +//------------------------------------------------------------------------ + +KwScenarioStartedMessage::KwScenarioStartedMessage(): + Message(MessageIDs::SCENARIO_STARTED_CMD, "SCENARIO_STARTED_CMD") +{ +} + +//------------------------------------------------------------------------ + +KwScenarioStartedMessage::KwScenarioStartedMessage(const KwScenarioStartedMessage& copy) : + Message(copy) +{ +} + +//------------------------------------------------------------------------ + +KwScenarioStartedMessage::~KwScenarioStartedMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* KwScenarioStartedMessage::cloneSelf() +{ + KwScenarioStartedMessage* pMsg = new KwScenarioStartedMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void KwScenarioStartedMessage::executeMessage() +{ + try + { + Condition& commandExecutingEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTTION_IN_PROGRESS); + Condition& completeEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE); + + completeEvent.reset(); + if (commandExecutingEvent.timedWait(0,0)) // a command is current executing + { + completeEvent.wait(); // wait until current command finish executing + } + + // signal this command is currently executing to prevent any other command from executing + commandExecutingEvent.signal(); + + GenericRspMessage rsp(true); + + UdpSocketMgr::Instance().sendAMessage(rsp); + + std::string appPath = ""; + std::string threadName = ""; + bool runApp = false; + if (LinuxProc::Instance().getComputerName() == Constants::ComputerHosts::SWDEV_PC) + { + threadName = "RunTelemetryThread"; + appPath = LinuxProc::Instance().getConfig().getString(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "TELEMETRY_APP_PATH"); + runApp = LinuxProc::Instance().getConfig().getBool(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "RUN_TELEMETRY"); + } + else if (LinuxProc::Instance().getComputerName() == Constants::ComputerHosts::SIXDOF_PC) + { + threadName = "Run6DofThread"; + appPath = LinuxProc::Instance().getConfig().getString(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "SIXDOF_APP_PATH"); + runApp = LinuxProc::Instance().getConfig().getBool(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "RUN_SIXDOF"); + } + + if (appPath.length() > 0 && runApp) + { + if (Util::FileSystem::FileExists(appPath)) + { + std::string appName = Util::FileSystem::ExtractFilename(appPath); + Util::KillProcess(appName); + } + + if (ms_runAppThread == 0) + { + ms_runAppThread = new RunAppThread(threadName, appPath, true); + ms_runAppThread->create(); + ms_runAppThread->resume(); + } + + ms_runAppThread->startThread(); + } + + commandExecutingEvent.reset(); + completeEvent.signal(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void KwScenarioStartedMessage::formatData(unsigned char* pData) +{ + // Here's how the data is formatted + // each data item is preceded by a 4-byte header which tells us the size of the data item + // 1 data item will have [header][data] + // 2 data items will have [header][data][header][data] + unsigned int dataLen = 0; + + // we want update total size of the entire message + m_header.setMessageLength(static_cast(dataLen)); + m_header.format(pData); +} + +//------------------------------------------------------------------------ + +void KwScenarioStartedMessage::parseData(const unsigned char*) +{ +} + +//------------------------------------------------------------------------ + +std::string KwScenarioStartedMessage::toString() const +{ + std::stringstream ss; + + ss << Message::toString() << ". No member data"; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.hpp b/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.hpp new file mode 100644 index 0000000..09077f0 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/KwScenarioStartedMessage.hpp @@ -0,0 +1,134 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class Thread; + +class KwScenarioStartedMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: KwScenarioStarted + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + KwScenarioStartedMessage(); + + //>--------------------------------------------------------------------------- + // Function: KwScenarioStarted + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + KwScenarioStartedMessage(const KwScenarioStartedMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~KwScenarioStarted + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~KwScenarioStartedMessage(); + + //>--------------------------------------------------------------------------- + // Function: ExecuteMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: ToString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + + //>--------------------------------------------------------------------------- + // Function: getRunAppThread + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + static Thread* getRunAppThread(){return ms_runAppThread;} + +protected: + //>--------------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char*); + +private: + // do not allow + KwScenarioStartedMessage &operator=(const KwScenarioStartedMessage &rhs); + + static Thread* ms_runAppThread; + +}; diff --git a/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.cpp b/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.cpp new file mode 100644 index 0000000..086cf70 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.cpp @@ -0,0 +1,208 @@ +#include +#include +#include "KwScenarioStoppedMessage.hpp" +#include "Exception.hpp" +#include "StringUtil.hpp" +#include "Util.hpp" +#include "FileSystemUtil.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "GenericRspMessage.hpp" +#include "Condition.hpp" +#include "MainWindow.h" +#include "UdpSocketMgr.hpp" +#include "ConfigFileManager.hpp" +#include "FileTransferThread.hpp" + +#include +#include +#include +#include +//------------------------------------------------------------------------ + +KwScenarioStoppedMessage::KwScenarioStoppedMessage(): + Message(MessageIDs::SCENARIO_STOPPED_CMD, "SCENARIO_STOPPED_CMD") +{ +} + +//------------------------------------------------------------------------ + +KwScenarioStoppedMessage::KwScenarioStoppedMessage(const KwScenarioStoppedMessage& copy) : + Message(copy) +{ +} + +//------------------------------------------------------------------------ + +KwScenarioStoppedMessage::~KwScenarioStoppedMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* KwScenarioStoppedMessage::cloneSelf() +{ + KwScenarioStoppedMessage* pMsg = new KwScenarioStoppedMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void KwScenarioStoppedMessage::executeMessage() +{ + try + { + Condition& commandExecutingEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTTION_IN_PROGRESS); + Condition& completeEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE); + + completeEvent.reset(); + if (commandExecutingEvent.timedWait(0,0)) // a command is current executing + { + completeEvent.wait(); // wait until current command finish executing + } + + // signal this command is currently executing to prevent any other command from executing + commandExecutingEvent.signal(); + + GenericRspMessage rsp(true); + + UdpSocketMgr::Instance().sendAMessage(rsp); + + std::string appPath = ""; + if (LinuxProc::Instance().getComputerName() == Constants::ComputerHosts::SWDEV_PC) + { + appPath = LinuxProc::Instance().getConfig().getString(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "TELEMETRY_APP_PATH"); + } + else if (LinuxProc::Instance().getComputerName() == Constants::ComputerHosts::SIXDOF_PC) + { + appPath = LinuxProc::Instance().getConfig().getString(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "SIXDOF_APP_PATH"); + } + else if ((LinuxProc::Instance().getComputerName() == Constants::ComputerHosts::VIDEO_PC)) + { + + } + + if (appPath.length() > 0) + { + if (Util::FileSystem::FileExists(appPath)) + { + std::string appName = Util::FileSystem::ExtractFilename(appPath); + + Util::KillProcess(appName); + } + } + + if (gatherTestDataAndLogs()) + { + m_testDataPath = Util::FileSystem::BuildPath(LinuxProc::Instance().getConfig().getString("GENERAL", "BASE_TEST_DATA_PATH"),m_testDataPath); + LinuxProc::Instance().getFileTransferThread()->setDestDir(m_testDataPath); + Condition& event = LinuxProc::Instance().getEvent(EventNames::START_FILE_TRANSFER); + event.signal(); + } + + commandExecutingEvent.reset(); + completeEvent.signal(); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +bool KwScenarioStoppedMessage::gatherTestDataAndLogs() +{ + bool success = false; + std::vector filesToBeTransferred; + std::map testDataMap = ConfigFileManager::Instance().getTestDataMap(); + + std::map::iterator it; + + std::vector::iterator it2; + + int fileCreatedMinutesAgo = 5; + for (it = testDataMap.begin(); it != testDataMap.end(); it++) + { + std::vector regexPatternVec = Util::Strings::StringSplit(it->second.fileRegexPatterns, ",", false); + + QDir sourceDir(it->second.path.c_str()); + QStringList tempList = Util::FileSystem::GetListOfFilesInADirectory(sourceDir, false); + + for ( int i = 0; i < tempList.size(); i++ ) + { + for (it2 = regexPatternVec.begin(); it2 != regexPatternVec.end(); it2++) + { + std::string regexPattern = Util::Strings::TrimSpaces(*it2); + QRegularExpression re(regexPattern.c_str(), QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch match = re.match(tempList[i]); + + if (match.hasMatch()) + { + QFileInfo fi(tempList[i]); + if (fi.lastModified().secsTo(QDateTime::currentDateTime()) <= fileCreatedMinutesAgo * 60) + { + LinuxProc::Instance().getFileTransferThread()->addSourceFile(tempList[i].toStdString()); + + if (!success) + success = true; + break; + } + + } + } + } + } + + return success; +} + +//------------------------------------------------------------------------ + +void KwScenarioStoppedMessage::formatData(unsigned char* pData) +{ + // Here's how the data is formatted + // each data item is preceded by a 4-byte header which tells us the size of the data item + // 1 data item will have [header][data] + // 2 data items will have [header][data][header][data] + unsigned int dataLen = 0; + const unsigned char* pTempDataStart = pData + getHeaderLength(); + + buildByteArray(&pTempDataStart, m_testDataPath.c_str(), m_testDataPath.length(), dataLen); + + // we want update total size of the entire message + m_header.setMessageLength(static_cast(dataLen)); + m_header.format(pData); +} + +//------------------------------------------------------------------------ + +void KwScenarioStoppedMessage::parseData(const unsigned char* pData) +{ + const unsigned char* pTempDataStart = pData; + const unsigned char* pTempDataEnd = pData + m_header.getMessageLength() - m_header.getHeaderLength() - 1; + + int sizeOfData = 0; + try { + sizeOfData = getNextDataItem(&pTempDataStart, pTempDataEnd, sizeOfData); + m_testDataPath = Util::Strings::ByteArrayToString(const_cast(pTempDataStart), sizeOfData); + + } + catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//------------------------------------------------------------------------ + +std::string KwScenarioStoppedMessage::toString() const +{ + std::stringstream ss; + + ss << Message::toString() << ". testDataPath: " << m_testDataPath; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.hpp b/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.hpp new file mode 100644 index 0000000..2c616a0 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/KwScenarioStoppedMessage.hpp @@ -0,0 +1,132 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class KwScenarioStoppedMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: KwScenarioStopped + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + KwScenarioStoppedMessage(); + + //>--------------------------------------------------------------------------- + // Function: KwScenarioStopped + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + KwScenarioStoppedMessage(const KwScenarioStoppedMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~KwScenarioStopped + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~KwScenarioStoppedMessage(); + + //>--------------------------------------------------------------------------- + // Function: ExecuteMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: ToString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + +protected: + //>--------------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char*); + +private: + // do not allow + KwScenarioStoppedMessage &operator=(const KwScenarioStoppedMessage &rhs); + + //>--------------------------------------------------------------------------- + // Function: gatherTestDataAndLogs + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + bool gatherTestDataAndLogs(); + + std::string m_testDataPath; + +}; diff --git a/HWIL_Assistant/src/AutomationMessages/Message.cpp b/HWIL_Assistant/src/AutomationMessages/Message.cpp new file mode 100644 index 0000000..55b6b32 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/Message.cpp @@ -0,0 +1,175 @@ +#include + +#include "Message.hpp" +#include "Exception.hpp" +#include "StringUtil.hpp" +//------------------------------------------------------------------------ + +Message::Message(const MessageIDs::MsgIds& id, + const std::string& description, + const unsigned short& messageLen) : + m_header(id, messageLen), + m_description(description) +{ +} + +//------------------------------------------------------------------------ + +Message::Message(const Message& copy) : + m_header(copy.m_header), + m_description(copy.m_description) +{ +} + +//------------------------------------------------------------------------ + +Message::~Message() +{ +} + +//------------------------------------------------------------------------ + +Message* Message::clone() +{ + return cloneSelf(); +} + +//------------------------------------------------------------------------ + +void Message::format(unsigned char* pBuffer) +{ + try + { + m_header.format(pBuffer); + formatData(pBuffer); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +std::string Message::getDescription() const +{ + return m_description; +} + +//------------------------------------------------------------------------ + +void Message::parse(const unsigned char* pData) +{ + try + { + m_header.parse(pData); + parseData(pData + getHeaderLength()); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void Message::setMessageLength(const unsigned short& length) +{ + m_header.setMessageLength(length); +} + +//------------------------------------------------------------------------ + +std::string Message::toString() const +{ + std::stringstream ss; + ss << "Message: " << getDescription() << ". " << m_header.toString(); + + return ss.str(); +} + +//------------------------------------------------------------------------ + +int Message::getNextDataItem(const unsigned char** pStartBuf, const unsigned char* pEndBuf, int& sizeOfPreviousData) +{ + bool selfThrown = false; + int sizeOfDataHeader = 4; + int sizeOfData = 0; + std::stringstream ssError; + + *pStartBuf += sizeOfPreviousData; + ssError << "Data structure is incorrect. Data: " << Util::Strings::ByteArrayToHexString(const_cast(*pStartBuf), pEndBuf - *pStartBuf + 1); + try { + // make sure 4 bytes of header information is present + if (*pStartBuf + sizeOfDataHeader > pEndBuf) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, ssError.str()); + } + + sizeOfData = *(*pStartBuf); + + // we want to make sure the nth header and nth data information match + // header tells us how many bytes in the nth data item, and the bytes + // of data is present in the buffer + if (*pStartBuf + sizeOfDataHeader + sizeOfData -1 <= pEndBuf) + { + // points to the address of the nth data item + *pStartBuf += sizeOfDataHeader; + } + else + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, ssError.str()); + } + } catch (Exception& e) { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } + + return sizeOfData; +} + +//------------------------------------------------------------------------ + +void Message::buildByteArray(const unsigned char** pStartBuf, const char* data, const int& sizeOfDataBytes, unsigned int& totalBytesInArray) +{ + // copy the header information for this data item + memcpy(const_cast(*pStartBuf), &sizeOfDataBytes, sizeof(sizeOfDataBytes)); + *pStartBuf += sizeof(sizeOfDataBytes); + totalBytesInArray += sizeof(sizeOfDataBytes); + + // copy the data for this data item + memcpy(const_cast(*pStartBuf), data, sizeOfDataBytes); + *pStartBuf += sizeOfDataBytes; + totalBytesInArray += sizeOfDataBytes; +} + +//------------------------------------------------------------------------ + +void Message::compareByteNumber(int expectedNumBytes, int actualNumbyte) +{ + bool selfThrown = false; + std::stringstream ss; + + try + { + if (expectedNumBytes != actualNumbyte) + { + selfThrown = true; + + ss << "Expected number of bytes received: " << expectedNumBytes << ". Actual number of bytes received: " << actualNumbyte; + throw Exception(Q_FUNC_INFO, ss.str()); + } + } + catch (Exception & e) { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} diff --git a/HWIL_Assistant/src/AutomationMessages/Message.hpp b/HWIL_Assistant/src/AutomationMessages/Message.hpp new file mode 100644 index 0000000..9301f43 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/Message.hpp @@ -0,0 +1,257 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class Message +{ +public: + //>--------------------------------------------------------------------- + // Function: ~Message() + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual ~Message(); + + //>--------------------------------------------------------------------- + // Function: Clone() + // + // Purpose: Get a copy of this object + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: a copy of this object + //<--------------------------------------------------------------------- + virtual Message* clone(); + + //>--------------------------------------------------------------------- + // Function: ExecuteMessage() + // + // Purpose: Executes this message + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void executeMessage() = 0; + + //>--------------------------------------------------------------------- + // Function: Format() + // + // Purpose: Formats this message for sending + //---------------------------------------------------------------------- + // Arguments: pBuffer - the buffer to put the formatting data in + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void format(unsigned char* pBuffer); + + //>--------------------------------------------------------------------- + // Function: GetDescription() + // + // Purpose: Getter for this objects description + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: The description + //<--------------------------------------------------------------------- + virtual std::string getDescription() const; + + //>--------------------------------------------------------------------- + // Function: GetMessageID() + // + // Purpose: Getter for this objects message id + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: The id + //<--------------------------------------------------------------------- + virtual MessageIDs::MsgIds getMessageID() { return m_header.getMessageId(); } + + //>--------------------------------------------------------------------- + // Function: GetEntireMessageLength() + // + // Purpose: Getter for this objects message number of bytes, including the header + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: The entire message number of bytes + //<--------------------------------------------------------------------- + virtual unsigned int getEntireMessageLength() const { return m_header.getMessageLength();} + + //>--------------------------------------------------------------------- + // Function: GetHeaderLength() + // + // Purpose: Getter for this objects message number of header bytes + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: The header number of bytes + //<--------------------------------------------------------------------- + virtual unsigned short getHeaderLength() const { return m_header.getHeaderLength();} + + //>--------------------------------------------------------------------- + // Function: Parse() + // + // Purpose: Takes an array of bytes and populates this object + //---------------------------------------------------------------------- + // Arguments: The array of bytes + //---------------------------------------------------------------------- + // Return Value: None + //<--------------------------------------------------------------------- + virtual void parse(const unsigned char* pData); + + //>--------------------------------------------------------------------- + // Function: ToString() + // + // Purpose: Converts this object into a string + //---------------------------------------------------------------------- + // Arguments: None + //---------------------------------------------------------------------- + // Return Value: The string form of this object + //<--------------------------------------------------------------------- + virtual std::string toString() const; + +protected: + //>--------------------------------------------------------------------- + // Function: Constructor + // + // Purpose: The constructor for the childern to call + //---------------------------------------------------------------------- + // Arguments: id - the message id + // description - the message description + // messageLen - the number of bytes in the message payload (not including the header) + //---------------------------------------------------------------------- + // Return Value: The object + //<--------------------------------------------------------------------- + Message(const MessageIDs::MsgIds& id, + const std::string& description, + const unsigned short& messageLen = 0); + + //>--------------------------------------------------------------------- + // Function: Copy Constructor + // + // Purpose: Create a copy of this object + //---------------------------------------------------------------------- + // Arguments: copy - the object to copy + //---------------------------------------------------------------------- + // Return Value: The object + //<--------------------------------------------------------------------- + Message(const Message ©); + + //>--------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: Pure virtual function for children to implement. + // Create a clone of this object + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: The object + //<--------------------------------------------------------------------- + virtual Message* cloneSelf() = 0; + + //>--------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: Pure virtual function for children to implement. + // Format the data + //---------------------------------------------------------------------- + // Arguments: pData - the buffer to format to + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void formatData(unsigned char* pData) = 0; + + //>--------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: Pure virtual function for children to implement. + // Parse the data + //---------------------------------------------------------------------- + // Arguments: pData - the buffer to parse from + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void parseData(const unsigned char* pData) = 0; + + //>--------------------------------------------------------------------- + // Function: SetMessageLength + // + // Purpose: Sets the message length of the payload of the message (not the header) + //---------------------------------------------------------------------- + // Arguments: length - the number of bytes in the payload + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void setMessageLength(const unsigned short& length); + + //>--------------------------------------------------------------------- + // Function: getNextDataItem + // + // Purpose: + // get the next data item + // data format: + // [data header][data][data header][data]... + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + int getNextDataItem(const unsigned char** pStartBuf, const unsigned char* pEndBuf, int& sizeOfPreviousData); + + //>--------------------------------------------------------------------- + // Function: buildByteArray + // + // Purpose: + // this will add to the byte array a data item + // data format: + // [data header][data] + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void buildByteArray(const unsigned char** pStartBuf, const char* data, const int& sizeOfDataBytes, unsigned int& totalBytesInArray); + + //>--------------------------------------------------------------------- + // Function: compareByteNumber + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void compareByteNumber(int expectedNumBytes, int actualNumbyte); + + MessageHeader m_header; + +private: + // do not allow + Message(); + Message &operator=(const Message &rhs); + + std::string m_description; +}; diff --git a/HWIL_Assistant/src/AutomationMessages/MessageHeader.cpp b/HWIL_Assistant/src/AutomationMessages/MessageHeader.cpp new file mode 100644 index 0000000..992f705 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/MessageHeader.cpp @@ -0,0 +1,86 @@ +#include +#include +#include "MessageHeader.hpp" + +//------------------------------------------------------------------------ + +MessageHeader::MessageHeader(const MessageIDs::MsgIds& id, const unsigned short& messageLen) : + m_headerStruct() +{ + m_headerStruct.messageId = id; + m_headerStruct.messageLength = messageLen + getHeaderLength(); +} + +//------------------------------------------------------------------------ + +MessageHeader::MessageHeader() : + m_headerStruct() +{ + m_headerStruct.messageId = 0; + m_headerStruct.messageLength = 0; +} + +//------------------------------------------------------------------------ + +MessageHeader::MessageHeader(const MessageHeader& copy) : + m_headerStruct(copy.m_headerStruct) +{ +} + +//------------------------------------------------------------------------ + +MessageHeader::~MessageHeader() +{ +} + +//------------------------------------------------------------------------ + +void MessageHeader::format(unsigned char* pData) +{ + memcpy(pData, &m_headerStruct, getHeaderLength()); +} + +//------------------------------------------------------------------------ + +MessageIDs::MsgIds MessageHeader::getMessageId() +{ + return (MessageIDs::MsgIds)m_headerStruct.messageId; +} + +//------------------------------------------------------------------------ + +unsigned short MessageHeader::getHeaderLength() const +{ + return sizeof(m_headerStruct); +} + +//------------------------------------------------------------------------ + +unsigned int MessageHeader::getMessageLength() const +{ + return m_headerStruct.messageLength; +} + +//------------------------------------------------------------------------ + +void MessageHeader::parse(const unsigned char* pData) +{ + ::memcpy(&m_headerStruct, pData, getHeaderLength()); +} + +//------------------------------------------------------------------------ + +void MessageHeader::setMessageLength(const unsigned short& length) +{ + m_headerStruct.messageLength = length + getHeaderLength(); +} + +//------------------------------------------------------------------------ + +std::string MessageHeader::toString() const +{ + std::stringstream ss; + ss << "msg id: 0x" << std::hex << std::uppercase << m_headerStruct.messageId << std::nouppercase << ". " << "msg len: " << std::dec << m_headerStruct.messageLength; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/MessageHeader.hpp b/HWIL_Assistant/src/AutomationMessages/MessageHeader.hpp new file mode 100644 index 0000000..be4b4d1 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/MessageHeader.hpp @@ -0,0 +1,163 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +#include "MessageIDs.hpp" + +class MessageHeader +{ +public: + //>--------------------------------------------------------------------- + // Function: MessageHeader + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: id - the message id + // messageLen - the number of bytes of the entire message including the header + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + MessageHeader(const MessageIDs::MsgIds& id, const unsigned short& messageLen); + + //>--------------------------------------------------------------------- + // Function: MessageHeader + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + MessageHeader(); + + //>--------------------------------------------------------------------- + // Function: Copy Constructor + // + // Purpose: Create a copy of this object + //---------------------------------------------------------------------- + // Arguments: copy - the object to copy + //---------------------------------------------------------------------- + // Return Value: The object + //<--------------------------------------------------------------------- + MessageHeader(const MessageHeader ©); + + //>--------------------------------------------------------------------- + // Function: ~MessageHeader() + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual ~MessageHeader(); + + //>--------------------------------------------------------------------- + // Function: Format() + // + // Purpose: Formats this message for sending + //---------------------------------------------------------------------- + // Arguments: pBuffer - the buffer to put the formatting data in + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void format(unsigned char* pData); + + //>--------------------------------------------------------------------- + // Function: GetHeaderLength() + // + // Purpose: Get the number of bytes in the header + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: number of bytes in the header + //<--------------------------------------------------------------------- + unsigned short getHeaderLength() const; + + //>--------------------------------------------------------------------- + // Function: GetMessageLength() + // + // Purpose: Get the number of bytes in the entire message, including header + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: number of bytes in the message + //<--------------------------------------------------------------------- + unsigned int getMessageLength() const; + + //>--------------------------------------------------------------------- + // Function: GetMessageId() + // + // Purpose: Get the message id + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: the message id + //<--------------------------------------------------------------------- + MessageIDs::MsgIds getMessageId(); + + //>--------------------------------------------------------------------- + // Function: Parse() + // + // Purpose: Takes an array of bytes and populates this object + //---------------------------------------------------------------------- + // Arguments: The array of bytes + //---------------------------------------------------------------------- + // Return Value: None + //<--------------------------------------------------------------------- + void parse(const unsigned char* pData); + + //>--------------------------------------------------------------------- + // Function: SetMessageLength + // + // Purpose: Sets the message length of the payload of the message (not the header) + //---------------------------------------------------------------------- + // Arguments: length - the number of bytes in the payload + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void setMessageLength(const unsigned short& length); + + //>--------------------------------------------------------------------- + // Function: ToString() + // + // Purpose: Converts this object into a string + //---------------------------------------------------------------------- + // Arguments: None + //---------------------------------------------------------------------- + // Return Value: The string form of this object + //<--------------------------------------------------------------------- + std::string toString() const; + +protected: + +private: + // do not allow + MessageHeader &operator=(const MessageHeader &rhs); + +#pragma pack(1) + struct HeaderStruct + { + unsigned int messageId; + unsigned int messageLength; + }; +#pragma pack() + + HeaderStruct m_headerStruct; +}; diff --git a/HWIL_Assistant/src/AutomationMessages/MessageIDs.hpp b/HWIL_Assistant/src/AutomationMessages/MessageIDs.hpp new file mode 100644 index 0000000..0ac518a --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/MessageIDs.hpp @@ -0,0 +1,33 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + + +namespace MessageIDs +{ + enum MsgIds + { + ARE_YOU_THERE_CMD = 0xCA001004, + SCENARIO_STARTED_CMD = 0xCA001005, + SCENARIO_STOPPED_CMD = 0xCA001006, + + WAIT_FOR_COMPLETION_CMD = 0xCA002000, + + GENERIC_RSP = 0xCA002001, + ARE_YOU_THERE_RSP = 0xCA002002 + }; +} diff --git a/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.cpp b/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.cpp new file mode 100644 index 0000000..71787b7 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.cpp @@ -0,0 +1,83 @@ +#include +#include +#include "WaitForLastTaskCompletionCmdMessage.hpp" +#include "Exception.hpp" +#include "Condition.hpp" +#include "LinuxProc.hpp" +#include "GenericRspMessage.hpp" +#include "UdpSocketMgr.hpp" + +bool WaitForLastTaskCompletionCmdMessage::s_commandCompletionSuccess = true; + +//------------------------------------------------------------------------ + +WaitForLastTaskCompletionCmdMessage::WaitForLastTaskCompletionCmdMessage(): + Message(MessageIDs::WAIT_FOR_COMPLETION_CMD, "WAIT_FOR_COMPLETION_CMD") +{ +} + +//------------------------------------------------------------------------ + +WaitForLastTaskCompletionCmdMessage::WaitForLastTaskCompletionCmdMessage(const WaitForLastTaskCompletionCmdMessage& copy) : + Message(copy) +{ +} + +//------------------------------------------------------------------------ + +WaitForLastTaskCompletionCmdMessage::~WaitForLastTaskCompletionCmdMessage() +{ +} + +//------------------------------------------------------------------------ + +Message* WaitForLastTaskCompletionCmdMessage::cloneSelf() +{ + WaitForLastTaskCompletionCmdMessage* pMsg = new WaitForLastTaskCompletionCmdMessage(*this); + return pMsg; +} + +//------------------------------------------------------------------------ + +void WaitForLastTaskCompletionCmdMessage::executeMessage() +{ + try + { + Condition& event = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE); + event.wait(false); + + GenericRspMessage rsp(s_commandCompletionSuccess); + + UdpSocketMgr::Instance().sendAMessage(rsp); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void WaitForLastTaskCompletionCmdMessage::formatData(unsigned char*) +{ + // no data to send +} + +//------------------------------------------------------------------------ + +void WaitForLastTaskCompletionCmdMessage::parseData(const unsigned char*) +{ + // no data to process +} + +//------------------------------------------------------------------------ + +std::string WaitForLastTaskCompletionCmdMessage::toString() const +{ + std::stringstream ss; + + ss << ""; + + return ss.str(); +} diff --git a/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.hpp b/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.hpp new file mode 100644 index 0000000..ac37371 --- /dev/null +++ b/HWIL_Assistant/src/AutomationMessages/WaitForLastTaskCompletionCmdMessage.hpp @@ -0,0 +1,121 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "Message.hpp" +#include "MessageIDs.hpp" +#include "MessageHeader.hpp" + +class WaitForLastTaskCompletionCmdMessage : public Message +{ +public: + //>--------------------------------------------------------------------------- + // Function: WaitForLastTaskCompletionCmdMessage + // + // Purpose: constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + WaitForLastTaskCompletionCmdMessage(); + + //>--------------------------------------------------------------------------- + // Function: WaitForLastTaskCompletionCmdMessage + // + // Purpose: copy constructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + WaitForLastTaskCompletionCmdMessage(const WaitForLastTaskCompletionCmdMessage ©); + + //>--------------------------------------------------------------------------- + // Function: ~WaitForLastTaskCompletionCmdMessage + // + // Purpose: destructor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual ~WaitForLastTaskCompletionCmdMessage(); + + //>--------------------------------------------------------------------------- + // Function: ExecuteMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void executeMessage(); + + //>--------------------------------------------------------------------------- + // Function: ToString + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual std::string toString() const; + + // indicate command executed successfully or not + static bool s_commandCompletionSuccess; + +protected: + //>--------------------------------------------------------------------------- + // Function: CloneSelf + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual Message* cloneSelf(); + + //>--------------------------------------------------------------------------- + // Function: FormatData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void formatData(unsigned char* pData); + + //>--------------------------------------------------------------------------- + // Function: ParseData + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + virtual void parseData(const unsigned char* pData); + +private: + // do not allow + WaitForLastTaskCompletionCmdMessage &operator=(const WaitForLastTaskCompletionCmdMessage &rhs); +}; diff --git a/HWIL_Assistant/src/Comm/UdpSocket.cpp b/HWIL_Assistant/src/Comm/UdpSocket.cpp new file mode 100644 index 0000000..9b5d673 --- /dev/null +++ b/HWIL_Assistant/src/Comm/UdpSocket.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include +#include +#include "StringUtil.hpp" +#include "UdpSocket.hpp" +#include "Exception.hpp" +#include "AutomationMsgParser.hpp" +#include "AutomationMsgHandler.hpp" +#include "LinuxProc.hpp" +#include "MainWindow.h" +#include "ErrorLog.hpp" + +//----------------------------------------------------------------------------- + +UdpSocket::UdpSocket(const int& localPort): + m_localPort(localPort), + m_sock(0) +{ + bool selfThrown = false; + try + { + m_sock = new QUdpSocket(); + + if (!m_sock->bind(QHostAddress::AnyIPv4, m_localPort)) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, "QUdpSocket.bind() fails"); + } + + connect(m_sock, SIGNAL(readyRead()), this, SLOT(readCallBack())); + } + catch (Exception& e) + { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +UdpSocket::UdpSocket(const int& localPort, const int& remotePort, const std::string& remoteAddr): + m_localPort(localPort), + m_remotePort(remotePort), + m_remoteAddr(remoteAddr), + m_sock(0) +{ + bool selfThrown = false; + try + { + m_sock = new QUdpSocket(); + + if (!m_sock->bind(QHostAddress::AnyIPv4, m_localPort)) + { + selfThrown = true; + throw Exception(Q_FUNC_INFO, "QUdpSocket.bind() fails"); + } + } + catch (Exception& e) + { + if (!selfThrown) + e.buildStackTrace(Q_FUNC_INFO); + + throw e; + } +} + +//----------------------------------------------------------------------------- + +UdpSocket::~UdpSocket() +{ + if (m_sock != 0) + delete m_sock; +} + +//----------------------------------------------------------------------------- + +void UdpSocket::readCallBack() +{ + std::stringstream ss; + + try + { + // when data comes in + QByteArray buffer; + buffer.resize(m_sock->pendingDatagramSize()); + + QHostAddress sender; + quint16 senderPort; + + qint64 sizeRead = m_sock->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort); + + m_remoteAddr = sender.toString().toStdString(); + m_remotePort = senderPort; + ss << "\nReceived command from: " << sender.toString().toStdString() << ", port: " << senderPort; + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + + qDebug() << "Message from: " << sender.toString(); + qDebug() << "Message port: " << senderPort; + + qDebug() << "Message: " << QString::fromStdString(Util::Strings::ByteArrayToHexString(buffer)); + + qDebug() << "Number of bytes: " << sizeRead; + + unsigned int msgId = 0; + try { + AutomationMsgParser::instance().parseMsg(reinterpret_cast(buffer.data()), static_cast(sizeRead), &msgId); + + AutomationMsgHandler::instance().handleMsg(reinterpret_cast(buffer.data()), msgId); + + ss.str(""); + ss << "\nProcess message " << std::hex << msgId << " successful"; + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + + } catch (Exception& e) { + + ss.str(""); + ss << "\nProcess "; + + if (msgId > 0) + ss << "message " << std::hex << msgId; + else + ss << "command"; + + ss << " failed"; + + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + + throw; + } + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + ErrorLog::Instance().log(e.getMessage(), true); + } + + ss.str(""); + ss << "\nWaiting for command..."; + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); +} + +//----------------------------------------------------------------------------- + +void UdpSocket::read(unsigned char* dataBuf, int& dataSize) +{ + std::stringstream ss; + + try + { + // when data comes in + QByteArray buffer; + buffer.resize(m_sock->pendingDatagramSize()); + + QHostAddress sender; + quint16 senderPort; + + if (buffer.size() > 0) + { + qint64 sizeRead = m_sock->readDatagram(buffer.data(), buffer.size(), &sender, &senderPort); + + m_remoteAddr = sender.toString().toStdString(); + m_remotePort = senderPort; + + dataSize = sizeRead; + + if (dataSize > 0) + memcpy(dataBuf, reinterpret_cast(buffer.data()), dataSize); + } + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + + ErrorLog::Instance().log(e.getMessage(), true); + } +} + +//----------------------------------------------------------------------------- + +void UdpSocket::write(const unsigned char* pDataToWrite, const unsigned int& numBytesToWrite) +{ + try + { + QByteArray databuf; + databuf = QByteArray(reinterpret_cast(pDataToWrite), numBytesToWrite); + + QHostAddress remoteHost(m_remoteAddr.c_str()); + m_sock->writeDatagram(databuf, remoteHost, m_remotePort); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} diff --git a/HWIL_Assistant/src/Comm/UdpSocket.hpp b/HWIL_Assistant/src/Comm/UdpSocket.hpp new file mode 100644 index 0000000..b24f01e --- /dev/null +++ b/HWIL_Assistant/src/Comm/UdpSocket.hpp @@ -0,0 +1,97 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include + +#include + +class QUdpSocket; + +class UdpSocket: public QObject +{ + Q_OBJECT +public: + //>--------------------------------------------------------------------- + // Function: UdpSocket() + // + // Purpose: Constructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: the object + //<--------------------------------------------------------------------- + UdpSocket(const int& localPort); + + //>--------------------------------------------------------------------- + // Function: UdpSocket() + // + // Purpose: Constructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: the object + //<--------------------------------------------------------------------- + UdpSocket(const int& localPort, const int& remotePort, const std::string& remoteAddr); + + //>--------------------------------------------------------------------- + // Function: ~UdpSocket + // + // Purpose: Destroyer + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ~UdpSocket(); + + //>--------------------------------------------------------------------- + // Function: Read + // + // Purpose: Read from the socket + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: + //<--------------------------------------------------------------------- + void read(unsigned char* dataBuf, int& dataSize); + + //>--------------------------------------------------------------------- + // Function: Write + // + // Purpose: Write to the socket + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: number of bytes written + //<--------------------------------------------------------------------- + void write(const unsigned char* pDataToWrite, const unsigned int& numBytesToWrite); + +public slots: + void readCallBack(); + +private: + // dont allow + UdpSocket(const UdpSocket& rhs); + UdpSocket& operator=(const UdpSocket& rhs); + + int m_localPort; + int m_remotePort; + std::string m_remoteAddr; + QUdpSocket *m_sock; +}; + diff --git a/HWIL_Assistant/src/Comm/UdpSocketMgr.cpp b/HWIL_Assistant/src/Comm/UdpSocketMgr.cpp new file mode 100644 index 0000000..7439bce --- /dev/null +++ b/HWIL_Assistant/src/Comm/UdpSocketMgr.cpp @@ -0,0 +1,95 @@ +#include "UdpSocketMgr.hpp" +#include "Exception.hpp" +#include "ErrorLog.hpp" +#include "Util.hpp" +#include "UdpSocket.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "MainWindow.h" +#include "Message.hpp" + +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- + +UdpSocketMgr& UdpSocketMgr::Instance() +{ + static UdpSocketMgr proc; + return proc; +} + +//----------------------------------------------------------------------------- + +UdpSocketMgr::UdpSocketMgr(): + m_udpSock(0) +{ +} + +//----------------------------------------------------------------------------- + +void UdpSocketMgr::deleteSocket() +{ + if (m_udpSock != 0) + { + delete m_udpSock; + m_udpSock = 0; + } +} + +//----------------------------------------------------------------------------- + +UdpSocketMgr::~UdpSocketMgr() +{ + if (m_udpSock != 0) + delete m_udpSock; +} + +//----------------------------------------------------------------------------- + +void UdpSocketMgr::setUpUdpSocket() +{ + try + { + int localPort = LinuxProc::Instance().getConfig().getInt("GENERAL", "CMD_LOCAL_PORT"); + + m_udpSock = new UdpSocket(localPort); + + std::stringstream ss; + ss << "Setting up UDP socket, local port: " << localPort; + ss << "\n\nWaiting for command..."; + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + + } catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} + +//----------------------------------------------------------------------------- + +void UdpSocketMgr::sendAMessage(Message &msg) +{ + try + { + // just need a buffer big enough for outgoing commands + const unsigned int BUF_SIZE = 1024; + + unsigned char data[BUF_SIZE]; + + msg.format(data); + + m_udpSock->write(data, msg.getEntireMessageLength()); + + } catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} diff --git a/HWIL_Assistant/src/Comm/UdpSocketMgr.hpp b/HWIL_Assistant/src/Comm/UdpSocketMgr.hpp new file mode 100644 index 0000000..f22487a --- /dev/null +++ b/HWIL_Assistant/src/Comm/UdpSocketMgr.hpp @@ -0,0 +1,100 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#ifndef UDPSOCKETMGR_H +#define UDPSOCKETMGR_H + +#include + +class UdpSocket; +class Message; + +class UdpSocketMgr : public QObject +{ +Q_OBJECT + +public: + //>--------------------------------------------------------------------------- + // Function: instance + // + // Purpose: singleton + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + static UdpSocketMgr& Instance(); + + //>--------------------------------------------------------------------------- + // Function: ~UdpSocketMgr + // + // Purpose: Destroyer + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + ~UdpSocketMgr(); + + //>--------------------------------------------------------------------------- + // Function: sendAMessage + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void sendAMessage(Message& msg); + + //>--------------------------------------------------------------------------- + // Function: deleteSocket + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void deleteSocket(); + + //>--------------------------------------------------------------------------- + // Function: setUpUdpSocket + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void setUpUdpSocket(); + +private: + //>--------------------------------------------------------------------------- + // Function: UdpSocketMgr + // + // Purpose: Ctor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + UdpSocketMgr(); + + UdpSocket* m_udpSock; +}; + +#endif diff --git a/HWIL_Assistant/src/Common/Constants.cpp b/HWIL_Assistant/src/Common/Constants.cpp new file mode 100644 index 0000000..25c9041 --- /dev/null +++ b/HWIL_Assistant/src/Common/Constants.cpp @@ -0,0 +1,3 @@ +#include "Constants.hpp" + +std::map Constants::ConfigSectionNameMapping::sectionMap = Constants::ConfigSectionNameMapping::createMap(); diff --git a/HWIL_Assistant/src/Common/Constants.hpp b/HWIL_Assistant/src/Common/Constants.hpp new file mode 100644 index 0000000..fa7e617 --- /dev/null +++ b/HWIL_Assistant/src/Common/Constants.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +namespace Constants +{ + enum class ComputerHosts + { + VIDEO_PC, + SWDEV_PC, + SIXDOF_PC, + UNKNOWN_PC, + NUM_COMPUTER_HOSTS + }; + + struct ConfigSectionNameMapping + { + static std::map createMap() + { + std::map map { + {ComputerHosts::VIDEO_PC, "VIDEO_COMPUTER"}, + {ComputerHosts::SWDEV_PC, "SWDEV_COMPUTER"}, + {ComputerHosts::SIXDOF_PC, "SIXDOF_COMPUTER"} + }; + + return map; + } + + static std::map sectionMap; + }; +} diff --git a/HWIL_Assistant/src/Common/Util.cpp b/HWIL_Assistant/src/Common/Util.cpp new file mode 100644 index 0000000..15c6cc7 --- /dev/null +++ b/HWIL_Assistant/src/Common/Util.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "Util.hpp" +#include "MiscUtil.hpp" +#include "DateTimeUtil.hpp" +#include "FileSystemUtil.hpp" +#include "Exception.hpp" +#include "Timestamp.hpp" +#include "LinuxProc.hpp" +#include "MainWindow.h" +#include "ErrorLog.hpp" + +//----------------------------------------------------------------------------- + +void Util::KillProcess(const std::string& processName, bool updateMainWindow) +{ + bool success = false; + bool processRunning = false; + std::string cmd = ""; + + for (int i=1; i<=6; i++) + { + std::map processToUserMap = Util::Misc::GetUsersOfRunningProcess(processName); + + if (processToUserMap.size() > 0) + { + processRunning = true; + + std::stringstream ss; + ss << "Sending KILL signal to process " << processName; + if (updateMainWindow) + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + else + ErrorLog::Instance().log(ss.str(), false, ErrorLog::INFO); + + // send KILL signal to telemetry app + if (i <= 3) + cmd = "kill -s INT "; // kill gracefully + else + cmd = "kill -9 "; // kill forcefully + + cmd += processToUserMap.begin()->first; + system(cmd.c_str()); + } + else + { + success = true; + break; + } + + Util::DateTime::Sleep(200); + } + + if (processRunning) + { + std::stringstream ss; + ss << "Killing " << processName << " "; + if (success) + { + ss << "successful"; + } + else + ss << "failed"; + + if (updateMainWindow) + LinuxProc::Instance().getMainWindow().updateStatusBox(ss.str()); + else + ErrorLog::Instance().log(ss.str(), false, ErrorLog::INFO); + } +} + +//----------------------------------------------------------------------------- + +void Util::PerformLogCleanUp(std::string logPath, std::string fileNameRegexPattern) +{ + QDir sourceDir(logPath.c_str()); + QStringList tempList = Util::FileSystem::GetListOfFilesInADirectory(sourceDir, false); + QMap msecsToFileMap; + int maxConsecutiveFileRemovals = 10; + int consecutiveFileRemovalFails = 0; + + for ( int i = 0; i < tempList.size(); i++ ) + { + QRegularExpression re(fileNameRegexPattern.c_str(), QRegularExpression::CaseInsensitiveOption); + + QRegularExpressionMatch match = re.match(tempList[i]); + + if (match.hasMatch()) { + QFileInfo fi(tempList[i]); + + if (fi.size() > 0) + { + msecsToFileMap[fi.lastModified().toMSecsSinceEpoch()] = tempList[i]; + } + else + { + QFile file(tempList[i]); + if (!file.remove()) + { + ErrorLog::Instance().log("Cannot remove file " + tempList[i].toStdString(), false, ErrorLog::ERROR); + consecutiveFileRemovalFails++; + } + else + consecutiveFileRemovalFails = 0; + + if (consecutiveFileRemovalFails == maxConsecutiveFileRemovals) + break; + } + } + } + + consecutiveFileRemovalFails = 0; + QDateTime now = QDateTime::currentDateTime(); + // keep logs that were created in the last 7 days + qint64 numDaysToKeepLogs = 7; + int MAX_NUM_LOGS_TO_KEEP = 30; + + for (auto it = msecsToFileMap.begin(); it != msecsToFileMap.end();) + { + QFileInfo fi(it.value()); + if (msecsToFileMap.size() > MAX_NUM_LOGS_TO_KEEP || fi.lastModified().daysTo(now) > numDaysToKeepLogs) + { + QFile file(it.value()); + if (!file.remove()) + { + ErrorLog::Instance().log("Cannot remove file " + it.value().toStdString(), false, ErrorLog::ERROR); + consecutiveFileRemovalFails++; + } + else + consecutiveFileRemovalFails = 0; + + it = msecsToFileMap.erase(it); + + if (consecutiveFileRemovalFails == maxConsecutiveFileRemovals) + break; + } + else + ++it; + } +} + +//----------------------------------------------------------------------------- diff --git a/HWIL_Assistant/src/Common/Util.hpp b/HWIL_Assistant/src/Common/Util.hpp new file mode 100644 index 0000000..3ccf654 --- /dev/null +++ b/HWIL_Assistant/src/Common/Util.hpp @@ -0,0 +1,52 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Timestamp.hpp" + +namespace Util +{ + //>--------------------------------------------------------------------- + // Function: KillProcess + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: + //<--------------------------------------------------------------------- + void KillProcess(const std::string& processName, bool updateMainWindow = true); + + //>--------------------------------------------------------------------- + // Function: KillProcess + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: + //<--------------------------------------------------------------------- + void PerformLogCleanUp(std::string logPath, std::string fileNameRegexPattern); +} diff --git a/HWIL_Assistant/src/Config/ConfigFileManager.cpp b/HWIL_Assistant/src/Config/ConfigFileManager.cpp new file mode 100644 index 0000000..fde23f1 --- /dev/null +++ b/HWIL_Assistant/src/Config/ConfigFileManager.cpp @@ -0,0 +1,69 @@ +#include "ConfigFileManager.hpp" +#include "LinuxProc.hpp" +#include "IniFile.hpp" +#include "Exception.hpp" +#include "StringUtil.hpp" + +#include + +//----------------------------------------------------------------------------- + +ConfigFileManager& ConfigFileManager::Instance() +{ + static ConfigFileManager confgMgr; + return confgMgr; +} + +//------------------------------------------------------------------------ + +ConfigFileManager::ConfigFileManager() +{ +} + +//------------------------------------------------------------------------ + +ConfigFileManager::~ConfigFileManager() +{ +} + +//------------------------------------------------------------------------ + +void ConfigFileManager::parseLogInfo(std::string sectionName) +{ + try { + std::vector iniKeys; + LinuxProc::Instance().getConfig().getKeys(sectionName, iniKeys); + + std::vector::iterator it; + for (it = iniKeys.begin(); it != iniKeys.end(); it++) + { + QRegularExpression re("^(test_data\\d+)[^\\d].+", QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch match = re.match(std::string(*it).c_str()); + if (match.hasMatch()) { + std::string uniqueKey = match.captured(1).toStdString(); + if (m_testDataMap.find(uniqueKey) == m_testDataMap.end()) + { + std::string key = uniqueKey + "_path"; + + TestDataInfo testData; + testData.path = LinuxProc::Instance().getConfig().getString(sectionName, key); + key = uniqueKey + "_FILE_REGEX_PATTERNS"; + testData.fileRegexPatterns = LinuxProc::Instance().getConfig().getString(sectionName, key); + key = uniqueKey + "_TRANSFER_TYPE"; + if (Util::Strings::StringsAreEqual(LinuxProc::Instance().getConfig().getString(sectionName, key), "move")) + { + testData.transferType = FileTransferType::MOVE; + } + key = uniqueKey + "_PERFORM_CLEAN_UP"; + testData.performCleanUp = LinuxProc::Instance().getConfig().getBool(sectionName, key); + + m_testDataMap[uniqueKey] = testData; + } + } + } + + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} diff --git a/HWIL_Assistant/src/Config/ConfigFileManager.hpp b/HWIL_Assistant/src/Config/ConfigFileManager.hpp new file mode 100644 index 0000000..4b0f0b3 --- /dev/null +++ b/HWIL_Assistant/src/Config/ConfigFileManager.hpp @@ -0,0 +1,122 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#pragma once + +#include "CustomDataTypes.hpp" + +#include +#include +#include + +class ConfigFileManager +{ +public: + enum class FileTransferType + { + COPY, + MOVE + }; + + struct TestDataInfo + { + std::string path; + std::string fileRegexPatterns; + FileTransferType transferType; + bool performCleanUp; + + TestDataInfo(): + path(), + fileRegexPatterns(), + transferType(FileTransferType::COPY), + performCleanUp(false) + { + } + }; + + static ConfigFileManager& Instance(); + + //>--------------------------------------------------------------------- + // Function: ~ConfigFileManager() + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ~ConfigFileManager(); + + //>--------------------------------------------------------------------- + // Function: parseLogInfo() + // + // Purpose: + // + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void parseLogInfo(std::string sectionName); + + //>--------------------------------------------------------------------- + // Function: getLogMap() + // + // Purpose: + // + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + std::map getTestDataMap(){return m_testDataMap;} + +private: + //>--------------------------------------------------------------------- + // Function: ConfigFileManager() + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ConfigFileManager(); + + //>--------------------------------------------------------------------- + // Function: ConfigFileManager() + // + // Purpose: copy constructor + //---------------------------------------------------------------------- + // Arguments: const ConfigFileManager & - reference to ConfigFileManager obj + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ConfigFileManager(const ConfigFileManager &rhs); + + //>--------------------------------------------------------------------- + // Function: operator&() + // + // Purpose: assignment operator + //---------------------------------------------------------------------- + // Arguments: const ConfigFileManager & - reference to ConfigFileManager obj + //---------------------------------------------------------------------- + // Return Value: reference to ConfigFileManager obj + //<--------------------------------------------------------------------- + ConfigFileManager &operator=(const ConfigFileManager &); + + std::map m_testDataMap; +}; diff --git a/HWIL_Assistant/src/Config/config.ini b/HWIL_Assistant/src/Config/config.ini new file mode 100644 index 0000000..0646d82 --- /dev/null +++ b/HWIL_Assistant/src/Config/config.ini @@ -0,0 +1,68 @@ +[GENERAL] +APP_SINGLETON_LOCAL_PORT = 44453 + +CMD_LOCAL_PORT = 44454 + +SHOW_MAIN_WINDOW = false + +# true - log everything for debugging purposes +# false - minimum debugging +VERBOSE_LOGGING = TRUE + +BASE_TEST_DATA_PATH = /duc_file_server/TestData/ + +[SWDEV_COMPUTER] +COMPUTER_NAME_REGEX_PATTERN = -swdev$ +#COMPUTER_NAME_REGEX_PATTERN = -6700k$ +SHOW_MAIN_WINDOW = true +RUN_TELEMETRY = true +#TELEMETRY_APP_PATH = /net/netapp01/vol/vol1/home/dle/Devshed/Development/Linux/Telemetry/tlm +TELEMETRY_APP_PATH = /duc_file_server/Programming/C_CPP/UdpServer/UdpServer/Debug/UdpServer + +# If more than one host is moving data to main repository, only one computer should create the test folder while all other must wait +# until the folder is created +WAIT_TIME_BEFORE_CREATING_TEST_DATA_FOLDER = 3 + +TEST_DATA1_PATH = /duc_file_server/Programming/QTCreator/HWIL_Assistant/HWIL_Assistant/build_x64_debug/Output_Test +TEST_DATA1_FILE_REGEX_PATTERNS = _log\.txt +TEST_DATA1_TRANSFER_TYPE = move +TEST_DATA1_PERFORM_CLEAN_UP = true + +#TEST_DATA2_PATH = /duc_file_server/Programming/QTCreator/HWIL_Assistant/HWIL_Assistant/build_x64_debug/Output_Test +#TEST_DATA2_FILE_REGEX_PATTERN = ^log* +#TEST_DATA2_TRANSFER_TYPE = move +#TEST_DATA2_PERFORM_CLEAN_UP = true + +[SIXDOF_COMPUTER] +#COMPUTER_NAME_REGEX_PATTERN = -6dof$ +COMPUTER_NAME_REGEX_PATTERN = -6700k$ +SHOW_MAIN_WINDOW = true + +RUN_HOSTBUS = true +HOSTBUS_APP_PATH = /duc_file_server/Programming/C_CPP/UdpServer/UdpServer/Debug/UdpServer + +RUN_SIXDOF = true +SIXDOF_APP_PATH = /duc_file_server/Programming/C_CPP/UdpClient/UdpClient/Debug/UdpClient + +# If more than one host is moving data to main repository, only one computer should create the test folder while all other must wait +# until the folder is created +WAIT_TIME_BEFORE_CREATING_TEST_DATA_FOLDER = 4 + +TEST_DATA1_PATH = /duc_file_server/Programming/QTCreator/HWIL_Assistant/HWIL_Assistant/build_x64_debug/Output_Test +TEST_DATA1_FILE_REGEX_PATTERNS = _log\.txt +TEST_DATA1_TRANSFER_TYPE = move +TEST_DATA1_PERFORM_CLEAN_UP = true + +#TEST_DATA2_PATH = /duc_file_server/Programming/QTCreator/HWIL_Assistant/HWIL_Assistant/build_x64_debug/Output_Test +#TEST_DATA2_FILE_REGEX_PATTERN = ^log* +#TEST_DATA2_TRANSFER_TYPE = move +#TEST_DATA2_PERFORM_CLEAN_UP = true + +[VIDEO_COMPUTER] +#COMPUTER_NAME_REGEX_PATTERN = -vcs$ +COMPUTER_NAME_REGEX_PATTERN = -6700k$ +SHOW_MAIN_WINDOW = true + +# If more than one host is moving data to main repository, only one computer should create the test folder while all other must wait +# until the folder is created +WAIT_TIME_BEFORE_CREATING_TEST_DATA_FOLDER = 5 diff --git a/HWIL_Assistant/src/LinuxProc.cpp b/HWIL_Assistant/src/LinuxProc.cpp new file mode 100644 index 0000000..5612751 --- /dev/null +++ b/HWIL_Assistant/src/LinuxProc.cpp @@ -0,0 +1,320 @@ +#include "LinuxProc.hpp" +#include "MainWindow.h" +#include "FileTransferDialog.hpp" +#include "IniFile.hpp" +#include "Exception.hpp" +#include "ErrorLog.hpp" +#include "Timestamp.hpp" +#include "FileSystemUtil.hpp" +#include "DateTimeUtil.hpp" +#include "StringUtil.hpp" +#include "MiscUtil.hpp" +#include "Util.hpp" +#include "UdpSocket.hpp" +#include "Message.hpp" +#include "Condition.hpp" +#include "FileTransferThread.hpp" +#include "NetworkingThread.hpp" +#include "UdpSocketMgr.hpp" +#include "ConfigFileManager.hpp" +#include "KwScenarioStartedMessage.hpp" +#include "AreYouThereCmdMessage.hpp" +#include "RunAppThread.hpp" +#include "AutomationMsgParser.hpp" +#include "AreYouThereRspMessage.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +//----------------------------------------------------------------------------- + +LinuxProc& LinuxProc::Instance() +{ + static LinuxProc proc; + return proc; +} + +//----------------------------------------------------------------------------- + +LinuxProc::LinuxProc(): + Proc(), + m_pMainWindow(0), + m_pFileTransferDialog(0), + m_iniFile(0), + m_eventMap(), + m_fileTransferThread(0), + m_networkingThread(0), + m_runHostBusThread(0), + m_computerName(Constants::ComputerHosts::UNKNOWN_PC) +{ + // all singleton classes aka [class]::instance() need to be instantiated here as they create static variables + // they all should also be instantiated in one thread, preferable the main thread. Instantiating them in multiple + // threads will make it hard for us to synchronize their destructions, as static variables are destroyed in the order + // they were created per thread + + // all static variables are destroyed in the reverse order they were created per thread + // so any static variables that are dependent upon need to be instantiated first so they will be destroyed last + // Proc is the last variable to be instantiated and the first static variable to be destroyed + // as it needs to coordinate the destruction of all variables created on the heap + try { + initEvents(); + + // at startup, there's no command executing, so we assume this event should be signaled + getEvent(EventNames::COMMAND_EXECUTION_COMPLETE).signal(); + + std::string exePath = Util::FileSystem::BuildPath(QCoreApplication::applicationDirPath().toStdString()); + + std::string configFilePath = Util::FileSystem::BuildPath(exePath,"config.ini"); + + m_iniFile = new IniFile(configFilePath); + + testAppSingleton(); + + std::string logPath = Util::FileSystem::BuildPath(exePath,"Output"); + + Util::FileSystem::CreateDirectory(logPath); + + Util::PerformLogCleanUp(logPath, "_log\\.txt"); + + Timestamp time; + std::stringstream ss; + + ss << time.GetCurrentDateTimeString(Timestamp::DateTimeFormat::YYYYMMDD) << "_" << Timestamp::GetCurrentDateTimeString(Timestamp::DateTimeFormat::HHMMSS, "_") << "_log.txt"; + + ErrorLog::Instance(Util::FileSystem::BuildPath(logPath,ss.str())); + + ConfigFileManager::Instance(); + + UdpSocketMgr::Instance(); + + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} + +//----------------------------------------------------------------------------- + +LinuxProc::~LinuxProc() +{ + LinuxProc::Instance().getEvent(EventNames::GLOBAL_QUIT).signal(); + + if (m_networkingThread != 0) + { + m_networkingThread->quit(); + m_networkingThread->wait(); + delete m_networkingThread; + } + + if (m_fileTransferThread != 0) + { + m_fileTransferThread->quit(); + m_fileTransferThread->waitForThreadToExit(); + delete m_fileTransferThread; + } + + if (KwScenarioStartedMessage::getRunAppThread() != 0) + { + KwScenarioStartedMessage::getRunAppThread()->quit(); + KwScenarioStartedMessage::getRunAppThread()->waitForThreadToExit(); + delete KwScenarioStartedMessage::getRunAppThread(); + } + + if (m_runHostBusThread != 0) + { + m_runHostBusThread->quit(); + m_runHostBusThread->waitForThreadToExit(); + delete m_runHostBusThread; + } + + if (m_pMainWindow != 0) + { + delete m_pMainWindow; + } + + if (m_pFileTransferDialog != 0) + { + delete m_pFileTransferDialog; + } + + if (m_iniFile != 0) + { + delete m_iniFile; + } + + // delete events + std::map::iterator eventIt; + for (eventIt = m_eventMap.begin(); eventIt != m_eventMap.end(); ++eventIt) + { + //std::string name = eventIt->second->GetName(); + delete eventIt->second; + eventIt->second = 0; + } +} + +//---------------------------------------------------------------------------- + +void LinuxProc::initialize() +{ + try { + m_pMainWindow = new MainWindow(); + m_pFileTransferDialog = new FileTransferDialog(); + m_pFileTransferDialog->setWindowFlags(Qt::CustomizeWindowHint); + + m_networkingThread = new NetworkingThread(); + m_networkingThread->start(); + + m_fileTransferThread = new FileTransferThread("FileTransferThread"); + m_fileTransferThread->create(); + m_fileTransferThread->resume(); + + bool showMainWindow = m_iniFile->getBool("GENERAL", "SHOW_MAIN_WINDOW"); + + if (showMainWindow) + m_pMainWindow->show(); + + std::string sectionName = "SWDEV_COMPUTER"; + std::string key = "COMPUTER_NAME_REGEX_PATTERN"; + std::string computerNamePattern = m_iniFile->getString(sectionName,key); + + { + QRegularExpression re(computerNamePattern.c_str(), QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch match = re.match(Util::Misc::GetComputerName().c_str()); + if (match.hasMatch()) + { + m_computerName = Constants::ComputerHosts::SWDEV_PC; + } + } + + if (m_computerName == Constants::ComputerHosts::UNKNOWN_PC) + { + sectionName = "SIXDOF_COMPUTER"; + + computerNamePattern = m_iniFile->getString(sectionName,key); + + { + QRegularExpression re(computerNamePattern.c_str(), QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch match = re.match(Util::Misc::GetComputerName().c_str()); + if (match.hasMatch()) + { + m_computerName = Constants::ComputerHosts::SIXDOF_PC; + + std::string appPath = getConfig().getString(Constants::ConfigSectionNameMapping::sectionMap[m_computerName], "HOSTBUS_APP_PATH"); + bool runApp = getConfig().getBool(Constants::ConfigSectionNameMapping::sectionMap[m_computerName], "RUN_HOSTBUS"); + + if (runApp) + { + m_runHostBusThread = new RunAppThread("RunHostBusThread", appPath, false); + m_runHostBusThread->create(); + m_runHostBusThread->resume(); + } + } + } + } + + if (m_computerName == Constants::ComputerHosts::UNKNOWN_PC) + { + sectionName = "VIDEO_COMPUTER"; + computerNamePattern = m_iniFile->getString(sectionName,key); + + { + QRegularExpression re(computerNamePattern.c_str(), QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch match = re.match(Util::Misc::GetComputerName().c_str()); + if (match.hasMatch()) + { + m_computerName = Constants::ComputerHosts::VIDEO_PC; + } + } + } + + if (m_computerName != Constants::ComputerHosts::UNKNOWN_PC) + { + try + { + showMainWindow = m_iniFile->getBool(sectionName,"SHOW_MAIN_WINDOW"); + if (showMainWindow) + m_pMainWindow->show(); + } + catch (Exception&){} + } + + m_pMainWindow->updateStatusBox("Host: " + Util::Misc::GetComputerName()); + + ConfigFileManager::Instance().parseLogInfo(Constants::ConfigSectionNameMapping::sectionMap[getComputerName()]); + + std::map testDataMap = ConfigFileManager::Instance().getTestDataMap(); + + std::map::iterator it; + + for (it = testDataMap.begin(); it != testDataMap.end(); it++) + { + if (it->second.performCleanUp) + { + Util::PerformLogCleanUp(it->second.path, it->second.fileRegexPatterns); + } + } + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} + +//----------------------------------------------------------------------------- + +void LinuxProc::testAppSingleton() +{ + UdpSocket* udpSock = 0; + try { + int localPort = getConfig().getInt("GENERAL", "APP_SINGLETON_LOCAL_PORT"); + int remotePort = getConfig().getInt("GENERAL", "CMD_LOCAL_PORT"); + + udpSock = new UdpSocket(localPort, remotePort, "localhost"); + + const unsigned int BUF_SIZE = 1024; + + unsigned char data[BUF_SIZE]; + + AreYouThereCmdMessage msg; + msg.format(data); + + udpSock->write(data, msg.getEntireMessageLength()); + + Util::DateTime::Sleep(1000); + unsigned char dataBuf[512]; + int dataSize = 0; + udpSock->read(dataBuf, dataSize); + + if (dataSize > 0) + { + unsigned int msgId = 0; + + AutomationMsgParser::instance().parseMsg(dataBuf, dataSize, &msgId); + + if (msgId == MessageIDs::ARE_YOU_THERE_RSP) + { + AreYouThereRspMessage cmd; + + cmd.parse(dataBuf); + + cmd.executeMessage(); + } + } + + delete udpSock; + + } catch (Exception& e) { + if (udpSock != 0) + delete udpSock; + + e.buildStackTrace(Q_FUNC_INFO); + throw; + } +} + + diff --git a/HWIL_Assistant/src/LinuxProc.hpp b/HWIL_Assistant/src/LinuxProc.hpp new file mode 100644 index 0000000..64f94f1 --- /dev/null +++ b/HWIL_Assistant/src/LinuxProc.hpp @@ -0,0 +1,165 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#ifndef LINUXPROC_H +#define LINUXPROC_H + +#include "Proc.hpp" +#include "EventNames.hpp" +#include "Constants.hpp" + +#include + +class MainWindow; +class FileTransferDialog; +class IniFile; +class Message; +class Condition; +class NetworkingThread; +class FileTransferThread; +class ErrorLog; +class RunAppThread; + +class LinuxProc : public QObject, public Proc +{ + Q_OBJECT + +public: + //>--------------------------------------------------------------------------- + // Function: instance + // + // Purpose: singleton + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + static LinuxProc& Instance(); + + //>--------------------------------------------------------------------------- + // Function: ~LinuxProc + // + // Purpose: Destroyer + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + ~LinuxProc(); + + //>--------------------------------------------------------------------------- + // Function: getConfig + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + IniFile& getConfig(){return *m_iniFile;}; + + //>--------------------------------------------------------------------------- + // Function: getMainWindow + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + MainWindow& getMainWindow(){return *m_pMainWindow;}; + + //>--------------------------------------------------------------------------- + // Function: getFileTransferDialog + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + FileTransferDialog& getFileTransferDialog(){return *m_pFileTransferDialog;}; + + //>--------------------------------------------------------------------------- + // Function: getFileTransferThread + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + FileTransferThread* getFileTransferThread(){return m_fileTransferThread;}; + + //>--------------------------------------------------------------------------- + // Function: getComputerName + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + Constants::ComputerHosts getComputerName(){return m_computerName;} + + //>--------------------------------------------------------------------------- + // Function: initialize + // + // Purpose: + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + void initialize(); + +private: + //>--------------------------------------------------------------------------- + // Function: Proc + // + // Purpose: Ctor + //---------------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------------- + // Return Value: + //---------------------------------------------------------------------------- + LinuxProc(); + + //>--------------------------------------------------------------------- + // Function: testAppSingleton() + // + // Purpose: Make sure only single instance of this app is running + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void testAppSingleton(); + + MainWindow* m_pMainWindow; + FileTransferDialog* m_pFileTransferDialog; + + IniFile* m_iniFile; + std::map m_eventMap; + + FileTransferThread* m_fileTransferThread; + NetworkingThread* m_networkingThread; + RunAppThread* m_runHostBusThread; + + Constants::ComputerHosts m_computerName; +}; + +#endif diff --git a/HWIL_Assistant/src/Misc/GUTS_Assistant.desktop b/HWIL_Assistant/src/Misc/GUTS_Assistant.desktop new file mode 100644 index 0000000..ee1bf75 --- /dev/null +++ b/HWIL_Assistant/src/Misc/GUTS_Assistant.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Name=HWIL_Assistant +Exec=/Released/HWIL_Assistant/HWIL_Assistant +Icon=/Released/HWIL_Assistant/assistant.png +Terminal=false +Type=Application +StartupNotify=true +Actions=new-window;new-private-window; +Name[en_US]=HWIL_Assistant diff --git a/HWIL_Assistant/src/Misc/assistant.png b/HWIL_Assistant/src/Misc/assistant.png new file mode 100644 index 0000000000000000000000000000000000000000..9f4f37831dc5bd9baa60ccba19be0d05f6c22a8f GIT binary patch literal 35063 zcmV*RKwiIzP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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 B-fI8= literal 0 HcmV?d00001 diff --git a/HWIL_Assistant/src/Threads/FileTransferThread.cpp b/HWIL_Assistant/src/Threads/FileTransferThread.cpp new file mode 100644 index 0000000..e5acd3c --- /dev/null +++ b/HWIL_Assistant/src/Threads/FileTransferThread.cpp @@ -0,0 +1,319 @@ +#include "FileTransferThread.hpp" +#include "LinuxProc.hpp" +#include "FileTransferDialog.hpp" +#include "Condition.hpp" +#include "FileSystemUtil.hpp" +#include "DateTimeUtil.hpp" +#include "StringUtil.hpp" +#include "Exception.hpp" +#include "MainWindow.h" +#include "Timestamp.hpp" +#include "ErrorLog.hpp" +#include "IniFile.hpp" + +#include +#include +#include + +//------------------------------------------------------------------------ + +FileTransferThread::FileTransferThread(const std::string& name): + Thread(name), + m_shallWeQuit(false), + m_shallWeSuspend(false), + m_startCondition(name + "_START_EVENT"), + m_totalSizeInBytes(0), + numFilesCopySuccess(0), + numFilesCopyFail(0) +{ +} + +//------------------------------------------------------------------------ + +FileTransferThread::~FileTransferThread() +{ +} + +//------------------------------------------------------------------------ + +void FileTransferThread::operator()() +{ + ErrorLog::Instance().log(getName() + " started", false, ErrorLog::INFO); + + try { + Condition& startFileTransferEvent = LinuxProc::Instance().getEvent(EventNames::START_FILE_TRANSFER); + + while (true) + { + startFileTransferEvent.wait(); + + if (ShallWeExit() == true) + break; + + LinuxProc::Instance().getFileTransferDialog().showWindow(true); + + try { + gatherInfo(); + + transferFiles(); + + } catch (Exception e) { + e.buildStackTrace(Q_FUNC_INFO); + ErrorLog::Instance().log(e.getMessage(), false); + } + + Condition& commandExecutingEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTTION_IN_PROGRESS); + commandExecutingEvent.reset(); // we are not executing command + + Condition& completeEvent = LinuxProc::Instance().getEvent(EventNames::COMMAND_EXECUTION_COMPLETE); + completeEvent.signal(); // we are done executing + + LinuxProc::Instance().getFileTransferDialog().showWindow(false); + + m_sourceDirList.clear(); + m_qFileList.clear(); + m_fileList.clear(); + + if (ShallWeExit() == true) + break; + } + + ErrorLog::Instance().log(getName() + " exited", false, ErrorLog::INFO); + + } catch (Exception e) { + ErrorLog::Instance().log(getName() + " exited", false, ErrorLog::INFO); + + e.buildStackTrace(Q_FUNC_INFO); + ErrorLog::Instance().log(e.getMessage(), false); + } +} + +//------------------------------------------------------------------------ + +void FileTransferThread::gatherInfo() +{ + try + { + FileTransferInfo fileInfo; + for ( int i = 0; i < m_sourceDirList.size(); i++ ) + { + QDir sourceDir(m_sourceDirList[i]); + QStringList fileList = Util::FileSystem::GetListOfFilesInADirectory(sourceDir, true); + + fileInfo.baseSourceDir = m_sourceDirList[i].toStdString(); + for ( int j = 0; j < fileList.size(); j++ ) + { + fileInfo.sourceFile = fileList[j].toStdString(); + m_qFileList.append(fileInfo); + + QFileInfo fi(QString(fileInfo.sourceFile.c_str())); + + m_totalSizeInBytes += fi.size(); + } + } + + for ( int i = 0; i < m_fileList.size(); i++ ) + { + fileInfo.baseSourceDir = Util::FileSystem::ExtractDirectory(m_fileList[i].toStdString()); + fileInfo.sourceFile = m_fileList[i].toStdString(); + m_qFileList.append(fileInfo); + + QFileInfo fi(QString(fileInfo.sourceFile.c_str())); + + m_totalSizeInBytes += fi.size(); + } + + std::stringstream ss; + ss << "Moving " << m_qFileList.size() << " items (" << Util::FileSystem::DescribeFileSize(m_totalSizeInBytes) << ")"; + LinuxProc::Instance().getFileTransferDialog().updateLabel(FileTransferDialog::HEADER_LBL, ss.str()); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void FileTransferThread::transferFiles() +{ + try + { + numFilesCopySuccess = 0; + numFilesCopyFail = 0; + std::string destFile; + FileTransferInfo fileInfo; + + int waitTimeBeforeCreatingTestFolder = LinuxProc::Instance().getConfig().getInt(Constants::ConfigSectionNameMapping::sectionMap[LinuxProc::Instance().getComputerName()], "WAIT_TIME_BEFORE_CREATING_TEST_DATA_FOLDER"); + + int timeElapse = 1; + while (!Util::FileSystem::DirExists(m_destDir)) + { + if (timeElapse++ > waitTimeBeforeCreatingTestFolder) + { + Util::FileSystem::CreateDirectory(m_destDir); + break; + } + + Util::DateTime::Sleep(1000); + } + + LinuxProc::Instance().getFileTransferDialog().startTheTimer(); + + int itemsRemaining = m_qFileList.size(); + int64_t tempTotalSizeInBytes = m_totalSizeInBytes; + for ( int i=0; i < m_qFileList.size(); i++ ) + { + fileInfo = m_qFileList[i]; + QFileInfo fi(fileInfo.sourceFile.c_str()); + int64_t fileSize = fi.size(); + + LinuxProc::Instance().getFileTransferDialog().updateLabel(FileTransferDialog::FILE_NAME_LBL, Util::Strings::ShortenStringToSize(fi.fileName().toStdString(),45) + " (" + Util::FileSystem::DescribeFileSize(fileSize) + ")"); + + LinuxProc::Instance().getFileTransferDialog().updateLabel(FileTransferDialog::FROM_DIR_LBL, Util::Strings::ShortenStringToSize(Util::FileSystem::BuildPath(fi.absolutePath().toStdString(),""),50)); + + LinuxProc::Instance().getFileTransferDialog().updateLabel(FileTransferDialog::ITEMS_REMAIN_LBL, QString::number(itemsRemaining).toStdString() + " (" + Util::FileSystem::DescribeFileSize(m_totalSizeInBytes) + ")"); + + LinuxProc::Instance().getFileTransferDialog().updateLabel(FileTransferDialog::TO_DIR_LBL, Util::Strings::ShortenStringToSize(destFile,50)); + + destFile = Util::FileSystem::BuildPath(m_destDir, fi.fileName().toStdString()); + + QFile sourceFile(fileInfo.sourceFile.c_str()); + + std::stringstream ss; + if (fileSize > 0) + { + QDateTime modifiedDate = fi.lastModified(); + QDateTime accessedDate = fi.lastRead(); + + // moving the file + bool success = sourceFile.rename(destFile.c_str()); + + ss << "Copying " << fi.fileName().toStdString() << " - "; + if (success) + { + Util::FileSystem::ChangeFileDateTime(destFile, modifiedDate, accessedDate); + ss << "SUCCESS"; + numFilesCopySuccess++; + } + else + { + ss << "FAIL"; + numFilesCopyFail++; + } + ss << "\n " + << "From: " << Util::FileSystem::BuildPath(fi.absolutePath().toStdString(),"") + << "\n " + << "To: "; + + QFileInfo fi2(destFile.c_str()); + ss << Util::FileSystem::BuildPath(fi2.absolutePath().toStdString(),""); + } + else + { + numFilesCopySuccess++; + QFile file(fileInfo.sourceFile.c_str()); + // remove empty file + bool success = file.remove(); + ss << "Removing " << fi.fileName().toStdString() << ", empty file - "; + if (success) + ss << "SUCCESS"; + else + ss << "FAIL"; + ss << "\n " + << "From: " << Util::FileSystem::BuildPath(fi.absolutePath().toStdString(),""); + } + ss << "\n"; + ErrorLog::Instance().log(ss.str(), false, ErrorLog::INFO); + + m_totalSizeInBytes -= fileSize; + itemsRemaining--; + } + + LinuxProc::Instance().getFileTransferDialog().stopTheTimer(); + + for ( int i=0; i < m_sourceDirList.size(); i++) + { + removeEmptyFolders(m_sourceDirList[i]); + } + + { + std::stringstream ss; + ss << "************************************************************************************" + << "\n" + << " Summary:" + << "\n" + << " Total files: " << m_qFileList.size() + << "\n" + << " # files copied with success: " << numFilesCopySuccess + << "\n" + << " # files copied with failure: " << numFilesCopyFail + << "\n" + << " Total size of all files: " << Util::FileSystem::DescribeFileSize(tempTotalSizeInBytes) + << "\n" + << " Transfer time: " << Util::DateTime::DescribeTimeElapsed(LinuxProc::Instance().getFileTransferDialog().getElapsedTimeSec()) + << "\n"; + if (LinuxProc::Instance().getFileTransferDialog().getElapsedTimeSec() > 0) + { + ss << " Estimated transfer speed: " << Util::FileSystem::DescribeFileSize(tempTotalSizeInBytes / LinuxProc::Instance().getFileTransferDialog().getElapsedTimeSec()) << " / s" + << "\n"; + } + ss << "************************************************************************************" + << "\n"; + ErrorLog::Instance().log(ss.str(), false, ErrorLog::INFO); + } + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +void FileTransferThread::removeEmptyFolders(QString topLevelDir) +{ + try + { + QDirIterator it(topLevelDir, QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); + + while(it.hasNext()) + { + it.next(); + removeEmptyFolders(it.filePath()); + } + + QDir dir(topLevelDir); + dir.rmdir(dir.absolutePath()); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } +} + +//------------------------------------------------------------------------ + +bool FileTransferThread::ShallWeExit() +{ + return m_shallWeQuit; +} + +//------------------------------------------------------------------------ + +bool FileTransferThread::ShallWeSuspend() +{ + return m_shallWeSuspend; +} + +//------------------------------------------------------------------------ + +void FileTransferThread::quit() +{ + m_shallWeQuit = true; + Condition& startFileTransferEvent = LinuxProc::Instance().getEvent(EventNames::START_FILE_TRANSFER); + startFileTransferEvent.signal(); +} diff --git a/HWIL_Assistant/src/Threads/FileTransferThread.hpp b/HWIL_Assistant/src/Threads/FileTransferThread.hpp new file mode 100644 index 0000000..2b24da2 --- /dev/null +++ b/HWIL_Assistant/src/Threads/FileTransferThread.hpp @@ -0,0 +1,207 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#ifndef FILETRANSFERTHREAD_H +#define FILETRANSFERTHREAD_H + +#include "Thread.hpp" + +#include + +class FileTransferThread : public Thread +{ +public: + struct FileTransferInfo { + std::string baseSourceDir; + std::string sourceFile; + }; + + //>--------------------------------------------------------------------- + // Function: FileTransferThread + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + FileTransferThread(const std::string& name); + + //>--------------------------------------------------------------------- + // Function: ~FileTransferThread + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual ~FileTransferThread(); + + //>--------------------------------------------------------------------- + // Function: operator + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void operator()(); + + //>--------------------------------------------------------------------- + // Function: StartThread() + // + // Purpose: Commands the thread to run + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: nonestd + //<--------------------------------------------------------------------- + virtual void startThread(){m_startCondition.signal();} + + //>--------------------------------------------------------------------- + // Function: SuspendThread() + // + // Purpose: Commands the thread to pause its execution + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void suspendThread(){m_shallWeSuspend = true;} + + //>--------------------------------------------------------------------- + // Function: Quit() + // + // Purpose: Command the thread to exit + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void quit(); + + //>--------------------------------------------------------------------- + // Function: addSourceDir + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // sourceDir - + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void addSourceDir(std::string sourceDir) {m_sourceDirList.append(sourceDir.c_str());} + + //>--------------------------------------------------------------------- + // Function: addSourceDir + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // sourceDir - + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void addSourceFile(std::string sourceDir) {m_fileList.append(sourceDir.c_str());} + + //>--------------------------------------------------------------------- + // Function: setDestDir + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // destDir - + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void setDestDir(std::string destDir) {m_destDir = destDir;}; + + //>--------------------------------------------------------------------- + // Function: setUut + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // destDir - + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void setUut(std::string uut) {m_uut = uut;}; + +private: + // do not allow + FileTransferThread(); + FileTransferThread(const FileTransferThread ©); + FileTransferThread &operator=(const FileTransferThread &rhs); + + //>--------------------------------------------------------------------- + // Function: gatherInfo + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void gatherInfo(); + + //>--------------------------------------------------------------------- + // Function: transferFiles + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void transferFiles(); + + //>--------------------------------------------------------------------- + // Function: removeEmptyFolders + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + // + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void removeEmptyFolders(QString topLevelDir); + + bool ShallWeSuspend(); + bool ShallWeExit(); + + bool m_shallWeQuit; + bool m_shallWeSuspend; + Condition m_startCondition; + + QStringList m_sourceDirList; + QStringList m_fileList; + std::string m_destDir; + std::string m_uut; + + QList m_qFileList; + int64_t m_totalSizeInBytes; + int numFilesCopySuccess; + int numFilesCopyFail; +}; + +#endif // FILETRANSFERTHREAD_H diff --git a/HWIL_Assistant/src/Threads/NetworkingThread.cpp b/HWIL_Assistant/src/Threads/NetworkingThread.cpp new file mode 100644 index 0000000..28426dd --- /dev/null +++ b/HWIL_Assistant/src/Threads/NetworkingThread.cpp @@ -0,0 +1,40 @@ +#include "NetworkingThread.hpp" +#include "UdpSocketMgr.hpp" +#include "FileTransferDialog.hpp" +#include "Condition.hpp" +#include "Util.hpp" +#include "Exception.hpp" +#include "MainWindow.h" +#include "ErrorLog.hpp" +#include "Proc.hpp" + +#include + +NetworkingThread::NetworkingThread() +{ + // Setup callback for cleanup when it finishes + connect(this, SIGNAL(finished()), + this, SLOT(deleteLater())); +} + +NetworkingThread::~NetworkingThread() +{ +} + +void NetworkingThread::run() +{ + ErrorLog::Instance().log("NetworkingThread started", false, ErrorLog::INFO); + + try { + // signals and slots for this QUdpSocket object will be handled by this thread + UdpSocketMgr::Instance().setUpUdpSocket(); + + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + ErrorLog::Instance().log(e.getMessage(), false); + } + + exec(); // run the event loop. + + ErrorLog::Instance().log("NetworkingThread exited", false, ErrorLog::INFO); +} diff --git a/HWIL_Assistant/src/Threads/NetworkingThread.hpp b/HWIL_Assistant/src/Threads/NetworkingThread.hpp new file mode 100644 index 0000000..c6a49f5 --- /dev/null +++ b/HWIL_Assistant/src/Threads/NetworkingThread.hpp @@ -0,0 +1,63 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#ifndef NETWORKINGTHREAD_H +#define NETWORKINGTHREAD_H + +#include + +class MainWindow; + +class NetworkingThread : public QThread +{ +Q_OBJECT +public: + //>--------------------------------------------------------------------- + // Function: NetworkingThread + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + NetworkingThread(); + + //>--------------------------------------------------------------------- + // Function: ~NetworkingThread + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ~NetworkingThread(); + +private: + //>--------------------------------------------------------------------- + // Function: run + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void run(); +}; + +#endif diff --git a/HWIL_Assistant/src/Threads/RunAppThread.cpp b/HWIL_Assistant/src/Threads/RunAppThread.cpp new file mode 100644 index 0000000..3aca008 --- /dev/null +++ b/HWIL_Assistant/src/Threads/RunAppThread.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include + +#include "qprocess.h" + +#include "ErrorLog.hpp" +#include "RunAppThread.hpp" +#include "Exception.hpp" +#include "LinuxProc.hpp" +#include "FileSystemUtil.hpp" +#include "Util.hpp" +#include "IniFile.hpp" +#include "MainWindow.h" + +//------------------------------------------------------------------------ + +RunAppThread::RunAppThread(const std::string& name, const std::string& appPath, const bool& runAppInLoop) : + Thread(name), + m_shallWeQuit(false), + m_shallWeSuspend(false), + m_runAppInLoop(runAppInLoop), + m_appPath(appPath), + m_startCondition(name + "_START_EVENT") +{ + try + { + + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw e; + } + catch (...) + { + throw Exception(Q_FUNC_INFO, "caught unknown error"); + } +} + +//------------------------------------------------------------------------ + +RunAppThread::~RunAppThread() +{ + +} + +//------------------------------------------------------------------------ + +void RunAppThread::operator()() +{ + ErrorLog::Instance().log(getName() + " started", false, ErrorLog::INFO); + + try { + if (Util::FileSystem::FileExists(m_appPath)) + { + if (m_runAppInLoop) + runAppInLoop(); + else + runAppOnce(); + } + else + { + throw Exception(Q_FUNC_INFO,m_appPath + " does not exist"); + } + + ErrorLog::Instance().log(getName() + " exited", false, ErrorLog::INFO); + + } catch (Exception& e) { + e.buildStackTrace(Q_FUNC_INFO); + ErrorLog::Instance().log(e.getMessage(), false); + ErrorLog::Instance().log(getName() + " exited", false, ErrorLog::INFO); + } +} + +//------------------------------------------------------------------------ + +void RunAppThread::runAppInLoop() +{ + try + { + std::string appName = Util::FileSystem::ExtractFilename(m_appPath); + while (true) + { + // wait here until command to start + m_startCondition.wait(); + + if (shallWeExit() == true) + break; + + LinuxProc::Instance().getMainWindow().updateStatusBox("Running " + appName); + + chdir(Util::FileSystem::ExtractDirectory(m_appPath).c_str()); + std::string cmd = "./" + appName; + system(cmd.c_str()); + + LinuxProc::Instance().getMainWindow().updateStatusBox(m_appPath + " has exited"); + + if (shallWeExit() == true) + break; + } + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } + catch (...) + { + } +} + +//------------------------------------------------------------------------ + +void RunAppThread::runAppOnce() +{ + try + { + std::string appName = Util::FileSystem::ExtractFilename(m_appPath); + LinuxProc::Instance().getMainWindow().updateStatusBox("Running " + appName); + + chdir(Util::FileSystem::ExtractDirectory(m_appPath).c_str()); + std::string cmd = "./" + appName; + system(cmd.c_str()); + + LinuxProc::Instance().getMainWindow().updateStatusBox(m_appPath + " has exited"); + } + catch (Exception& e) + { + e.buildStackTrace(Q_FUNC_INFO); + throw; + } + catch (...) + { + } +} + +//------------------------------------------------------------------------ + +void RunAppThread::quit() + { + if (m_runAppInLoop) + { + m_shallWeQuit = true; + startThread(); + } + else + { + Util::KillProcess(Util::FileSystem::ExtractFilename(m_appPath), false); + } + } + +//------------------------------------------------------------------------ + +bool RunAppThread::shallWeExit() +{ + return m_shallWeQuit; +} + +//------------------------------------------------------------------------ + +bool RunAppThread::shallWeSuspend() +{ + return m_shallWeSuspend; +} diff --git a/HWIL_Assistant/src/Threads/RunAppThread.hpp b/HWIL_Assistant/src/Threads/RunAppThread.hpp new file mode 100644 index 0000000..665ee30 --- /dev/null +++ b/HWIL_Assistant/src/Threads/RunAppThread.hpp @@ -0,0 +1,111 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ + +#pragma once + +#include "Thread.hpp" + +class RunAppThread : public Thread +{ +public: + //>--------------------------------------------------------------------- + // Function: Thread() + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: name - the name of this thread + // streamName - the hsdc stream name to read from + // pVideoFrameTableAllocated - the buffer to put the data we read into + // pProc - the process this thread is running under + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + RunAppThread(const std::string& threadName, const std::string& appPath, const bool& runAppInLoop); + + //>--------------------------------------------------------------------- + // Function: ~Thread() + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual ~RunAppThread(); + + //>--------------------------------------------------------------------- + // Function: operator()() + // + // Purpose: where all the action is in the derived classes + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void operator()(); + + //>--------------------------------------------------------------------- + // Function: StartThread() + // + // Purpose: Commands the thread to run + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: nonestd + //<--------------------------------------------------------------------- + virtual void startThread(){m_startCondition.signal();} + + //>--------------------------------------------------------------------- + // Function: SuspendThread() + // + // Purpose: Commands the thread to pause its execution + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void suspendThread(){m_shallWeSuspend = true;} + + //>--------------------------------------------------------------------- + // Function: Quit() + // + // Purpose: Command the thread to exit + //---------------------------------------------------------------------- + // Arguments: none + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + virtual void quit(); + +private: + // do not allow + RunAppThread(); + RunAppThread(const RunAppThread ©); + RunAppThread &operator=(const RunAppThread &rhs); + + bool shallWeSuspend(); + bool shallWeExit(); + + void runAppInLoop(); + void runAppOnce(); + + bool m_shallWeQuit; + bool m_shallWeSuspend; + bool m_runAppInLoop; + std::string m_appPath; + Condition m_startCondition; +}; diff --git a/HWIL_Assistant/src/UI/FileTransferDialog.cpp b/HWIL_Assistant/src/UI/FileTransferDialog.cpp new file mode 100644 index 0000000..e35f196 --- /dev/null +++ b/HWIL_Assistant/src/UI/FileTransferDialog.cpp @@ -0,0 +1,133 @@ +#include "FileTransferDialog.hpp" +#include "ui_FileTransferDialog.h" +#include "DateTimeUtil.hpp" + +//------------------------------------------------------------------------ + +FileTransferDialog::FileTransferDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::FileTransferDialog), + m_timeElapsedSec(0) +{ + ui->setupUi(this); + +#ifndef LINUX_PLATFORM + QFont f( "Segoe UI", 12, QFont::Normal); + ui->Header->setFont( f); + ui->label1->setFont(f); + ui->label1_2->setFont(f); + ui->label1_3->setFont(f); + ui->label1_4->setFont(f); + ui->label1_5->setFont(f); + + ui->FileName->setFont(f); + ui->From->setFont(f); + ui->To->setFont(f); + ui->ItemsRemain->setFont(f); + ui->TimeElapsed->setFont(f); + + ui->label1_4->setGeometry(ui->label1_4->x(), ui->label1_4->y(), ui->label1_4->width() + 5, ui->label1_4->height()); +#endif + + connect(this, SIGNAL(LabelChanged(int,QString)), this, SLOT(on_LabelChanged(int,QString))); + connect(this, SIGNAL(ShowWindowChanged(bool)), this, SLOT(on_ShowWindowChanged(bool))); + connect(this, SIGNAL(startTheTimerChanged()), this, SLOT(on_startTheTimer())); + connect(this, SIGNAL(stopTheTimerChanged()), this, SLOT(on_stopTheTimer())); +} + +//------------------------------------------------------------------------ + +FileTransferDialog::~FileTransferDialog() +{ + delete ui; +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::updateLabel(LABEL label, std::string msg) +{ + emit LabelChanged(label, msg.c_str()); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::on_LabelChanged(int label, QString msg) +{ + if (label == HEADER_LBL) + { + ui->Header->setText(msg); + } + else if (label == FILE_NAME_LBL) + { + ui->FileName->setText(msg); + } + else if (label == FROM_DIR_LBL) + { + ui->From->setText(msg); + } + else if (label == TO_DIR_LBL) + { + ui->To->setText(msg); + } + else if (label == ITEMS_REMAIN_LBL) + { + ui->ItemsRemain->setText(msg); + } + else if (label == TIME_ELAPSED) + { + ui->TimeElapsed->setText(msg); + } +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::showWindow(bool show) +{ + emit ShowWindowChanged(show); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::on_ShowWindowChanged(bool show) +{ + if (show) + this->show(); + else + this->hide(); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::on_startTheTimer() +{ + m_timeElapsedSec = 0; + m_timerId = startTimer(1000); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::on_stopTheTimer() +{ + killTimer(m_timerId); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::timerEvent(QTimerEvent *) +{ + ui->TimeElapsed->setText(Util::DateTime::DescribeTimeElapsed(m_timeElapsedSec++).c_str()); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::startTheTimer() +{ + emit startTheTimerChanged(); +} + +//------------------------------------------------------------------------ + +void FileTransferDialog::stopTheTimer() +{ + emit stopTheTimerChanged(); +} diff --git a/HWIL_Assistant/src/UI/FileTransferDialog.hpp b/HWIL_Assistant/src/UI/FileTransferDialog.hpp new file mode 100644 index 0000000..78f806f --- /dev/null +++ b/HWIL_Assistant/src/UI/FileTransferDialog.hpp @@ -0,0 +1,188 @@ +// UNCLASSIFIED +/*------------------------------------------------------------------------- +RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION +PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS +AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO +UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO +RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS +CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS +OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON +COMPANY. + +THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. +GOVERNMENT. + +UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. +-------------------------------------------------------------------------*/ +#ifndef FILETRANSFERDIALOG_HPP +#define FILETRANSFERDIALOG_HPP + +#include + +namespace Ui { +class FileTransferDialog; +} + +class FileTransferDialog : public QDialog +{ + Q_OBJECT + +public: + enum LABEL + { + HEADER_LBL, + FILE_NAME_LBL, + FROM_DIR_LBL, + TO_DIR_LBL, + ITEMS_REMAIN_LBL, + TIME_ELAPSED + }; + + //>--------------------------------------------------------------------- + // Function: FileTransferDialog + // + // Purpose: constructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + explicit FileTransferDialog(QWidget *parent = nullptr); + + //>--------------------------------------------------------------------- + // Function: ~FileTransferDialog + // + // Purpose: destructor + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + ~FileTransferDialog(); + + //>--------------------------------------------------------------------- + // Function: updateLabel + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void updateLabel(LABEL label, std::string msg); + + //>--------------------------------------------------------------------- + // Function: showWindow + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void showWindow(bool show); + + //>--------------------------------------------------------------------- + // Function: startTheTimer + // + // Purpose: wrapper to emit a signal + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void startTheTimer(); + + //>--------------------------------------------------------------------- + // Function: stopTheTimer + // + // Purpose: wrapper to emit a signal + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void stopTheTimer(); + + //>--------------------------------------------------------------------- + // Function: getElapsedTimeSec + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + int getElapsedTimeSec() {return m_timeElapsedSec;}; + +public slots: + //>--------------------------------------------------------------------- + // Function: on_LabelChanged + // + // Purpose: change the text of a label + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void on_LabelChanged(int label, QString msg); + + //>--------------------------------------------------------------------- + // Function: on_ShowWindowChanged + // + // Purpose: show or hide this dialog + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void on_ShowWindowChanged(bool show); + + //>--------------------------------------------------------------------- + // Function: on_startTheTimer + // + // Purpose: start the timer + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void on_startTheTimer(); + + //>--------------------------------------------------------------------- + // Function: on_stopTheTimer + // + // Purpose: stop the timer + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void on_stopTheTimer(); + +signals: + void LabelChanged(int label, QString msg); + void ShowWindowChanged(bool show); + + void startTheTimerChanged(); + void stopTheTimerChanged(); + +private: + //>--------------------------------------------------------------------- + // Function: timerEvent + // + // Purpose: + //---------------------------------------------------------------------- + // Arguments: + //---------------------------------------------------------------------- + // Return Value: none + //<--------------------------------------------------------------------- + void timerEvent(QTimerEvent *event) override; + + Ui::FileTransferDialog *ui; + + int m_timerId; + int m_timeElapsedSec; +}; + +#endif // FILETRANSFERDIALOG_HPP diff --git a/HWIL_Assistant/src/UI/FileTransferDialog.ui b/HWIL_Assistant/src/UI/FileTransferDialog.ui new file mode 100644 index 0000000..4e440ee --- /dev/null +++ b/HWIL_Assistant/src/UI/FileTransferDialog.ui @@ -0,0 +1,240 @@ + + + FileTransferDialog + + + + 0 + 0 + 555 + 244 + + + + Dialog + + + background-color: rgb(255, 255, 255); + + + + + 20 + 60 + 47 + 13 + + + + + Sans Serif + 10 + + + + Name + + + + + + 150 + 54 + 401 + 21 + + + + + Sans Serif + 10 + + + + processing + + + + + + 6 + 0 + 551 + 41 + + + + + Sans Serif + 12 + + + + background-color: qlineargradient(spread:pad, x1:1, y1:0.0340909, x2:0, y2:0.0113636, stop:0 rgba(0, 86, 255, 255), stop:1 rgba(255, 255, 255, 255)); + + + processing... please wait + + + 9 + + + + + + 22 + 95 + 47 + 13 + + + + + Sans Serif + 10 + + + + From + + + + + + 23 + 130 + 47 + 13 + + + + + Sans Serif + 10 + + + + To + + + + + + 23 + 163 + 111 + 21 + + + + + Sans Serif + 10 + + + + Items Remaining + + + + + + 23 + 199 + 91 + 21 + + + + + Sans Serif + 10 + + + + QFrame::NoFrame + + + Time Elasped + + + + + + 150 + 88 + 401 + 21 + + + + + Sans Serif + 10 + + + + processing + + + + + + 150 + 125 + 401 + 21 + + + + + Sans Serif + 10 + + + + processing + + + + + + 150 + 162 + 401 + 21 + + + + + Sans Serif + 10 + + + + processing + + + + + + 150 + 197 + 401 + 21 + + + + + Sans Serif + 10 + + + + processing + + + + + + diff --git a/HWIL_Assistant/src/UI/MainWindow.cpp b/HWIL_Assistant/src/UI/MainWindow.cpp new file mode 100644 index 0000000..8bb424e --- /dev/null +++ b/HWIL_Assistant/src/UI/MainWindow.cpp @@ -0,0 +1,102 @@ +#include "MainWindow.h" +#include "ui_mainwindow.h" +#include +#include + +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), + ui(new Ui::MainWindow), + m_lastCursorPos(), + cursorXGoingEast(true), + cursorYGoingSouth(true) +{ + ui->setupUi(this); + + connect(this, SIGNAL(statusBoxChanged(QString)), this, SLOT(on_StatusBoxChanged(QString))); + + timerId = startTimer(30000); +} + +MainWindow::~MainWindow() +{ + killTimer(timerId); + delete ui; +} + +void MainWindow::updateStatusBox(std::string msg) { + + emit statusBoxChanged(msg.c_str()); +} + +void MainWindow::on_StatusBoxChanged(QString msg) { + + ui->statusBox->appendPlainText(msg); +} + +void MainWindow::showEvent( QShowEvent* event ) +{ + QWidget::showEvent( event ); +} + +void MainWindow::timerEvent(QTimerEvent *) +{ + QCursor cursor; + + if (m_lastCursorPos.x() == cursor.pos().x() && m_lastCursorPos.y() == cursor.pos().y()) + { + QScreen *screen = QGuiApplication::primaryScreen(); + QRect screenGeometry = screen->geometry(); + int height = screenGeometry.height(); + int width = screenGeometry.width(); + + int newX = 0; + int newY = 0; + + if (cursorXGoingEast) + newX = cursor.pos().x() + 50; + else + newX = cursor.pos().x() - 50; + + if (cursorYGoingSouth) + newY = cursor.pos().y() + 50; + else + newY = cursor.pos().y() - 50; + + + if (newX > width) + { + newX = cursor.pos().x() - 50; + cursorXGoingEast = false; + } + else if (newX < 0) + { + newX = cursor.pos().x() + 50; + cursorXGoingEast = true; + } + + if (newY > height) + { + newY = cursor.pos().y() - 50; + cursorYGoingSouth = false; + } + else if (newY < 0) + { + newY = cursor.pos().y() + 50; + cursorYGoingSouth = true; + } + + m_lastCursorPos.setX(newX); + m_lastCursorPos.setY(newY); + + cursor.setPos(newX, newY); + + QTest::mouseClick(this, Qt::RightButton, Qt::NoModifier, QPoint(newX, newY)); + QTest::mouseClick(this, Qt::RightButton, Qt::NoModifier, QPoint(newX, newY)); + } + else + { + m_lastCursorPos = cursor.pos(); + } +} diff --git a/HWIL_Assistant/src/UI/MainWindow.h b/HWIL_Assistant/src/UI/MainWindow.h new file mode 100644 index 0000000..89cebf1 --- /dev/null +++ b/HWIL_Assistant/src/UI/MainWindow.h @@ -0,0 +1,36 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + + void updateStatusBox(std::string msg); + +public slots: + void on_StatusBoxChanged(QString msg); + +signals: + void statusBoxChanged(QString msg); + +private: + void showEvent( QShowEvent* event ) override; + void timerEvent(QTimerEvent *event) override; + + Ui::MainWindow *ui; + int timerId; + QPoint m_lastCursorPos; + bool cursorXGoingEast; + bool cursorYGoingSouth; +}; +#endif // MAINWINDOW_H diff --git a/HWIL_Assistant/src/UI/mainwindow.ui b/HWIL_Assistant/src/UI/mainwindow.ui new file mode 100644 index 0000000..47db957 --- /dev/null +++ b/HWIL_Assistant/src/UI/mainwindow.ui @@ -0,0 +1,42 @@ + + + MainWindow + + + + 0 + 0 + 858 + 694 + + + + HWIL Assistant + + + + + + 10 + 10 + 841 + 631 + + + + + + + + 0 + 0 + 858 + 25 + + + + + + + + diff --git a/HWIL_Assistant/src/main.cpp b/HWIL_Assistant/src/main.cpp new file mode 100644 index 0000000..e1a3c09 --- /dev/null +++ b/HWIL_Assistant/src/main.cpp @@ -0,0 +1,43 @@ +#include "LinuxProc.hpp" +#include "Exception.hpp" +#include "MainWindow.h" +#include "ErrorLog.hpp" + +#include +#include + +int main(int argc, char *argv[]) +{ + int ret = 0; + + QApplication a(argc, argv); + + try { + LinuxProc::Instance(); + + try { + LinuxProc::Instance().initialize(); + + } catch (Exception& e) { + MainWindow* pMainWindow = static_cast(&LinuxProc::Instance().getMainWindow()); + + if (pMainWindow != 0) + { + LinuxProc::Instance().getMainWindow().close(); + } + ErrorLog::Instance().log(e.getMessage()); + throw; + } + + // this will loop indefinitely until we close the main GUI + ret = a.exec(); + + } catch (Exception& e) { + QMessageBox msgBox; + msgBox.setWindowTitle("Fatal Error"); + msgBox.setText(e.getMessage(Exception::ERROR_MESSAGE_ONLY).c_str()); + msgBox.exec(); + } + + return ret; +}