Skip to content

Commit

Permalink
- Output Host IP in log (for debugging purposes) and additional logging
Browse files Browse the repository at this point in the history
- Display warning in UI when TV is configured on a subnet different from PC
 - Add service dependencies
 - Set service shutdown priority
- Implemented option to automatically check for new application version (off by default)
- Bug fixes and optimisations
  • Loading branch information
JPersson77 committed May 3, 2021
1 parent 7f7e782 commit 090d7e9
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 28 deletions.
57 changes: 52 additions & 5 deletions LGTV Companion Service/Service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ PREFS Prefs; //App preferences
vector <CSession> DeviceCtrlSessions; //CSession objects manage network connections with Display
DWORD EventCallbackStatus = NULL;
WSADATA WSAData;
mutex g_mutex;
//mutex g_mutex;
wstring DataPath;
vector<string> HostIPs;

Expand Down Expand Up @@ -313,6 +313,15 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR* lpszArgv)
thread thread_obj(IPCThread);
thread_obj.detach();

if (SetProcessShutdownParameters(0x1E1, 0))
Log("Setting shutdown parameter level 0x1E1");
// else if (SetProcessShutdownParameters(0x3ff, 0))
// Log("Setting shutdown parameter level 0x3FF");
else
Log("Could not set shutdown parameter level");

SetProcessShutdownParameters(0x3FF,0);

ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
//register to receive power notifications
gPs1 = RegisterPowerSettingNotification(gSvcStatusHandle, &(GUID_CONSOLE_DISPLAY_STATE), DEVICE_NOTIFY_SERVICE_HANDLE);
Expand Down Expand Up @@ -348,7 +357,7 @@ VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHi

if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_POWEREVENT;// | SERVICE_ACCEPT_USERMODEREBOOT; //does not work
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_POWEREVENT; //SERVICE_ACCEPT_PRESHUTDOWN | // | SERVICE_ACCEPT_USERMODEREBOOT; //does not work

if ((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED))
Expand All @@ -361,10 +370,26 @@ VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHi
// Called by SCM whenever a control code is sent to the service using the ControlService function. dwCtrl - control code
DWORD SvcCtrlHandler(DWORD dwCtrl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
bool bThreadNotFinished;

switch (dwCtrl)
{
case SERVICE_CONTROL_STOP: // works
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 20000);

do
{
bThreadNotFinished = false;

for (auto& dev : DeviceCtrlSessions)
{
if (dev.IsBusy())
bThreadNotFinished = true;
}
if (bThreadNotFinished)
Sleep(100);
} while (bThreadNotFinished);


// Signal the service to stop.
SetEvent(ghSvcStopEvent);
Expand Down Expand Up @@ -441,7 +466,7 @@ DWORD SvcCtrlHandler(DWORD dwCtrl, DWORD dwEventType, LPVOID lpEventData, LPVOI
default:break;
}
break;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_PRESHUTDOWN:
if (EventCallbackStatus == SYSTEM_EVENT_REBOOT)
{
Log("** System is restarting.");
Expand All @@ -463,7 +488,29 @@ DWORD SvcCtrlHandler(DWORD dwCtrl, DWORD dwEventType, LPVOID lpEventData, LPVOI
Log("WARNING! The application did not receive an Event Subscription Callback prior to system shutting down. Unable to determine if system is shutting down or restarting.");
DispatchSystemPowerEvent(SYSTEM_EVENT_UNSURE);
}

//copy paste from the STOP event below
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 20000);

do
{
bThreadNotFinished = false;

for (auto& dev : DeviceCtrlSessions)
{
if (dev.IsBusy())
bThreadNotFinished = true;
}
if(bThreadNotFinished)
Sleep(100);
} while (bThreadNotFinished);


// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
break;

case SERVICE_CONTROL_INTERROGATE:
Log("SERVICE_CONTROL_INTERROGATE");
break;
Expand Down
10 changes: 6 additions & 4 deletions LGTV Companion Service/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#pragma comment(lib, "Advapi32.lib")

#define APPNAME L"LGTV Companion"
#define APPVERSION L"1.2.3"
#define APPVERSION L"1.3.0"
#define SVCNAME L"LGTVsvc"
#define SVCDISPLAYNAME L"LGTV Companion Service"
#define SERVICE_PORT "3000"
Expand All @@ -45,7 +45,7 @@
#define DEFAULT_RESTART {"restart"}
#define DEFAULT_SHUTDOWN {"shutdown","power off"}

#define SERVICE_DEPENDENCIES NULL //L"Dhcp\0Dnscache\0\0"
#define SERVICE_DEPENDENCIES L"Dhcp\0Dnscache\0LanmanServer\0\0"
#define SERVICE_ACCOUNT NULL //L"NT AUTHORITY\\LocalService"
#define MUTEX_WAIT 10 // thread wait in ms
#define THREAD_WAIT 5 // wait to spawn new thread (seconds)
Expand Down Expand Up @@ -103,9 +103,11 @@ class CSession {
void Stop();
void SystemEvent(DWORD);
SESSIONPARAMETERS GetParams();
bool IsBusy();
private:
bool ThreadedOperationsRunning = false;
void TurnOnDisplay(void);
bool ThreadedOpDisplayOn = false;
bool ThreadedOpDisplayOff = false;
void TurnOnDisplay(void);
void TurnOffDisplay(void);
SESSIONPARAMETERS Parameters;
};
Expand Down
73 changes: 63 additions & 10 deletions LGTV Companion Service/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ SESSIONPARAMETERS CSession::GetParams(void)
mMutex.unlock();
return copy;
}
bool CSession::IsBusy(void)
{
bool ret;
//thread safe section
while (!mMutex.try_lock())
Sleep(MUTEX_WAIT);
ret = ThreadedOpDisplayOn||ThreadedOpDisplayOff;
mMutex.unlock();
return ret;
}
void CSession::TurnOnDisplay(void)
{
string s;
Expand All @@ -54,14 +64,15 @@ void CSession::TurnOnDisplay(void)
Sleep(MUTEX_WAIT);


if (!ThreadedOperationsRunning)
if (!ThreadedOpDisplayOn)
{
s = Parameters.DeviceId;
s += ", spawning DisplayPowerOnThread().";

ThreadedOperationsRunning = true;
// TimeStamp = time(0);
thread thread_obj(DisplayPowerOnThread, &Parameters, &ThreadedOperationsRunning, Parameters.PowerOnTimeout);
ThreadedOpDisplayOn = true;
// ThreadedOperationsTimeStamp = time(0);

thread thread_obj(DisplayPowerOnThread, &Parameters, &ThreadedOpDisplayOn, Parameters.PowerOnTimeout);
thread_obj.detach();
}
else
Expand All @@ -81,14 +92,14 @@ void CSession::TurnOffDisplay(void)
while (!mMutex.try_lock())
Sleep(MUTEX_WAIT);

if (!ThreadedOperationsRunning && Parameters.SessionKey != "")
if (!ThreadedOpDisplayOff && Parameters.SessionKey != "")
{
s = Parameters.DeviceId;
s += ", spawning DisplayPowerOffThread().";

ThreadedOperationsRunning = true;
// TimeStamp = time(0);
thread thread_obj(DisplayPowerOffThread, &Parameters, &ThreadedOperationsRunning);
ThreadedOpDisplayOff = true;
// ThreadedOperationsTimeStamp = time(0);
thread thread_obj(DisplayPowerOffThread, &Parameters, &ThreadedOpDisplayOff);
thread_obj.detach();
}
else
Expand Down Expand Up @@ -424,8 +435,14 @@ void WOLthread (SESSIONPARAMETERS* CallingSessionParameters, bool* CallingSessio
// THREAD: Spawned when the device should power OFF.
void DisplayPowerOffThread(SESSIONPARAMETERS* CallingSessionParameters, bool* CallingSessionThreadRunning)
{
time_t origtim = time(0);

// Log("DEBUG INFO: DisplayPowerOffThread() running...");
if (!CallingSessionParameters)
{
// Log("DEBUG INFO: DisplayPowerOffThread() :: CallingSessionParameters is zero");
return;
}
if (CallingSessionParameters->SessionKey != "") //assume we have paired here. Doe not make sense to try pairing when display shall turn off.
{
string host = CallingSessionParameters->IP;
Expand All @@ -438,16 +455,28 @@ void DisplayPowerOffThread(SESSIONPARAMETERS* CallingSessionParameters, bool* Ca

try
{
net::io_context ioc;
// Log("DEBUG INFO: DisplayPowerOffThread() creating websocket...");

net::io_context ioc;

size_t ckf = handshake.find(ck);
handshake.replace(ckf, ck.length(), key);
tcp::resolver resolver{ ioc };
websocket::stream<tcp::socket> ws{ ioc };
// Log("DEBUG INFO: DisplayPowerOffThread() resolving...");

auto const results = resolver.resolve(host, SERVICE_PORT);
// Log("DEBUG INFO: DisplayPowerOffThread() connecting...");

auto ep = net::connect(ws.next_layer(), results);

host += ':' + std::to_string(ep.port());
if (time(0) - origtim > 10) // this thread should not run too long
{
Log("DisplayPowerOffThread() forced exit.");
goto threadoffend;
}
// Log("DEBUG INFO: DisplayPowerOffThread() setting options...");

// Set a decorator to change the User-Agent of the handshake
ws.set_option(websocket::stream_base::decorator(
Expand All @@ -457,13 +486,32 @@ void DisplayPowerOffThread(SESSIONPARAMETERS* CallingSessionParameters, bool* Ca
std::string(BOOST_BEAST_VERSION_STRING) +
" websocket-client-LGTVsvc");
}));
if (time(0) - origtim > 10) // this thread should not run too long
{
Log("DisplayPowerOffThread() forced exit.");
goto threadoffend;
}

// Log("DEBUG INFO: DisplayPowerOffThread() handshake...");

ws.handshake(host, "/");


if (time(0) - origtim > 10) // this thread should not run too long
{
Log("WARNING! DisplayPowerOffThread() - forced exit");
goto threadoffend;
}

// Log("DEBUG INFO: DisplayPowerOffThread() sending...");

beast::flat_buffer buffer;

ws.write(net::buffer(std::string(handshake)));
ws.read(buffer); // read the response
ws.write(net::buffer(std::string(poweroffmess)));
ws.read(buffer); // read the response
// Log("DEBUG INFO: DisplayPowerOffThread() closing...");

ws.close(websocket::close_code::normal);

logmsg = device;
Expand All @@ -479,6 +527,11 @@ void DisplayPowerOffThread(SESSIONPARAMETERS* CallingSessionParameters, bool* Ca
Log(logmsg);
}
}
else
Log("WARNING! DisplayPowerOffThread() - no pairing key");

threadoffend:

//thread safe section
while (!mMutex.try_lock())
Sleep(MUTEX_WAIT);
Expand Down
3 changes: 2 additions & 1 deletion LGTV Companion Setup/Product.wxs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- When publishing updated version, make sure to generate new GUID for "Product Id", and update "Version" -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"><?define LGTV Companion Service_TargetDir=$(var.LGTV Companion Service.TargetDir)?><?define LGTV Companion UI_TargetDir=$(var.LGTV Companion UI.TargetDir)?>
<Product Id="CC249C3C-30B9-4303-AC84-9A374DC01765" Name="LGTV Companion" Language="1033" Version="1.2.0" Manufacturer="J Persson" UpgradeCode="0BA17E5B-11CE-491D-B1A1-05DD2D9F610A">
<Product Id="33587CA8-2E58-4EFE-B8AB-43FB30FD0D5A" Name="LGTV Companion" Language="1033" Version="1.3.0" Manufacturer="J Persson" UpgradeCode="0BA17E5B-11CE-491D-B1A1-05DD2D9F610A">
<Package Id="*" InstallerVersion="301" Compressed="yes" InstallScope="perMachine" Platform='x64' Description="LGTV Companion installer" InstallPrivileges="elevated" AdminImage="yes"/>
<Media Id="1" Cabinet="LGTVapp.cab" EmbedCab="yes" />

Expand Down
Loading

0 comments on commit 090d7e9

Please sign in to comment.