mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-29 08:33:23 -05:00
142 lines
3.9 KiB
C++
142 lines
3.9 KiB
C++
|
/*
|
||
|
*(C) 2006 Roku LLC
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License Version 2 as published
|
||
|
* by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful, but
|
||
|
* without any warranty; without even the implied warranty of
|
||
|
* merchantability or fitness for a particular purpose. See the GNU General
|
||
|
* Public License for more details.
|
||
|
*
|
||
|
* Please read README.txt in the same directory as this source file for
|
||
|
* further license information.
|
||
|
*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "ServerEvents.h"
|
||
|
|
||
|
ServerEvents::ServerEvents(Observer *obs) :
|
||
|
m_thread(INVALID_HANDLE_VALUE),
|
||
|
m_mailslot(INVALID_HANDLE_VALUE),
|
||
|
m_obs(obs)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ServerEvents::~ServerEvents()
|
||
|
{
|
||
|
ATLASSERT(m_mailslot == INVALID_HANDLE_VALUE);
|
||
|
ATLASSERT(m_thread == INVALID_HANDLE_VALUE);
|
||
|
}
|
||
|
|
||
|
bool ServerEvents::Start()
|
||
|
{
|
||
|
ATLASSERT(m_mailslot == INVALID_HANDLE_VALUE);
|
||
|
ATLASSERT(m_thread == INVALID_HANDLE_VALUE);
|
||
|
ATLASSERT(m_obs != NULL);
|
||
|
|
||
|
m_mailslot = ::CreateMailslot(_T("\\\\.\\mailslot\\FireflyMediaServer--67A72768-4154-417e-BFA0-FA9B50C342DE"), 0, MAILSLOT_WAIT_FOREVER, NULL);
|
||
|
|
||
|
if (m_mailslot != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
//m_thread = ::CreateThread(NULL, 0, &StaticThreadProc, this, 0, &thread_id);
|
||
|
m_thread = (HANDLE)_beginthreadex(NULL, 0, &StaticThreadProc, this, 0, NULL);
|
||
|
if (m_thread == NULL)
|
||
|
{
|
||
|
// Failed
|
||
|
ATLTRACE("beginthreadex failed: %d\n", errno);
|
||
|
::CloseHandle(m_mailslot);
|
||
|
m_mailslot = INVALID_HANDLE_VALUE;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void ServerEvents::Stop()
|
||
|
{
|
||
|
ATLASSERT(m_mailslot != INVALID_HANDLE_VALUE);
|
||
|
ATLASSERT(m_thread != INVALID_HANDLE_VALUE);
|
||
|
|
||
|
// Force the thread to give up. This could be done with a separate event
|
||
|
// and overlapped IO but this is cheap.
|
||
|
CloseHandle(m_mailslot);
|
||
|
m_mailslot = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
// Wait for it to finish.
|
||
|
WaitForSingleObject(m_thread, INFINITE);
|
||
|
CloseHandle(m_thread);
|
||
|
m_thread = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
//DWORD ServerEvents::StaticThreadProc(LPVOID param)
|
||
|
unsigned ServerEvents::StaticThreadProc(void *param)
|
||
|
{
|
||
|
return reinterpret_cast<ServerEvents *>(param)->ThreadProc();
|
||
|
}
|
||
|
|
||
|
DWORD ServerEvents::ThreadProc()
|
||
|
{
|
||
|
const size_t BUFFER_SIZE = 65536;
|
||
|
void *buffer = operator new(BUFFER_SIZE);
|
||
|
|
||
|
bool finished = false;
|
||
|
while (!finished)
|
||
|
{
|
||
|
DWORD bytes_read;
|
||
|
if (ReadFile(m_mailslot, buffer, BUFFER_SIZE, &bytes_read, NULL))
|
||
|
{
|
||
|
TCHAR *b = (TCHAR *)buffer;
|
||
|
b[bytes_read/sizeof(TCHAR)] = 0;
|
||
|
ATLTRACE("%ls\n", b);
|
||
|
|
||
|
OnEvent(buffer, bytes_read);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ATLTRACE("Read failed: error %d\n", GetLastError());
|
||
|
finished = true;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void ServerEvents::OnEvent(const void *buffer, size_t bytes_received)
|
||
|
{
|
||
|
const BYTE *received = reinterpret_cast<const BYTE *>(buffer);
|
||
|
|
||
|
if (bytes_received >= 12)
|
||
|
{
|
||
|
UINT32 packet_size = received[0] | (received[1] << 8) | (received[2] << 16) | (received[3] << 24);
|
||
|
UINT32 id = received[4] | (received[5] << 8) | (received[6] << 16) | (received[7] << 24);
|
||
|
UINT32 intval = received[8] | (received[9] << 8) | (received[10] << 16) | (received[11] << 24);
|
||
|
|
||
|
size_t string_length = bytes_received - 12;
|
||
|
|
||
|
if ((packet_size < bytes_received) && (packet_size >= 12))
|
||
|
string_length = packet_size - 12;
|
||
|
|
||
|
CString str;
|
||
|
if (string_length > 0)
|
||
|
{
|
||
|
#ifdef UNICODE
|
||
|
// It might be less that string_length long after conversion but it shouldn't be more unless
|
||
|
// our codepage is extremely weird.
|
||
|
|
||
|
str.ReleaseBuffer(MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, reinterpret_cast<const char *>(received + 12),
|
||
|
string_length, str.GetBufferSetLength(string_length), string_length));
|
||
|
#else
|
||
|
SafeStringCopy(str.GetBufferSetLength(string_length), received + 12, string_length);
|
||
|
#endif
|
||
|
str.ReleaseBuffer(string_length);
|
||
|
}
|
||
|
|
||
|
m_obs->OnServerEvent(id, intval, str);
|
||
|
}
|
||
|
}
|