mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[host] initial service framework implemented
This commit is contained in:
parent
941f0f1c16
commit
3dd205bafc
@ -1,3 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
/*
|
/*
|
||||||
KVMGFX Client - A KVM Client for VGA Passthrough
|
KVMGFX Client - A KVM Client for VGA Passthrough
|
||||||
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
Copyright (C) 2017 Geoffrey McRae <geoff@hostfission.com>
|
||||||
@ -16,6 +17,8 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define KVMGFX_HEADER_MAGIC "[[KVMGFXHeader]]"
|
#define KVMGFX_HEADER_MAGIC "[[KVMGFXHeader]]"
|
||||||
|
|
||||||
typedef enum FrameType
|
typedef enum FrameType
|
||||||
|
15
host/CaptureFactory.h
Normal file
15
host/CaptureFactory.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define W32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "ICapture.h"
|
||||||
|
|
||||||
|
static class CaptureFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static ICapture * GetCaptureDevice()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
14
host/ICapture.h
Normal file
14
host/ICapture.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common/KVMGFXHeader.h>
|
||||||
|
|
||||||
|
__interface ICapture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Initialize();
|
||||||
|
bool DeInitialize();
|
||||||
|
enum FrameType GetFrameType();
|
||||||
|
enum FrameComp GetFrameCompression();
|
||||||
|
size_t GetMaxFrameSize();
|
||||||
|
bool GrabFrame(void * buffer, size_t bufferSize, size_t * outLen);
|
||||||
|
};
|
165
host/Service.cpp
Normal file
165
host/Service.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
#include "service.h"
|
||||||
|
#include "ivshmem.h"
|
||||||
|
|
||||||
|
#include <common\debug.h>
|
||||||
|
#include <common\KVMGFXHeader.h>
|
||||||
|
|
||||||
|
#include "CaptureFactory.h"
|
||||||
|
|
||||||
|
Service * Service::m_instance = NULL;
|
||||||
|
|
||||||
|
Service::Service() :
|
||||||
|
m_initialized(false),
|
||||||
|
m_readyEvent(INVALID_HANDLE_VALUE),
|
||||||
|
m_capture(NULL),
|
||||||
|
m_memory(NULL)
|
||||||
|
{
|
||||||
|
m_ivshmem = IVSHMEM::Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Service::~Service()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::Initialize()
|
||||||
|
{
|
||||||
|
if (m_initialized)
|
||||||
|
DeInitialize();
|
||||||
|
|
||||||
|
if (!m_ivshmem->Initialize())
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("IVSHMEM failed to initalize");
|
||||||
|
DeInitialize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ivshmem->GetSize() < sizeof(KVMGFXHeader))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Shared memory is not large enough for the KVMGFXHeader");
|
||||||
|
DeInitialize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memory = m_ivshmem->GetMemory();
|
||||||
|
if (!m_memory)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to get IVSHMEM memory");
|
||||||
|
DeInitialize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_readyEvent = m_ivshmem->CreateVectorEvent(0);
|
||||||
|
if (m_readyEvent == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to get event for vector 0");
|
||||||
|
DeInitialize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_capture = CaptureFactory::GetCaptureDevice();
|
||||||
|
if (!m_capture || !m_capture->Initialize())
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to initialize capture interface");
|
||||||
|
DeInitialize();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KVMGFXHeader * header = static_cast<KVMGFXHeader*>(m_memory);
|
||||||
|
ZeroMemory(header, sizeof(KVMGFXHeader));
|
||||||
|
memcpy(header->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC));
|
||||||
|
|
||||||
|
header->version = 2;
|
||||||
|
header->guestID = m_ivshmem->GetPeerID();
|
||||||
|
|
||||||
|
m_initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Service::DeInitialize()
|
||||||
|
{
|
||||||
|
if (m_capture)
|
||||||
|
{
|
||||||
|
m_capture->DeInitialize();
|
||||||
|
m_capture = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_readyEvent != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(m_readyEvent);
|
||||||
|
|
||||||
|
m_memory = NULL;
|
||||||
|
m_ivshmem->DeInitialize();
|
||||||
|
m_initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::Process(HANDLE stopEvent)
|
||||||
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
KVMGFXHeader * header = static_cast<KVMGFXHeader *>(m_memory );
|
||||||
|
void * data = static_cast<void *>(header + 1);
|
||||||
|
const size_t available = m_ivshmem->GetSize() - sizeof(KVMGFXHeader);
|
||||||
|
if (m_capture->GetMaxFrameSize() > available)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Frame could exceed buffer size!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the header
|
||||||
|
header->frameType = m_capture->GetFrameType();
|
||||||
|
header->compType = m_capture->GetFrameCompression();
|
||||||
|
|
||||||
|
// capture a frame of data
|
||||||
|
if (!m_capture->GrabFrame(
|
||||||
|
data,
|
||||||
|
m_ivshmem->GetSize() - sizeof(KVMGFXHeader),
|
||||||
|
&header->dataLen))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Capture failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tell the host where the cursor is
|
||||||
|
POINT cursorPos;
|
||||||
|
GetCursorPos(&cursorPos);
|
||||||
|
header->mouseX = cursorPos.x;
|
||||||
|
header->mouseY = cursorPos.y;
|
||||||
|
|
||||||
|
// wait for the host to notify that is it is ready to proceed
|
||||||
|
ResetEvent(m_readyEvent);
|
||||||
|
while(
|
||||||
|
stopEvent == INVALID_HANDLE_VALUE ||
|
||||||
|
(WaitForSingleObject(stopEvent, 0) == WAIT_OBJECT_0)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!m_ivshmem->RingDoorbell(header->hostID, 0))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to ring doorbell");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (WaitForSingleObject(m_readyEvent, 1000))
|
||||||
|
{
|
||||||
|
case WAIT_ABANDONED:
|
||||||
|
DEBUG_ERROR("Wait abandoned");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// if we timed out we just continue to ring until we get an answer or we are stopped
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_FAILED:
|
||||||
|
DEBUG_ERROR("Wait failed");
|
||||||
|
return false;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_ERROR("Unknown error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
35
host/Service.h
Normal file
35
host/Service.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define W32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "ivshmem.h"
|
||||||
|
#include "ICapture.h"
|
||||||
|
|
||||||
|
class Service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Service * Get()
|
||||||
|
{
|
||||||
|
if (!m_instance)
|
||||||
|
m_instance = new Service();
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
void DeInitialize();
|
||||||
|
bool Process(HANDLE stopEvent);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Service * m_instance;
|
||||||
|
|
||||||
|
Service();
|
||||||
|
~Service();
|
||||||
|
|
||||||
|
bool m_initialized;
|
||||||
|
IVSHMEM * m_ivshmem;
|
||||||
|
HANDLE m_readyEvent;
|
||||||
|
ICapture * m_capture;
|
||||||
|
void * m_memory;
|
||||||
|
};
|
@ -216,4 +216,22 @@ HANDLE IVSHMEM::CreateVectorEvent(UINT16 vector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return event;
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IVSHMEM::RingDoorbell(UINT16 peerID, UINT16 door)
|
||||||
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IVSHMEM_RING msg;
|
||||||
|
msg.peerID = peerID;
|
||||||
|
msg.vector = door;
|
||||||
|
|
||||||
|
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RING_DOORBELL, &msg, sizeof(IVSHMEM_RING), NULL, 0, NULL, NULL))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
@ -23,6 +23,7 @@ public:
|
|||||||
UINT16 GetVectors();
|
UINT16 GetVectors();
|
||||||
void * GetMemory();
|
void * GetMemory();
|
||||||
HANDLE CreateVectorEvent(UINT16 vector);
|
HANDLE CreateVectorEvent(UINT16 vector);
|
||||||
|
bool RingDoorbell(UINT16 peerID, UINT16 door);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -154,9 +154,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="ivshmem.cpp" />
|
<ClCompile Include="ivshmem.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
|
<ClCompile Include="Service.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="CaptureFactory.h" />
|
||||||
|
<ClInclude Include="ICapture.h" />
|
||||||
<ClInclude Include="ivshmem.h" />
|
<ClInclude Include="ivshmem.h" />
|
||||||
|
<ClInclude Include="Service.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -21,10 +21,22 @@
|
|||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Service.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="ivshmem.h">
|
<ClInclude Include="ivshmem.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ICapture.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Service.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="CaptureFactory.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -2,7 +2,7 @@
|
|||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <common\debug.h>
|
#include <common\debug.h>
|
||||||
|
|
||||||
#include "ivshmem.h"
|
#include "Service.h"
|
||||||
|
|
||||||
#define SERVICE_NAME "kvm-ivshmem-host"
|
#define SERVICE_NAME "kvm-ivshmem-host"
|
||||||
|
|
||||||
@ -146,19 +146,18 @@ VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
|
|||||||
|
|
||||||
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
||||||
{
|
{
|
||||||
IVSHMEM * ivshmem = IVSHMEM::Get();
|
Service *svc = svc->Get();
|
||||||
if (!ivshmem->Initialize())
|
if (!svc->Initialize())
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize IVSHMEM");
|
DEBUG_ERROR("Failed to initialize service");
|
||||||
return ERROR;
|
return ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (WaitForSingleObject(app.serviceStopEvent, 0) != WAIT_OBJECT_0)
|
while (WaitForSingleObject(app.serviceStopEvent, 0) != WAIT_OBJECT_0)
|
||||||
{
|
if (!svc->Process(app.serviceStopEvent))
|
||||||
Sleep(1000);
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
ivshmem->DeInitialize();
|
svc->DeInitialize();
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user