* fixed a shit-ton of memory leaks (lots in the ipc log handler, oops)
* added non-pod data support to events (event delete can now call dtors) * improved cleanup of ipc message objects (because of non-pod event data support) * moved the "message received" event up to ipc server and client (passed on from proxies)
This commit is contained in:
parent
21cf3f2478
commit
8bad45e8a2
|
@ -41,30 +41,34 @@ void IpcReader::read()
|
||||||
QMutexLocker locker(&m_Mutex);
|
QMutexLocker locker(&m_Mutex);
|
||||||
std::cout << "ready read" << std::endl;
|
std::cout << "ready read" << std::endl;
|
||||||
|
|
||||||
char codeBuf[1];
|
while (m_Socket->bytesAvailable()) {
|
||||||
readStream(codeBuf, 1);
|
std::cout << "bytes available" << std::endl;
|
||||||
int code = bytesToInt(codeBuf, 1);
|
|
||||||
|
|
||||||
switch (code) {
|
char codeBuf[1];
|
||||||
case kIpcLogLine: {
|
readStream(codeBuf, 1);
|
||||||
std::cout << "reading log line" << std::endl;
|
int code = bytesToInt(codeBuf, 1);
|
||||||
|
|
||||||
char lenBuf[4];
|
switch (code) {
|
||||||
readStream(lenBuf, 4);
|
case kIpcLogLine: {
|
||||||
int len = bytesToInt(lenBuf, 4);
|
std::cout << "reading log line" << std::endl;
|
||||||
|
|
||||||
char* data = new char[len];
|
char lenBuf[4];
|
||||||
readStream(data, len);
|
readStream(lenBuf, 4);
|
||||||
QString line = QString::fromUtf8(data, len);
|
int len = bytesToInt(lenBuf, 4);
|
||||||
delete data;
|
|
||||||
|
|
||||||
readLogLine(line);
|
char* data = new char[len];
|
||||||
break;
|
readStream(data, len);
|
||||||
|
QString line = QString::fromUtf8(data, len);
|
||||||
|
delete data;
|
||||||
|
|
||||||
|
readLogLine(line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
std::cerr << "aborting, message invalid: " << code << std::endl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
std::cerr << "aborting, message invalid: " << code << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "read done" << std::endl;
|
std::cout << "read done" << std::endl;
|
||||||
|
@ -82,13 +86,7 @@ bool IpcReader::readStream(char* buffer, int length)
|
||||||
m_Socket->waitForReadyRead(-1);
|
m_Socket->waitForReadyRead(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// i really don't trust qt not to copy beyond the array length.
|
int got = m_Socket->read(buffer, ask);
|
||||||
// seems like a convoluted an expensive way to copy from the stream :/
|
|
||||||
char* tempBuffer = new char[ask];
|
|
||||||
int got = m_Socket->read(tempBuffer, ask);
|
|
||||||
memcpy(buffer, tempBuffer, got);
|
|
||||||
delete tempBuffer;
|
|
||||||
|
|
||||||
read += got;
|
read += got;
|
||||||
|
|
||||||
std::cout << "> ask=" << ask << " got=" << got
|
std::cout << "> ask=" << ask << " got=" << got
|
||||||
|
|
|
@ -25,16 +25,20 @@ CArch* CArch::s_instance = NULL;
|
||||||
|
|
||||||
CArch::CArch()
|
CArch::CArch()
|
||||||
{
|
{
|
||||||
|
assert(s_instance == NULL);
|
||||||
|
s_instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CArch::~CArch()
|
CArch::~CArch()
|
||||||
{
|
{
|
||||||
|
#if SYSAPI_WIN32
|
||||||
|
CArchMiscWindows::cleanup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArch::init()
|
CArch::init()
|
||||||
{
|
{
|
||||||
// initialization that requires ARCH is done here.
|
|
||||||
ARCH_NETWORK::init();
|
ARCH_NETWORK::init();
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
ARCH_TASKBAR::init();
|
ARCH_TASKBAR::init();
|
||||||
|
@ -45,10 +49,6 @@ CArch::init()
|
||||||
CArch*
|
CArch*
|
||||||
CArch::getInstance()
|
CArch::getInstance()
|
||||||
{
|
{
|
||||||
if (s_instance == NULL) {
|
assert(s_instance != NULL);
|
||||||
s_instance = new CArch();
|
|
||||||
s_instance->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,15 @@ class CArch : public ARCH_CONSOLE,
|
||||||
public ARCH_TASKBAR,
|
public ARCH_TASKBAR,
|
||||||
public ARCH_TIME {
|
public ARCH_TIME {
|
||||||
public:
|
public:
|
||||||
~CArch();
|
CArch();
|
||||||
|
virtual ~CArch();
|
||||||
|
|
||||||
|
//! Call init on other arch classes.
|
||||||
|
/*!
|
||||||
|
Some arch classes depend on others to exist first. When init is called
|
||||||
|
these clases will have ARCH available for use.
|
||||||
|
*/
|
||||||
|
virtual void init();
|
||||||
|
|
||||||
//
|
//
|
||||||
// accessors
|
// accessors
|
||||||
|
@ -111,10 +119,6 @@ public:
|
||||||
|
|
||||||
ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; }
|
ARCH_PLUGIN& plugin() const { return (ARCH_PLUGIN&)m_plugin; }
|
||||||
|
|
||||||
private:
|
|
||||||
CArch();
|
|
||||||
void init();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CArch* s_instance;
|
static CArch* s_instance;
|
||||||
ARCH_PLUGIN m_plugin;
|
ARCH_PLUGIN m_plugin;
|
||||||
|
|
|
@ -50,6 +50,12 @@ HICON CArchMiscWindows::s_largeIcon = NULL;
|
||||||
HICON CArchMiscWindows::s_smallIcon = NULL;
|
HICON CArchMiscWindows::s_smallIcon = NULL;
|
||||||
HINSTANCE CArchMiscWindows::s_instanceWin32 = NULL;
|
HINSTANCE CArchMiscWindows::s_instanceWin32 = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
CArchMiscWindows::cleanup()
|
||||||
|
{
|
||||||
|
delete s_dialogs;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CArchMiscWindows::init()
|
CArchMiscWindows::init()
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,9 @@ public:
|
||||||
//! Initialize
|
//! Initialize
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
|
//! Delete memory
|
||||||
|
static void cleanup();
|
||||||
|
|
||||||
//! Test if windows 95, et al.
|
//! Test if windows 95, et al.
|
||||||
/*!
|
/*!
|
||||||
Returns true iff the platform is win95/98/me.
|
Returns true iff the platform is win95/98/me.
|
||||||
|
|
|
@ -109,6 +109,11 @@ CArchNetworkWinsock::~CArchNetworkWinsock()
|
||||||
s_networkModule = NULL;
|
s_networkModule = NULL;
|
||||||
}
|
}
|
||||||
ARCH->closeMutex(m_mutex);
|
ARCH->closeMutex(m_mutex);
|
||||||
|
|
||||||
|
CEventList::iterator it;
|
||||||
|
for (it = m_unblockEvents.begin(); it != m_unblockEvents.end(); it++) {
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -429,6 +434,7 @@ CArchNetworkWinsock::pollSocket(CPollEntry pe[], int num, double timeout)
|
||||||
ARCH->closeThread(thread);
|
ARCH->closeThread(thread);
|
||||||
if (unblockEvent == NULL) {
|
if (unblockEvent == NULL) {
|
||||||
unblockEvent = new WSAEVENT;
|
unblockEvent = new WSAEVENT;
|
||||||
|
m_unblockEvents.push_back(unblockEvent);
|
||||||
*unblockEvent = WSACreateEvent_winsock();
|
*unblockEvent = WSACreateEvent_winsock();
|
||||||
mt->setNetworkDataForCurrentThread(unblockEvent);
|
mt->setNetworkDataForCurrentThread(unblockEvent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "IArchMultithread.h"
|
#include "IArchMultithread.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#define ARCH_NETWORK CArchNetworkWinsock
|
#define ARCH_NETWORK CArchNetworkWinsock
|
||||||
|
|
||||||
|
@ -98,7 +99,10 @@ private:
|
||||||
void throwNameError(int);
|
void throwNameError(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef std::list<WSAEVENT> CEventList;
|
||||||
|
|
||||||
CArchMutex m_mutex;
|
CArchMutex m_mutex;
|
||||||
|
CEventList m_unblockEvents;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,8 @@ CEvent::CEvent() :
|
||||||
m_type(kUnknown),
|
m_type(kUnknown),
|
||||||
m_target(NULL),
|
m_target(NULL),
|
||||||
m_data(NULL),
|
m_data(NULL),
|
||||||
m_flags(0)
|
m_flags(0),
|
||||||
|
m_dataObject(nullptr)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
@ -35,7 +36,8 @@ CEvent::CEvent(Type type, void* target, void* data, Flags flags) :
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_target(target),
|
m_target(target),
|
||||||
m_data(data),
|
m_data(data),
|
||||||
m_flags(flags)
|
m_flags(flags),
|
||||||
|
m_dataObject(nullptr)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
@ -58,6 +60,12 @@ CEvent::getData() const
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CEventData*
|
||||||
|
CEvent::getDataObject() const
|
||||||
|
{
|
||||||
|
return m_dataObject;
|
||||||
|
}
|
||||||
|
|
||||||
CEvent::Flags
|
CEvent::Flags
|
||||||
CEvent::getFlags() const
|
CEvent::getFlags() const
|
||||||
{
|
{
|
||||||
|
@ -77,7 +85,15 @@ CEvent::deleteData(const CEvent& event)
|
||||||
default:
|
default:
|
||||||
if ((event.getFlags() & kDontFreeData) == 0) {
|
if ((event.getFlags() & kDontFreeData) == 0) {
|
||||||
free(event.getData());
|
free(event.getData());
|
||||||
|
delete event.getDataObject();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CEvent::setDataObject(CEventData* dataObject)
|
||||||
|
{
|
||||||
|
assert(m_dataObject == nullptr);
|
||||||
|
m_dataObject = dataObject;
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
#include "stdmap.h"
|
#include "stdmap.h"
|
||||||
|
|
||||||
|
class CEventData {
|
||||||
|
public:
|
||||||
|
CEventData() { }
|
||||||
|
virtual ~CEventData() { }
|
||||||
|
};
|
||||||
|
|
||||||
//! Event
|
//! Event
|
||||||
/*!
|
/*!
|
||||||
A \c CEvent holds an event type and a pointer to event data.
|
A \c CEvent holds an event type and a pointer to event data.
|
||||||
|
@ -45,13 +51,15 @@ public:
|
||||||
|
|
||||||
CEvent();
|
CEvent();
|
||||||
|
|
||||||
//! Create \c CEvent with data
|
//! Create \c CEvent with data (POD)
|
||||||
/*!
|
/*!
|
||||||
The \p type must have been registered using \c registerType().
|
The \p type must have been registered using \c registerType().
|
||||||
The \p data must be POD (plain old data) allocated by malloc(),
|
The \p data must be POD (plain old data) allocated by malloc(),
|
||||||
which means it cannot have a constructor, destructor or be
|
which means it cannot have a constructor, destructor or be
|
||||||
composed of any types that do. \p target is the intended
|
composed of any types that do. For non-POD (normal C++ objects
|
||||||
recipient of the event. \p flags is any combination of \c Flags.
|
use \c setDataObject().
|
||||||
|
\p target is the intended recipient of the event.
|
||||||
|
\p flags is any combination of \c Flags.
|
||||||
*/
|
*/
|
||||||
CEvent(Type type, void* target = NULL, void* data = NULL,
|
CEvent(Type type, void* target = NULL, void* data = NULL,
|
||||||
Flags flags = kNone);
|
Flags flags = kNone);
|
||||||
|
@ -65,6 +73,13 @@ public:
|
||||||
*/
|
*/
|
||||||
static void deleteData(const CEvent&);
|
static void deleteData(const CEvent&);
|
||||||
|
|
||||||
|
//! Set data (non-POD)
|
||||||
|
/*!
|
||||||
|
Set non-POD (non plain old data), where delete is called when the event
|
||||||
|
is deleted, and the destructor is called.
|
||||||
|
*/
|
||||||
|
void setDataObject(CEventData* dataObject);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
@ -81,12 +96,20 @@ public:
|
||||||
*/
|
*/
|
||||||
void* getTarget() const;
|
void* getTarget() const;
|
||||||
|
|
||||||
//! Get the event data
|
//! Get the event data (POD).
|
||||||
/*!
|
/*!
|
||||||
Returns the event data.
|
Returns the event data (POD).
|
||||||
*/
|
*/
|
||||||
void* getData() const;
|
void* getData() const;
|
||||||
|
|
||||||
|
//! Get the event data (non-POD)
|
||||||
|
/*!
|
||||||
|
Returns the event data (non-POD). The difference between this and
|
||||||
|
\c getData() is that when delete is called on this data, so non-POD
|
||||||
|
(non plain old data) dtor is called.
|
||||||
|
*/
|
||||||
|
CEventData* getDataObject() const;
|
||||||
|
|
||||||
//! Get event flags
|
//! Get event flags
|
||||||
/*!
|
/*!
|
||||||
Returns the event flags.
|
Returns the event flags.
|
||||||
|
@ -100,6 +123,7 @@ private:
|
||||||
void* m_target;
|
void* m_target;
|
||||||
void* m_data;
|
void* m_data;
|
||||||
Flags m_flags;
|
Flags m_flags;
|
||||||
|
CEventData* m_dataObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
*
|
*
|
||||||
* This package is distributed in the hope that it will be useful,
|
* This package is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
|
@ -28,79 +28,81 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
// names of priorities
|
// names of priorities
|
||||||
static const char* g_priority[] = {
|
static const char* g_priority[] = {
|
||||||
"FATAL",
|
"FATAL",
|
||||||
"ERROR",
|
"ERROR",
|
||||||
"WARNING",
|
"WARNING",
|
||||||
"NOTE",
|
"NOTE",
|
||||||
"INFO",
|
"INFO",
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
"DEBUG1",
|
"DEBUG1",
|
||||||
"DEBUG2",
|
"DEBUG2",
|
||||||
"DEBUG3",
|
"DEBUG3",
|
||||||
"DEBUG4",
|
"DEBUG4",
|
||||||
"DEBUG5"
|
"DEBUG5"
|
||||||
};
|
};
|
||||||
|
|
||||||
// number of priorities
|
// number of priorities
|
||||||
static const int g_numPriority = (int)(sizeof(g_priority) / sizeof(g_priority[0]));
|
static const int g_numPriority = (int)(sizeof(g_priority) / sizeof(g_priority[0]));
|
||||||
|
|
||||||
// the default priority
|
// the default priority
|
||||||
#if defined(_DEBUG) || defined(DEBUG)
|
#if defined(_DEBUG) || defined(DEBUG)
|
||||||
static const int g_defaultMaxPriority = kDEBUG;
|
static const int g_defaultMaxPriority = kDEBUG;
|
||||||
#else
|
#else
|
||||||
static const int g_defaultMaxPriority = kINFO;
|
static const int g_defaultMaxPriority = kINFO;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// length of longest string in g_priority
|
// length of longest string in g_priority
|
||||||
static const int g_maxPriorityLength = 7;
|
static const int g_maxPriorityLength = 7;
|
||||||
|
|
||||||
// length of suffix string (": ")
|
// length of suffix string (": ")
|
||||||
static const int g_prioritySuffixLength = 2;
|
static const int g_prioritySuffixLength = 2;
|
||||||
|
|
||||||
// amount of padded required to fill in the priority prefix
|
// amount of padded required to fill in the priority prefix
|
||||||
static const int g_priorityPad = g_maxPriorityLength +
|
static const int g_priorityPad = g_maxPriorityLength +
|
||||||
g_prioritySuffixLength;
|
g_prioritySuffixLength;
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CLog
|
// CLog
|
||||||
//
|
//
|
||||||
|
|
||||||
CLog* CLog::s_log = NULL;
|
CLog* CLog::s_log = NULL;
|
||||||
|
|
||||||
CLog::CLog()
|
CLog::CLog()
|
||||||
{
|
{
|
||||||
// create mutex for multithread safe operation
|
assert(s_log == NULL);
|
||||||
m_mutex = ARCH->newMutex();
|
|
||||||
|
|
||||||
// other initalization
|
// create mutex for multithread safe operation
|
||||||
m_maxPriority = g_defaultMaxPriority;
|
m_mutex = ARCH->newMutex();
|
||||||
m_maxNewlineLength = 0;
|
|
||||||
insert(new CConsoleLogOutputter);
|
// other initalization
|
||||||
|
m_maxPriority = g_defaultMaxPriority;
|
||||||
|
m_maxNewlineLength = 0;
|
||||||
|
insert(new CConsoleLogOutputter);
|
||||||
|
|
||||||
|
s_log = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLog::~CLog()
|
CLog::~CLog()
|
||||||
{
|
{
|
||||||
// clean up
|
// clean up
|
||||||
for (COutputterList::iterator index = m_outputters.begin();
|
for (COutputterList::iterator index = m_outputters.begin();
|
||||||
index != m_outputters.end(); ++index) {
|
index != m_outputters.end(); ++index) {
|
||||||
delete *index;
|
delete *index;
|
||||||
}
|
}
|
||||||
for (COutputterList::iterator index = m_alwaysOutputters.begin();
|
for (COutputterList::iterator index = m_alwaysOutputters.begin();
|
||||||
index != m_alwaysOutputters.end(); ++index) {
|
index != m_alwaysOutputters.end(); ++index) {
|
||||||
delete *index;
|
delete *index;
|
||||||
}
|
}
|
||||||
ARCH->closeMutex(m_mutex);
|
ARCH->closeMutex(m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLog*
|
CLog*
|
||||||
CLog::getInstance()
|
CLog::getInstance()
|
||||||
{
|
{
|
||||||
if (s_log == NULL)
|
assert(s_log != NULL);
|
||||||
s_log = new CLog();
|
return s_log;
|
||||||
|
|
||||||
return s_log;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
|
@ -118,180 +120,180 @@ CLog::getFilterName(int level) const
|
||||||
void
|
void
|
||||||
CLog::print(const char* file, int line, const char* fmt, ...)
|
CLog::print(const char* file, int line, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
// check if fmt begins with a priority argument
|
// check if fmt begins with a priority argument
|
||||||
ELevel priority = kINFO;
|
ELevel priority = kINFO;
|
||||||
if ((strlen(fmt) > 2) && (fmt[0] == '%' && fmt[1] == 'z')) {
|
if ((strlen(fmt) > 2) && (fmt[0] == '%' && fmt[1] == 'z')) {
|
||||||
|
|
||||||
// 060 in octal is 0 (48 in decimal), so subtracting this converts ascii
|
// 060 in octal is 0 (48 in decimal), so subtracting this converts ascii
|
||||||
// number it a true number. we could use atoi instead, but this is how
|
// number it a true number. we could use atoi instead, but this is how
|
||||||
// it was done originally.
|
// it was done originally.
|
||||||
priority = (ELevel)(fmt[2] - '\060');
|
priority = (ELevel)(fmt[2] - '\060');
|
||||||
|
|
||||||
// move the pointer on past the debug priority char
|
// move the pointer on past the debug priority char
|
||||||
fmt += 3;
|
fmt += 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// done if below priority threshold
|
// done if below priority threshold
|
||||||
if (priority > getFilter()) {
|
if (priority > getFilter()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute prefix padding length
|
// compute prefix padding length
|
||||||
char stack[1024];
|
char stack[1024];
|
||||||
|
|
||||||
// compute suffix padding length
|
// compute suffix padding length
|
||||||
int sPad = m_maxNewlineLength;
|
int sPad = m_maxNewlineLength;
|
||||||
|
|
||||||
// print to buffer, leaving space for a newline at the end and prefix
|
// print to buffer, leaving space for a newline at the end and prefix
|
||||||
// at the beginning.
|
// at the beginning.
|
||||||
char* buffer = stack;
|
char* buffer = stack;
|
||||||
int len = (int)(sizeof(stack) / sizeof(stack[0]));
|
int len = (int)(sizeof(stack) / sizeof(stack[0]));
|
||||||
while (true) {
|
while (true) {
|
||||||
// try printing into the buffer
|
// try printing into the buffer
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
int n = ARCH->vsnprintf(buffer, len - sPad, fmt, args);
|
int n = ARCH->vsnprintf(buffer, len - sPad, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
// if the buffer wasn't big enough then make it bigger and try again
|
// if the buffer wasn't big enough then make it bigger and try again
|
||||||
if (n < 0 || n > (int)len) {
|
if (n < 0 || n > (int)len) {
|
||||||
if (buffer != stack) {
|
if (buffer != stack) {
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
len *= 2;
|
len *= 2;
|
||||||
buffer = new char[len];
|
buffer = new char[len];
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the buffer was big enough then continue
|
// if the buffer was big enough then continue
|
||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the prefix to the buffer. leave space for priority label.
|
// print the prefix to the buffer. leave space for priority label.
|
||||||
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
// do not prefix time and file for kPRINT (CLOG_PRINT)
|
||||||
if (priority != kPRINT) {
|
if (priority != kPRINT) {
|
||||||
|
|
||||||
char message[2048];
|
char message[2048];
|
||||||
|
|
||||||
#if defined(_DEBUG) || defined(DEBUG)
|
#if defined(_DEBUG) || defined(DEBUG)
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
char tmp[220];
|
char tmp[220];
|
||||||
time_t t;
|
time_t t;
|
||||||
time(&t);
|
time(&t);
|
||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
sprintf(tmp, "%04i-%02i-%02iT%02i:%02i:%02i", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
sprintf(tmp, "%04i-%02i-%02iT%02i:%02i:%02i", tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
sprintf(message, "%s %s: %s\n\t%s,%d", tmp, g_priority[priority], buffer, file, line);
|
sprintf(message, "%s %s: %s\n\t%s,%d", tmp, g_priority[priority], buffer, file, line);
|
||||||
#else
|
#else
|
||||||
sprintf(message, "%s: %s", g_priority[priority], buffer);
|
sprintf(message, "%s: %s", g_priority[priority], buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
output(priority, message);
|
output(priority, message);
|
||||||
} else {
|
} else {
|
||||||
output(priority, buffer);
|
output(priority, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
if (buffer != stack) {
|
if (buffer != stack) {
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLog::insert(ILogOutputter* outputter, bool alwaysAtHead)
|
CLog::insert(ILogOutputter* outputter, bool alwaysAtHead)
|
||||||
{
|
{
|
||||||
assert(outputter != NULL);
|
assert(outputter != NULL);
|
||||||
|
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
if (alwaysAtHead) {
|
if (alwaysAtHead) {
|
||||||
m_alwaysOutputters.push_front(outputter);
|
m_alwaysOutputters.push_front(outputter);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_outputters.push_front(outputter);
|
m_outputters.push_front(outputter);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputter->open(kAppVersion);
|
outputter->open(kAppVersion);
|
||||||
|
|
||||||
// Issue 41
|
// Issue 41
|
||||||
// don't show log unless user requests it, as some users find this
|
// don't show log unless user requests it, as some users find this
|
||||||
// feature irritating (i.e. when they lose network connectivity).
|
// feature irritating (i.e. when they lose network connectivity).
|
||||||
// in windows the log window can be displayed by selecting "show log"
|
// in windows the log window can be displayed by selecting "show log"
|
||||||
// from the synergy system tray icon.
|
// from the synergy system tray icon.
|
||||||
// if this causes problems for other architectures, then a different
|
// if this causes problems for other architectures, then a different
|
||||||
// work around should be attempted.
|
// work around should be attempted.
|
||||||
//outputter->show(false);
|
//outputter->show(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLog::remove(ILogOutputter* outputter)
|
CLog::remove(ILogOutputter* outputter)
|
||||||
{
|
{
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
m_outputters.remove(outputter);
|
m_outputters.remove(outputter);
|
||||||
m_alwaysOutputters.remove(outputter);
|
m_alwaysOutputters.remove(outputter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLog::pop_front(bool alwaysAtHead)
|
CLog::pop_front(bool alwaysAtHead)
|
||||||
{
|
{
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
COutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
|
COutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters;
|
||||||
if (!list->empty()) {
|
if (!list->empty()) {
|
||||||
delete list->front();
|
delete list->front();
|
||||||
list->pop_front();
|
list->pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CLog::setFilter(const char* maxPriority)
|
CLog::setFilter(const char* maxPriority)
|
||||||
{
|
{
|
||||||
if (maxPriority != NULL) {
|
if (maxPriority != NULL) {
|
||||||
for (int i = 0; i < g_numPriority; ++i) {
|
for (int i = 0; i < g_numPriority; ++i) {
|
||||||
if (strcmp(maxPriority, g_priority[i]) == 0) {
|
if (strcmp(maxPriority, g_priority[i]) == 0) {
|
||||||
setFilter(i);
|
setFilter(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLog::setFilter(int maxPriority)
|
CLog::setFilter(int maxPriority)
|
||||||
{
|
{
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
m_maxPriority = maxPriority;
|
m_maxPriority = maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CLog::getFilter() const
|
CLog::getFilter() const
|
||||||
{
|
{
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
return m_maxPriority;
|
return m_maxPriority;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CLog::output(ELevel priority, char* msg)
|
CLog::output(ELevel priority, char* msg)
|
||||||
{
|
{
|
||||||
assert(priority >= -1 && priority < g_numPriority);
|
assert(priority >= -1 && priority < g_numPriority);
|
||||||
assert(msg != NULL);
|
assert(msg != NULL);
|
||||||
if (!msg) return;
|
if (!msg) return;
|
||||||
|
|
||||||
CArchMutexLock lock(m_mutex);
|
CArchMutexLock lock(m_mutex);
|
||||||
|
|
||||||
COutputterList::const_iterator i;
|
COutputterList::const_iterator i;
|
||||||
|
|
||||||
for (i = m_alwaysOutputters.begin(); i != m_alwaysOutputters.end(); ++i) {
|
for (i = m_alwaysOutputters.begin(); i != m_alwaysOutputters.end(); ++i) {
|
||||||
|
|
||||||
// write to outputter
|
// write to outputter
|
||||||
(*i)->write(priority, msg);
|
(*i)->write(priority, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = m_outputters.begin(); i != m_outputters.end(); ++i) {
|
for (i = m_outputters.begin(); i != m_outputters.end(); ++i) {
|
||||||
|
|
||||||
// write to outputter and break out of loop if it returns false
|
// write to outputter and break out of loop if it returns false
|
||||||
if (!(*i)->write(priority, msg)) {
|
if (!(*i)->write(priority, msg)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ LOGC() provide convenient access.
|
||||||
*/
|
*/
|
||||||
class CLog {
|
class CLog {
|
||||||
public:
|
public:
|
||||||
|
CLog();
|
||||||
~CLog();
|
~CLog();
|
||||||
|
|
||||||
//! @name manipulators
|
//! @name manipulators
|
||||||
|
@ -86,6 +87,8 @@ public:
|
||||||
then it simply returns true.
|
then it simply returns true.
|
||||||
*/
|
*/
|
||||||
bool setFilter(const char* name);
|
bool setFilter(const char* name);
|
||||||
|
|
||||||
|
//! Set the minimum priority filter (by ordinal).
|
||||||
void setFilter(int);
|
void setFilter(int);
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
@ -119,7 +122,6 @@ public:
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CLog();
|
|
||||||
void output(ELevel priority, char* msg);
|
void output(ELevel priority, char* msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
#include "CStopwatch.h"
|
#include "CStopwatch.h"
|
||||||
#include "CArch.h"
|
#include "CArch.h"
|
||||||
|
|
||||||
class CEventQueueTimer { };
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// CSimpleEventQueueBuffer
|
// CSimpleEventQueueBuffer
|
||||||
//
|
//
|
||||||
|
|
|
@ -49,4 +49,11 @@ private:
|
||||||
CEventDeque m_queue;
|
CEventDeque m_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CEventQueueTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CEventQueueTimer() { }
|
||||||
|
virtual ~CEventQueueTimer() { }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
|
|
||||||
CEvent::Type CIpcClient::s_connectedEvent = CEvent::kUnknown;
|
CEvent::Type CIpcClient::s_connectedEvent = CEvent::kUnknown;
|
||||||
|
CEvent::Type CIpcClient::s_messageReceivedEvent = CEvent::kUnknown;
|
||||||
|
|
||||||
CIpcClient::CIpcClient() :
|
CIpcClient::CIpcClient() :
|
||||||
m_serverAddress(CNetworkAddress(IPC_HOST, IPC_PORT)),
|
m_serverAddress(CNetworkAddress(IPC_HOST, IPC_PORT)),
|
||||||
|
@ -37,6 +38,8 @@ m_server(nullptr)
|
||||||
|
|
||||||
CIpcClient::~CIpcClient()
|
CIpcClient::~CIpcClient()
|
||||||
{
|
{
|
||||||
|
EVENTQUEUE->removeHandler(m_socket.getConnectedEvent(), m_socket.getEventTarget());
|
||||||
|
EVENTQUEUE->removeHandler(CIpcServerProxy::getMessageReceivedEvent(), m_server);
|
||||||
delete m_server;
|
delete m_server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +48,25 @@ CIpcClient::connect()
|
||||||
{
|
{
|
||||||
m_socket.connect(m_serverAddress);
|
m_socket.connect(m_serverAddress);
|
||||||
m_server = new CIpcServerProxy(m_socket);
|
m_server = new CIpcServerProxy(m_socket);
|
||||||
|
|
||||||
|
EVENTQUEUE->adoptHandler(
|
||||||
|
CIpcServerProxy::getMessageReceivedEvent(), m_server,
|
||||||
|
new TMethodEventJob<CIpcClient>(
|
||||||
|
this, &CIpcClient::handleMessageReceived));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIpcClient::disconnect()
|
||||||
|
{
|
||||||
|
m_server->disconnect();
|
||||||
|
delete m_server;
|
||||||
|
m_server = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcClient::send(const CIpcMessage& message)
|
CIpcClient::send(const CIpcMessage& message)
|
||||||
{
|
{
|
||||||
assert(m_server != NULL);
|
assert(m_server != nullptr);
|
||||||
m_server->send(message);
|
m_server->send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,13 +77,27 @@ CIpcClient::getConnectedEvent()
|
||||||
s_connectedEvent, "CIpcClient::connected");
|
s_connectedEvent, "CIpcClient::connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CEvent::Type
|
||||||
|
CIpcClient::getMessageReceivedEvent()
|
||||||
|
{
|
||||||
|
return EVENTQUEUE->registerTypeOnce(
|
||||||
|
s_messageReceivedEvent, "CIpcClient::messageReceived");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcClient::handleConnected(const CEvent&, void*)
|
CIpcClient::handleConnected(const CEvent&, void*)
|
||||||
{
|
{
|
||||||
EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this, m_server, CEvent::kDontFreeData));
|
EVENTQUEUE->addEvent(CEvent(
|
||||||
|
getConnectedEvent(), this, m_server, CEvent::kDontFreeData));
|
||||||
|
|
||||||
CIpcMessage message;
|
CIpcHelloMessage message(kIpcClientNode);
|
||||||
message.m_type = kIpcHello;
|
|
||||||
message.m_data = new UInt8(kIpcClientNode);
|
|
||||||
send(message);
|
send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIpcClient::handleMessageReceived(const CEvent& e, void*)
|
||||||
|
{
|
||||||
|
CEvent event(getMessageReceivedEvent(), this);
|
||||||
|
event.setDataObject(e.getDataObject());
|
||||||
|
EVENTQUEUE->addEvent(event);
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ public:
|
||||||
//! Connects to the IPC server at localhost.
|
//! Connects to the IPC server at localhost.
|
||||||
void connect();
|
void connect();
|
||||||
|
|
||||||
|
//! Disconnects from the IPC server.
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
//! Sends a message to the server.
|
//! Sends a message to the server.
|
||||||
void send(const CIpcMessage& message);
|
void send(const CIpcMessage& message);
|
||||||
|
|
||||||
|
@ -47,11 +50,13 @@ public:
|
||||||
|
|
||||||
//! Raised when the socket is connected.
|
//! Raised when the socket is connected.
|
||||||
static CEvent::Type getConnectedEvent();
|
static CEvent::Type getConnectedEvent();
|
||||||
|
static CEvent::Type getMessageReceivedEvent();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleConnected(const CEvent&, void*);
|
void handleConnected(const CEvent&, void*);
|
||||||
|
void handleMessageReceived(const CEvent&, void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CNetworkAddress m_serverAddress;
|
CNetworkAddress m_serverAddress;
|
||||||
|
@ -59,4 +64,5 @@ private:
|
||||||
CIpcServerProxy* m_server;
|
CIpcServerProxy* m_server;
|
||||||
|
|
||||||
static CEvent::Type s_connectedEvent;
|
static CEvent::Type s_connectedEvent;
|
||||||
|
static CEvent::Type s_messageReceivedEvent;
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,36 +99,36 @@ CIpcClientProxy::handleData(const CEvent&, void*)
|
||||||
// don't allow the dtor to destroy the stream while we're using it.
|
// don't allow the dtor to destroy the stream while we're using it.
|
||||||
CArchMutexLock lock(m_readMutex);
|
CArchMutexLock lock(m_readMutex);
|
||||||
|
|
||||||
UInt8 code[1];
|
UInt8 codeBuf[1];
|
||||||
UInt32 n = m_stream.read(code, 1);
|
UInt32 n = m_stream.read(codeBuf, 1);
|
||||||
|
int code = codeBuf[0];
|
||||||
|
|
||||||
while (n != 0) {
|
while (n != 0) {
|
||||||
UInt8 type = code[0];
|
|
||||||
|
|
||||||
CIpcMessage* m = new CIpcMessage();
|
LOG((CLOG_DEBUG "ipc client proxy read: %d", code));
|
||||||
m->m_type = type;
|
|
||||||
m->m_source = this;
|
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "ipc client proxy read: %d", code[0]));
|
CIpcMessage* m = nullptr;
|
||||||
|
switch (code) {
|
||||||
switch (type) {
|
|
||||||
case kIpcHello:
|
case kIpcHello:
|
||||||
parseHello();
|
m = parseHello();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kIpcCommand:
|
case kIpcCommand:
|
||||||
m->m_data = parseCommand();
|
m = parseCommand();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
delete m;
|
|
||||||
disconnect();
|
disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// event deletes data.
|
// don't delete with this event; the data is passed to a new event.
|
||||||
EVENTQUEUE->addEvent(CEvent(getMessageReceivedEvent(), this, m));
|
CEvent e(getMessageReceivedEvent(), this, NULL, CEvent::kDontFreeData);
|
||||||
|
e.setDataObject(m);
|
||||||
|
EVENTQUEUE->addEvent(e);
|
||||||
|
|
||||||
n = m_stream.read(code, 1);
|
n = m_stream.read(codeBuf, 1);
|
||||||
|
code = codeBuf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "finished ipc client proxy handle data"));
|
LOG((CLOG_DEBUG "finished ipc client proxy handle data"));
|
||||||
|
@ -142,20 +142,19 @@ CIpcClientProxy::send(const CIpcMessage& message)
|
||||||
// also, don't allow the dtor to destroy the stream while we're using it.
|
// also, don't allow the dtor to destroy the stream while we're using it.
|
||||||
CArchMutexLock lock(m_writeMutex);
|
CArchMutexLock lock(m_writeMutex);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "ipc client proxy write: %d", message.m_type));
|
LOG((CLOG_DEBUG "ipc client proxy write: %d", message.type()));
|
||||||
|
|
||||||
UInt8 code[1];
|
CProtocolUtil::writef(&m_stream, "%1i", message.type());
|
||||||
code[0] = message.m_type;
|
|
||||||
m_stream.write(code, 1);
|
|
||||||
|
|
||||||
switch (message.m_type) {
|
switch (message.type()) {
|
||||||
case kIpcLogLine: {
|
case kIpcLogLine: {
|
||||||
CString* s = (CString*)message.m_data;
|
const CIpcLogLineMessage& llm = static_cast<const CIpcLogLineMessage&>(message);
|
||||||
const char* data = s->c_str();
|
|
||||||
|
|
||||||
|
CString logLine = llm.logLine();
|
||||||
|
const char* data = logLine.c_str();
|
||||||
int len = strlen(data);
|
int len = strlen(data);
|
||||||
CProtocolUtil::writef(&m_stream, "%4i", len);
|
|
||||||
|
|
||||||
|
CProtocolUtil::writef(&m_stream, "%4i", len);
|
||||||
m_stream.write(data, len);
|
m_stream.write(data, len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -165,30 +164,35 @@ CIpcClientProxy::send(const CIpcMessage& message)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG((CLOG_ERR "message not supported: %d", message.m_type));
|
LOG((CLOG_ERR "message not supported: %d", message.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
CIpcHelloMessage*
|
||||||
CIpcClientProxy::parseHello()
|
CIpcClientProxy::parseHello()
|
||||||
{
|
{
|
||||||
UInt8 buffer[1];
|
UInt8 buffer[1];
|
||||||
m_stream.read(buffer, 1);
|
m_stream.read(buffer, 1);
|
||||||
m_clientType = static_cast<EIpcClientType>(buffer[0]);
|
m_clientType = static_cast<EIpcClientType>(buffer[0]);
|
||||||
|
|
||||||
|
// must be deleted by event handler.
|
||||||
|
return new CIpcHelloMessage(m_clientType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
CIpcCommandMessage*
|
||||||
CIpcClientProxy::parseCommand()
|
CIpcClientProxy::parseCommand()
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
CProtocolUtil::readf(&m_stream, "%2i", &len);
|
CProtocolUtil::readf(&m_stream, "%2i", &len);
|
||||||
|
|
||||||
UInt8* buffer = new UInt8[len];
|
char* buffer = new char[len];
|
||||||
m_stream.read(buffer, len);
|
m_stream.read(buffer, len);
|
||||||
|
CString s(buffer, len);
|
||||||
|
delete buffer;
|
||||||
|
|
||||||
// delete by event cleanup.
|
// must be deleted by event handler.
|
||||||
return new CString((const char*)buffer, len);
|
return new CIpcCommandMessage(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -23,12 +23,17 @@
|
||||||
|
|
||||||
namespace synergy { class IStream; }
|
namespace synergy { class IStream; }
|
||||||
class CIpcMessage;
|
class CIpcMessage;
|
||||||
|
class CIpcCommandMessage;
|
||||||
|
class CIpcHelloMessage;
|
||||||
|
|
||||||
class CIpcClientProxy {
|
class CIpcClientProxy {
|
||||||
|
friend class CIpcServer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CIpcClientProxy(synergy::IStream& stream);
|
CIpcClientProxy(synergy::IStream& stream);
|
||||||
virtual ~CIpcClientProxy();
|
virtual ~CIpcClientProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
//! Send a message to the client.
|
//! Send a message to the client.
|
||||||
void send(const CIpcMessage& message);
|
void send(const CIpcMessage& message);
|
||||||
|
|
||||||
|
@ -38,20 +43,17 @@ public:
|
||||||
//! Raised when the client disconnects from the server.
|
//! Raised when the client disconnects from the server.
|
||||||
static CEvent::Type getDisconnectedEvent();
|
static CEvent::Type getDisconnectedEvent();
|
||||||
|
|
||||||
private:
|
|
||||||
void handleData(const CEvent&, void*);
|
void handleData(const CEvent&, void*);
|
||||||
void handleDisconnect(const CEvent&, void*);
|
void handleDisconnect(const CEvent&, void*);
|
||||||
void handleWriteError(const CEvent&, void*);
|
void handleWriteError(const CEvent&, void*);
|
||||||
void parseHello();
|
CIpcHelloMessage* parseHello();
|
||||||
void* parseCommand();
|
CIpcCommandMessage* parseCommand();
|
||||||
void disconnect();
|
void disconnect();
|
||||||
|
|
||||||
public:
|
private:
|
||||||
synergy::IStream& m_stream;
|
synergy::IStream& m_stream;
|
||||||
EIpcClientType m_clientType;
|
EIpcClientType m_clientType;
|
||||||
bool m_disconnecting;
|
bool m_disconnecting;
|
||||||
|
|
||||||
private:
|
|
||||||
CArchMutex m_readMutex;
|
CArchMutex m_readMutex;
|
||||||
CArchMutex m_writeMutex;
|
CArchMutex m_writeMutex;
|
||||||
|
|
||||||
|
|
|
@ -109,12 +109,21 @@ CIpcLogOutputter::bufferThread(void*)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
while (m_running) {
|
while (m_running) {
|
||||||
|
|
||||||
if (m_ipcServer.hasClients(kIpcClientGui)) {
|
if (m_ipcServer.hasClients(kIpcClientGui)) {
|
||||||
while (!m_buffer.empty()) {
|
|
||||||
|
// buffer is sent in chunks, so keep sending until it's
|
||||||
|
// empty (or the program has stopped in the meantime).
|
||||||
|
while (m_running && !m_buffer.empty()) {
|
||||||
sendBuffer();
|
sendBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// program may be stopping while we were in the send loop.
|
||||||
|
if (!m_running) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_bufferWaiting = true;
|
m_bufferWaiting = true;
|
||||||
ARCH->waitCondVar(m_notifyCond, m_notifyMutex, -1);
|
ARCH->waitCondVar(m_notifyCond, m_notifyMutex, -1);
|
||||||
m_bufferWaiting = false;
|
m_bufferWaiting = false;
|
||||||
|
@ -138,7 +147,7 @@ CIpcLogOutputter::notifyBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
CString
|
CString
|
||||||
CIpcLogOutputter::emptyBuffer(size_t count)
|
CIpcLogOutputter::getChunk(size_t count)
|
||||||
{
|
{
|
||||||
CArchMutexLock lock(m_bufferMutex);
|
CArchMutexLock lock(m_bufferMutex);
|
||||||
|
|
||||||
|
@ -155,13 +164,10 @@ CIpcLogOutputter::emptyBuffer(size_t count)
|
||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcLogOutputter::sendBuffer()
|
CIpcLogOutputter::sendBuffer()
|
||||||
{
|
{
|
||||||
CIpcMessage message;
|
CIpcLogLineMessage message(getChunk(MAX_SEND));
|
||||||
message.m_type = kIpcLogLine;
|
|
||||||
message.m_data = new CString(emptyBuffer(MAX_SEND));
|
|
||||||
|
|
||||||
m_sending = true;
|
m_sending = true;
|
||||||
m_ipcServer.send(message, kIpcClientGui);
|
m_ipcServer.send(message, kIpcClientGui);
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void bufferThread(void*);
|
void bufferThread(void*);
|
||||||
CString emptyBuffer(size_t count);
|
CString getChunk(size_t count);
|
||||||
void sendBuffer();
|
void sendBuffer();
|
||||||
void appendBuffer(const CString& text);
|
void appendBuffer(const CString& text);
|
||||||
|
|
||||||
|
|
|
@ -16,17 +16,52 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
|
#include "Ipc.h"
|
||||||
|
|
||||||
CIpcMessage::CIpcMessage() :
|
CIpcMessage::CIpcMessage(UInt8 type) :
|
||||||
m_type(0),
|
m_type(type)
|
||||||
m_data(nullptr),
|
|
||||||
m_source(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcMessage::~CIpcMessage()
|
CIpcMessage::~CIpcMessage()
|
||||||
{
|
{
|
||||||
if (m_data != nullptr) {
|
}
|
||||||
delete m_data;
|
|
||||||
}
|
CIpcHelloMessage::CIpcHelloMessage(EIpcClientType clientType) :
|
||||||
|
CIpcMessage(kIpcHello),
|
||||||
|
m_clientType(clientType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcHelloMessage::~CIpcHelloMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcShutdownMessage::CIpcShutdownMessage() :
|
||||||
|
CIpcMessage(kIpcShutdown)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcShutdownMessage::~CIpcShutdownMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcLogLineMessage::CIpcLogLineMessage(const CString& logLine) :
|
||||||
|
CIpcMessage(kIpcLogLine),
|
||||||
|
m_logLine(logLine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcLogLineMessage::~CIpcLogLineMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcCommandMessage::CIpcCommandMessage(const CString& command) :
|
||||||
|
CIpcMessage(kIpcCommand),
|
||||||
|
m_command(command)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CIpcCommandMessage::~CIpcCommandMessage()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,63 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BasicTypes.h"
|
#include "BasicTypes.h"
|
||||||
|
#include "CString.h"
|
||||||
|
#include "Ipc.h"
|
||||||
|
#include "CEvent.h"
|
||||||
|
|
||||||
class CIpcMessage {
|
class CIpcMessage : public CEventData {
|
||||||
public:
|
public:
|
||||||
CIpcMessage();
|
|
||||||
virtual ~CIpcMessage();
|
virtual ~CIpcMessage();
|
||||||
|
|
||||||
|
//! Gets the message type ID.
|
||||||
|
UInt8 type() const { return m_type; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CIpcMessage(UInt8 type);
|
||||||
|
|
||||||
|
private:
|
||||||
UInt8 m_type;
|
UInt8 m_type;
|
||||||
void* m_data;
|
};
|
||||||
void* m_source;
|
|
||||||
|
class CIpcHelloMessage : public CIpcMessage {
|
||||||
|
public:
|
||||||
|
CIpcHelloMessage(EIpcClientType clientType);
|
||||||
|
virtual ~CIpcHelloMessage();
|
||||||
|
|
||||||
|
//! Gets the message type ID.
|
||||||
|
EIpcClientType clientType() const { return m_clientType; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
EIpcClientType m_clientType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CIpcShutdownMessage : public CIpcMessage {
|
||||||
|
public:
|
||||||
|
CIpcShutdownMessage();
|
||||||
|
virtual ~CIpcShutdownMessage();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CIpcLogLineMessage : public CIpcMessage {
|
||||||
|
public:
|
||||||
|
CIpcLogLineMessage(const CString& logLine);
|
||||||
|
virtual ~CIpcLogLineMessage();
|
||||||
|
|
||||||
|
//! Gets the log line.
|
||||||
|
CString logLine() const { return m_logLine; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CString m_logLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CIpcCommandMessage : public CIpcMessage {
|
||||||
|
public:
|
||||||
|
CIpcCommandMessage(const CString& command);
|
||||||
|
virtual ~CIpcCommandMessage();
|
||||||
|
|
||||||
|
//! Gets the command.
|
||||||
|
CString command() const { return m_command; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CString m_command;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
|
|
||||||
CEvent::Type CIpcServer::s_clientConnectedEvent = CEvent::kUnknown;
|
CEvent::Type CIpcServer::s_clientConnectedEvent = CEvent::kUnknown;
|
||||||
|
CEvent::Type CIpcServer::s_messageReceivedEvent = CEvent::kUnknown;
|
||||||
|
|
||||||
CIpcServer::CIpcServer() :
|
CIpcServer::CIpcServer() :
|
||||||
m_address(CNetworkAddress(IPC_HOST, IPC_PORT))
|
m_address(CNetworkAddress(IPC_HOST, IPC_PORT))
|
||||||
|
@ -45,7 +46,7 @@ CIpcServer::~CIpcServer()
|
||||||
ARCH->lockMutex(m_clientsMutex);
|
ARCH->lockMutex(m_clientsMutex);
|
||||||
CClientList::iterator it;
|
CClientList::iterator it;
|
||||||
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
for (it = m_clients.begin(); it != m_clients.end(); it++) {
|
||||||
delete *it;
|
deleteClient(*it);
|
||||||
}
|
}
|
||||||
m_clients.empty();
|
m_clients.empty();
|
||||||
ARCH->unlockMutex(m_clientsMutex);
|
ARCH->unlockMutex(m_clientsMutex);
|
||||||
|
@ -80,6 +81,11 @@ CIpcServer::handleClientConnecting(const CEvent&, void*)
|
||||||
new TMethodEventJob<CIpcServer>(
|
new TMethodEventJob<CIpcServer>(
|
||||||
this, &CIpcServer::handleClientDisconnected));
|
this, &CIpcServer::handleClientDisconnected));
|
||||||
|
|
||||||
|
EVENTQUEUE->adoptHandler(
|
||||||
|
CIpcClientProxy::getMessageReceivedEvent(), proxy,
|
||||||
|
new TMethodEventJob<CIpcServer>(
|
||||||
|
this, &CIpcServer::handleMessageReceived));
|
||||||
|
|
||||||
EVENTQUEUE->addEvent(CEvent(
|
EVENTQUEUE->addEvent(CEvent(
|
||||||
getClientConnectedEvent(), this, proxy, CEvent::kDontFreeData));
|
getClientConnectedEvent(), this, proxy, CEvent::kDontFreeData));
|
||||||
}
|
}
|
||||||
|
@ -89,15 +95,29 @@ CIpcServer::handleClientDisconnected(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcClientProxy* proxy = static_cast<CIpcClientProxy*>(e.getTarget());
|
CIpcClientProxy* proxy = static_cast<CIpcClientProxy*>(e.getTarget());
|
||||||
|
|
||||||
EVENTQUEUE->removeHandler(
|
|
||||||
CIpcClientProxy::getDisconnectedEvent(), proxy);
|
|
||||||
|
|
||||||
CArchMutexLock lock(m_clientsMutex);
|
CArchMutexLock lock(m_clientsMutex);
|
||||||
m_clients.remove(proxy);
|
m_clients.remove(proxy);
|
||||||
delete proxy;
|
deleteClient(proxy);
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "ipc client proxy removed, connected=%d", m_clients.size()));
|
LOG((CLOG_DEBUG "ipc client proxy removed, connected=%d", m_clients.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIpcServer::handleMessageReceived(const CEvent& e, void*)
|
||||||
|
{
|
||||||
|
CEvent event(getMessageReceivedEvent(), this);
|
||||||
|
event.setDataObject(e.getDataObject());
|
||||||
|
EVENTQUEUE->addEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIpcServer::deleteClient(CIpcClientProxy* proxy)
|
||||||
|
{
|
||||||
|
EVENTQUEUE->removeHandler(CIpcClientProxy::getMessageReceivedEvent(), proxy);
|
||||||
|
EVENTQUEUE->removeHandler(CIpcClientProxy::getDisconnectedEvent(), proxy);
|
||||||
|
delete proxy;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CIpcServer::hasClients(EIpcClientType clientType) const
|
CIpcServer::hasClients(EIpcClientType clientType) const
|
||||||
{
|
{
|
||||||
|
@ -127,6 +147,13 @@ CIpcServer::getClientConnectedEvent()
|
||||||
s_clientConnectedEvent, "CIpcServer::clientConnected");
|
s_clientConnectedEvent, "CIpcServer::clientConnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CEvent::Type
|
||||||
|
CIpcServer::getMessageReceivedEvent()
|
||||||
|
{
|
||||||
|
return EVENTQUEUE->registerTypeOnce(
|
||||||
|
s_messageReceivedEvent, "CIpcServer::messageReceived");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcServer::send(const CIpcMessage& message, EIpcClientType filterType)
|
CIpcServer::send(const CIpcMessage& message, EIpcClientType filterType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,12 +58,16 @@ public:
|
||||||
//! Raised when we have created the client proxy.
|
//! Raised when we have created the client proxy.
|
||||||
static CEvent::Type getClientConnectedEvent();
|
static CEvent::Type getClientConnectedEvent();
|
||||||
|
|
||||||
|
//! Raised when a message is received through a client proxy.
|
||||||
|
static CEvent::Type getMessageReceivedEvent();
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleClientConnecting(const CEvent&, void*);
|
void handleClientConnecting(const CEvent&, void*);
|
||||||
void handleClientDisconnected(const CEvent&, void*);
|
void handleClientDisconnected(const CEvent&, void*);
|
||||||
void handleClientMessage(const CEvent&, void*);
|
void handleMessageReceived(const CEvent&, void*);
|
||||||
|
void deleteClient(CIpcClientProxy* proxy);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::list<CIpcClientProxy*> CClientList;
|
typedef std::list<CIpcClientProxy*> CClientList;
|
||||||
|
@ -74,4 +78,5 @@ private:
|
||||||
CArchMutex m_clientsMutex;
|
CArchMutex m_clientsMutex;
|
||||||
|
|
||||||
static CEvent::Type s_clientConnectedEvent;
|
static CEvent::Type s_clientConnectedEvent;
|
||||||
|
static CEvent::Type s_messageReceivedEvent;
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,77 +45,88 @@ CIpcServerProxy::~CIpcServerProxy()
|
||||||
void
|
void
|
||||||
CIpcServerProxy::handleData(const CEvent&, void*)
|
CIpcServerProxy::handleData(const CEvent&, void*)
|
||||||
{
|
{
|
||||||
UInt8 code[1];
|
LOG((CLOG_DEBUG "start ipc server proxy handle data"));
|
||||||
UInt32 n = m_stream.read(code, 1);
|
|
||||||
|
UInt8 codeBuf[1];
|
||||||
|
UInt32 n = m_stream.read(codeBuf, 1);
|
||||||
|
int code = codeBuf[0];
|
||||||
|
|
||||||
while (n != 0) {
|
while (n != 0) {
|
||||||
|
|
||||||
CIpcMessage* m = new CIpcMessage();
|
LOG((CLOG_DEBUG "ipc server proxy read: %d", code));
|
||||||
m->m_type = code[0];
|
|
||||||
|
|
||||||
LOG((CLOG_DEBUG "ipc server proxy read: %d", m->m_type));
|
CIpcMessage* m = nullptr;
|
||||||
switch (m->m_type) {
|
switch (code) {
|
||||||
case kIpcLogLine:
|
case kIpcLogLine:
|
||||||
m->m_data = parseLogLine();
|
m = parseLogLine();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case kIpcShutdown:
|
case kIpcShutdown:
|
||||||
// no data.
|
m = new CIpcShutdownMessage();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
delete m;
|
|
||||||
disconnect();
|
disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// event deletes data.
|
// don't delete with this event; the data is passed to a new event.
|
||||||
EVENTQUEUE->addEvent(CEvent(getMessageReceivedEvent(), this, m));
|
CEvent e(getMessageReceivedEvent(), this, NULL, CEvent::kDontFreeData);
|
||||||
|
e.setDataObject(m);
|
||||||
|
EVENTQUEUE->addEvent(e);
|
||||||
|
|
||||||
n = m_stream.read(code, 1);
|
n = m_stream.read(codeBuf, 1);
|
||||||
|
code = codeBuf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG((CLOG_DEBUG "finished ipc server proxy handle data"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcServerProxy::send(const CIpcMessage& message)
|
CIpcServerProxy::send(const CIpcMessage& message)
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG "ipc server proxy write: %d", message.m_type));
|
LOG((CLOG_DEBUG "ipc server proxy write: %d", message.type()));
|
||||||
|
|
||||||
UInt8 code[1];
|
CProtocolUtil::writef(&m_stream, "%1i", message.type());
|
||||||
code[0] = message.m_type;
|
|
||||||
m_stream.write(code, 1);
|
|
||||||
|
|
||||||
switch (message.m_type) {
|
switch (message.type()) {
|
||||||
case kIpcHello:
|
case kIpcHello: {
|
||||||
m_stream.write(message.m_data, 1);
|
const CIpcHelloMessage& hm = static_cast<const CIpcHelloMessage&>(message);
|
||||||
|
CProtocolUtil::writef(&m_stream, "%1i", hm.clientType());
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case kIpcCommand: {
|
case kIpcCommand: {
|
||||||
CString* s = (CString*)message.m_data;
|
const CIpcCommandMessage& cm = static_cast<const CIpcCommandMessage&>(message);
|
||||||
const char* data = s->c_str();
|
|
||||||
|
|
||||||
|
CString command = cm.command();
|
||||||
|
const char* data = command.c_str();
|
||||||
int len = strlen(data);
|
int len = strlen(data);
|
||||||
CProtocolUtil::writef(&m_stream, "%2i", len);
|
|
||||||
|
|
||||||
|
CProtocolUtil::writef(&m_stream, "%2i", len);
|
||||||
m_stream.write(data, len);
|
m_stream.write(data, len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG((CLOG_ERR "message not supported: %d", message.m_type));
|
LOG((CLOG_ERR "message not supported: %d", message.type()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
CIpcLogLineMessage*
|
||||||
CIpcServerProxy::parseLogLine()
|
CIpcServerProxy::parseLogLine()
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
CProtocolUtil::readf(&m_stream, "%4i", &len);
|
CProtocolUtil::readf(&m_stream, "%4i", &len);
|
||||||
|
|
||||||
UInt8* buffer = new UInt8[len];
|
char* buffer = new char[len];
|
||||||
m_stream.read(buffer, len);
|
m_stream.read(buffer, len);
|
||||||
|
CString s(buffer, len);
|
||||||
|
delete buffer;
|
||||||
|
|
||||||
return new CString((const char*)buffer, len);
|
// must be deleted by event handler.
|
||||||
|
return new CIpcLogLineMessage(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -21,22 +21,25 @@
|
||||||
|
|
||||||
namespace synergy { class IStream; }
|
namespace synergy { class IStream; }
|
||||||
class CIpcMessage;
|
class CIpcMessage;
|
||||||
|
class CIpcLogLineMessage;
|
||||||
|
|
||||||
class CIpcServerProxy {
|
class CIpcServerProxy {
|
||||||
|
friend class CIpcClient;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CIpcServerProxy(synergy::IStream& stream);
|
CIpcServerProxy(synergy::IStream& stream);
|
||||||
virtual ~CIpcServerProxy();
|
virtual ~CIpcServerProxy();
|
||||||
|
|
||||||
|
private:
|
||||||
void send(const CIpcMessage& message);
|
void send(const CIpcMessage& message);
|
||||||
|
|
||||||
|
void handleData(const CEvent&, void*);
|
||||||
|
CIpcLogLineMessage* parseLogLine();
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
//! Raised when the client receives a message from the server.
|
//! Raised when the client receives a message from the server.
|
||||||
static CEvent::Type getMessageReceivedEvent();
|
static CEvent::Type getMessageReceivedEvent();
|
||||||
|
|
||||||
private:
|
|
||||||
void handleData(const CEvent&, void*);
|
|
||||||
void* parseLogLine();
|
|
||||||
void disconnect();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
synergy::IStream& m_stream;
|
synergy::IStream& m_stream;
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,14 @@ CMSWindowsClipboard::~CMSWindowsClipboard()
|
||||||
delete m_facade;
|
delete m_facade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsClipboard::setFacade(IMSWindowsClipboardFacade& facade)
|
||||||
|
{
|
||||||
|
delete m_facade;
|
||||||
|
m_facade = &facade;
|
||||||
|
m_deleteFacade = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CMSWindowsClipboard::emptyUnowned()
|
CMSWindowsClipboard::emptyUnowned()
|
||||||
{
|
{
|
||||||
|
|
|
@ -61,7 +61,7 @@ public:
|
||||||
virtual bool has(EFormat) const;
|
virtual bool has(EFormat) const;
|
||||||
virtual CString get(EFormat) const;
|
virtual CString get(EFormat) const;
|
||||||
|
|
||||||
void setFacade(IMSWindowsClipboardFacade& facade) { m_facade = &facade; m_deleteFacade = false; }
|
void setFacade(IMSWindowsClipboardFacade& facade);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearConverters();
|
void clearConverters();
|
||||||
|
|
|
@ -186,7 +186,7 @@ CMSWindowsDesks::setOptions(const COptionsList& options)
|
||||||
for (UInt32 i = 0, n = (UInt32)options.size(); i < n; i += 2) {
|
for (UInt32 i = 0, n = (UInt32)options.size(); i < n; i += 2) {
|
||||||
if (options[i] == kOptionWin32KeepForeground) {
|
if (options[i] == kOptionWin32KeepForeground) {
|
||||||
m_leaveForegroundOption = (options[i + 1] != 0);
|
m_leaveForegroundOption = (options[i + 1] != 0);
|
||||||
LOG((CLOG_DEBUG1 "%s the foreground window", m_leaveForegroundOption ? "Don\'t grab" : "Grab"));
|
LOG((CLOG_DEBUG1 "%s the foreground window", m_leaveForegroundOption ? "don\'t grab" : "grab"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,12 @@ void
|
||||||
CMSWindowsRelauncher::stop()
|
CMSWindowsRelauncher::stop()
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
|
|
||||||
m_thread->wait(5);
|
m_thread->wait(5);
|
||||||
|
delete m_thread;
|
||||||
|
|
||||||
|
m_outputThread->wait(5);
|
||||||
|
delete m_outputThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this still gets the physical session (the one the keyboard and
|
// this still gets the physical session (the one the keyboard and
|
||||||
|
@ -360,6 +365,8 @@ CMSWindowsRelauncher::mainLoop(void*)
|
||||||
LOG((CLOG_DEBUG "terminated running process on exit"));
|
LOG((CLOG_DEBUG "terminated running process on exit"));
|
||||||
shutdownProcess(pi, 10);
|
shutdownProcess(pi, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG((CLOG_DEBUG "relauncher main thread finished"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -403,7 +410,7 @@ CMSWindowsRelauncher::outputLoop(void*)
|
||||||
// +1 char for \0
|
// +1 char for \0
|
||||||
CHAR buffer[kOutputBufferSize + 1];
|
CHAR buffer[kOutputBufferSize + 1];
|
||||||
|
|
||||||
while (true) {
|
while (m_running) {
|
||||||
|
|
||||||
DWORD bytesRead;
|
DWORD bytesRead;
|
||||||
BOOL success = ReadFile(m_stdOutRead, buffer, kOutputBufferSize, &bytesRead, NULL);
|
BOOL success = ReadFile(m_stdOutRead, buffer, kOutputBufferSize, &bytesRead, NULL);
|
||||||
|
@ -432,8 +439,7 @@ CMSWindowsRelauncher::shutdownProcess(const PROCESS_INFORMATION& pi, int timeout
|
||||||
if (exitCode != STILL_ACTIVE)
|
if (exitCode != STILL_ACTIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CIpcMessage shutdown;
|
CIpcShutdownMessage shutdown;
|
||||||
shutdown.m_type = kIpcShutdown;
|
|
||||||
m_ipcServer.send(shutdown, kIpcClientNode);
|
m_ipcServer.send(shutdown, kIpcClientNode);
|
||||||
|
|
||||||
// wait for process to exit gracefully.
|
// wait for process to exit gracefully.
|
||||||
|
|
|
@ -248,6 +248,11 @@ CApp::run(int argc, char** argv)
|
||||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CArch arch;
|
||||||
|
arch.init();
|
||||||
|
|
||||||
|
CLog log;
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_10_7
|
#if MAC_OS_X_VERSION_10_7
|
||||||
// dock hide only supported on lion :(
|
// dock hide only supported on lion :(
|
||||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||||
|
@ -348,28 +353,27 @@ CApp::initApp(int argc, const char** argv)
|
||||||
void
|
void
|
||||||
CApp::initIpcClient()
|
CApp::initIpcClient()
|
||||||
{
|
{
|
||||||
// TODO: delete ipc client on shutdown and the 2 event handlers.
|
|
||||||
m_ipcClient = new CIpcClient();
|
m_ipcClient = new CIpcClient();
|
||||||
m_ipcClient->connect();
|
m_ipcClient->connect();
|
||||||
|
|
||||||
EVENTQUEUE->adoptHandler(
|
EVENTQUEUE->adoptHandler(
|
||||||
CIpcClient::getConnectedEvent(), m_ipcClient,
|
CIpcClient::getMessageReceivedEvent(), m_ipcClient,
|
||||||
new TMethodEventJob<CApp>(this, &CApp::handleIpcConnected));
|
new TMethodEventJob<CApp>(this, &CApp::handleIpcMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CApp::handleIpcConnected(const CEvent& e, void*)
|
CApp::cleanupIpcClient()
|
||||||
{
|
{
|
||||||
EVENTQUEUE->adoptHandler(
|
m_ipcClient->disconnect();
|
||||||
CIpcServerProxy::getMessageReceivedEvent(), e.getData(),
|
EVENTQUEUE->removeHandler(CIpcClient::getMessageReceivedEvent(), m_ipcClient);
|
||||||
new TMethodEventJob<CApp>(this, &CApp::handleIpcMessage));
|
delete m_ipcClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CApp::handleIpcMessage(const CEvent& e, void*)
|
CApp::handleIpcMessage(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
|
CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
|
||||||
if (m->m_type == kIpcShutdown) {
|
if (m->type() == kIpcShutdown) {
|
||||||
LOG((CLOG_INFO "got ipc shutdown message"));
|
LOG((CLOG_INFO "got ipc shutdown message"));
|
||||||
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
|
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,13 +94,13 @@ public:
|
||||||
virtual void bye(int error) { m_bye(error); }
|
virtual void bye(int error) { m_bye(error); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleIpcConnected(const CEvent&, void*);
|
|
||||||
void handleIpcMessage(const CEvent&, void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void parseArgs(int argc, const char* const* argv, int &i);
|
virtual void parseArgs(int argc, const char* const* argv, int &i);
|
||||||
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
|
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
|
||||||
void initIpcClient();
|
void initIpcClient();
|
||||||
|
void cleanupIpcClient();
|
||||||
|
|
||||||
IArchTaskBarReceiver* m_taskBarReceiver;
|
IArchTaskBarReceiver* m_taskBarReceiver;
|
||||||
bool m_suspended;
|
bool m_suspended;
|
||||||
|
|
|
@ -552,6 +552,10 @@ CClientApp::mainLoop()
|
||||||
updateStatus();
|
updateStatus();
|
||||||
LOG((CLOG_NOTE "stopped client"));
|
LOG((CLOG_NOTE "stopped client"));
|
||||||
|
|
||||||
|
if (argsBase().m_enableIpc) {
|
||||||
|
cleanupIpcClient();
|
||||||
|
}
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
#include "CSocketMultiplexer.h"
|
#include "CSocketMultiplexer.h"
|
||||||
#include "CIpcLogOutputter.h"
|
#include "CIpcLogOutputter.h"
|
||||||
|
#include "CLog.h"
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
@ -91,23 +92,28 @@ CDaemonApp::~CDaemonApp()
|
||||||
int
|
int
|
||||||
CDaemonApp::run(int argc, char** argv)
|
CDaemonApp::run(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
#if SYSAPI_WIN32
|
||||||
|
// win32 instance needed for threading, etc.
|
||||||
|
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CArch arch;
|
||||||
|
arch.init();
|
||||||
|
|
||||||
|
CLog log;
|
||||||
|
|
||||||
bool uninstall = false;
|
bool uninstall = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if SYSAPI_WIN32
|
|
||||||
// win32 instance needed for threading, etc.
|
|
||||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
// sends debug messages to visual studio console window.
|
// sends debug messages to visual studio console window.
|
||||||
CLOG->insert(new CMSWindowsDebugOutputter());
|
log.insert(new CMSWindowsDebugOutputter());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// default log level to system setting.
|
// default log level to system setting.
|
||||||
string logLevel = ARCH->setting("LogLevel");
|
string logLevel = arch.setting("LogLevel");
|
||||||
if (logLevel != "")
|
if (logLevel != "")
|
||||||
CLOG->setFilter(logLevel.c_str());
|
log.setFilter(logLevel.c_str());
|
||||||
|
|
||||||
bool foreground = false;
|
bool foreground = false;
|
||||||
|
|
||||||
|
@ -120,11 +126,11 @@ CDaemonApp::run(int argc, char** argv)
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
else if (arg == "/install") {
|
else if (arg == "/install") {
|
||||||
uninstall = true;
|
uninstall = true;
|
||||||
ARCH->installDaemon();
|
arch.installDaemon();
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
else if (arg == "/uninstall") {
|
else if (arg == "/uninstall") {
|
||||||
ARCH->uninstallDaemon();
|
arch.uninstallDaemon();
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,9 +149,9 @@ CDaemonApp::run(int argc, char** argv)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
ARCH->daemonize("Synergy", winMainLoopStatic);
|
arch.daemonize("Synergy", winMainLoopStatic);
|
||||||
#elif SYSAPI_UNIX
|
#elif SYSAPI_UNIX
|
||||||
ARCH->daemonize("Synergy", unixMainLoopStatic);
|
arch.daemonize("Synergy", unixMainLoopStatic);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,8 +209,8 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
eventQueue.adoptHandler(
|
eventQueue.adoptHandler(
|
||||||
CIpcServer::getClientConnectedEvent(), m_ipcServer,
|
CIpcServer::getMessageReceivedEvent(), m_ipcServer,
|
||||||
new TMethodEventJob<CDaemonApp>(this, &CDaemonApp::handleIpcConnected));
|
new TMethodEventJob<CDaemonApp>(this, &CDaemonApp::handleIpcMessage));
|
||||||
|
|
||||||
m_ipcServer->listen();
|
m_ipcServer->listen();
|
||||||
|
|
||||||
|
@ -228,10 +234,11 @@ CDaemonApp::mainLoop(bool logToFile)
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
m_relauncher->stop();
|
m_relauncher->stop();
|
||||||
|
delete m_relauncher;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
eventQueue.removeHandler(
|
eventQueue.removeHandler(
|
||||||
CIpcServer::getClientConnectedEvent(), m_ipcServer);
|
CIpcServer::getMessageReceivedEvent(), m_ipcServer);
|
||||||
|
|
||||||
CLOG->remove(m_ipcLogOutputter);
|
CLOG->remove(m_ipcLogOutputter);
|
||||||
delete m_ipcLogOutputter;
|
delete m_ipcLogOutputter;
|
||||||
|
@ -278,23 +285,14 @@ CDaemonApp::logPath()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CDaemonApp::handleIpcConnected(const CEvent& e, void*)
|
|
||||||
{
|
|
||||||
LOG((CLOG_DEBUG "ipc client connected"));
|
|
||||||
EVENTQUEUE->adoptHandler(
|
|
||||||
CIpcClientProxy::getMessageReceivedEvent(), e.getData(),
|
|
||||||
new TMethodEventJob<CDaemonApp>(
|
|
||||||
this, &CDaemonApp::handleIpcMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
|
CDaemonApp::handleIpcMessage(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcMessage& m = *static_cast<CIpcMessage*>(e.getData());
|
CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
|
||||||
switch (m.m_type) {
|
switch (m->type()) {
|
||||||
case kIpcCommand: {
|
case kIpcCommand: {
|
||||||
CString& command = *static_cast<CString*>(m.m_data);
|
CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
|
||||||
|
CString& command = cm->command();
|
||||||
LOG((CLOG_DEBUG "got new command: %s", command.c_str()));
|
LOG((CLOG_DEBUG "got new command: %s", command.c_str()));
|
||||||
|
|
||||||
CString debugArg("--debug");
|
CString debugArg("--debug");
|
||||||
|
|
|
@ -41,7 +41,6 @@ private:
|
||||||
void daemonize();
|
void daemonize();
|
||||||
void foregroundError(const char* message);
|
void foregroundError(const char* message);
|
||||||
std::string logPath();
|
std::string logPath();
|
||||||
void handleIpcConnected(const CEvent&, void*);
|
|
||||||
void handleIpcMessage(const CEvent&, void*);
|
void handleIpcMessage(const CEvent&, void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -831,6 +831,10 @@ CServerApp::mainLoop()
|
||||||
updateStatus();
|
updateStatus();
|
||||||
LOG((CLOG_NOTE "stopped server"));
|
LOG((CLOG_NOTE "stopped server"));
|
||||||
|
|
||||||
|
if (argsBase().m_enableIpc) {
|
||||||
|
cleanupIpcClient();
|
||||||
|
}
|
||||||
|
|
||||||
return kExitSuccess;
|
return kExitSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
#include "CIpcServerProxy.h"
|
#include "CIpcServerProxy.h"
|
||||||
#include "CIpcMessage.h"
|
#include "CIpcMessage.h"
|
||||||
|
#include "CSimpleEventQueueBuffer.h"
|
||||||
|
|
||||||
class CIpcTests : public ::testing::Test
|
class CIpcTests : public ::testing::Test
|
||||||
{
|
{
|
||||||
|
@ -41,14 +42,15 @@ public:
|
||||||
CIpcTests();
|
CIpcTests();
|
||||||
virtual ~CIpcTests();
|
virtual ~CIpcTests();
|
||||||
|
|
||||||
void connectToServer_handleClientConnected(const CEvent&, void*);
|
void connectToServer_handleMessageReceived(const CEvent&, void*);
|
||||||
void sendMessageToServer_handleClientConnected(const CEvent&, void*);
|
void sendMessageToServer_handleClientConnected(const CEvent&, void*);
|
||||||
void sendMessageToServer_handleMessageReceived(const CEvent&, void*);
|
void sendMessageToServer_handleMessageReceived(const CEvent&, void*);
|
||||||
void sendMessageToClient_handleConnected(const CEvent&, void*);
|
void sendMessageToClient_handleClientConnected(const CEvent&, void*);
|
||||||
void sendMessageToClient_handleMessageReceived(const CEvent&, void*);
|
void sendMessageToClient_handleMessageReceived(const CEvent&, void*);
|
||||||
void handleQuitTimeout(const CEvent&, void* vclient);
|
void handleQuitTimeout(const CEvent&, void* vclient);
|
||||||
void raiseQuitEvent();
|
void raiseQuitEvent();
|
||||||
void quitTimeout(double timeout);
|
void initQuitTimeout(double timeout);
|
||||||
|
void cleanupQuitTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void timeoutThread(void*);
|
void timeoutThread(void*);
|
||||||
|
@ -56,11 +58,13 @@ private:
|
||||||
public:
|
public:
|
||||||
CSocketMultiplexer m_multiplexer;
|
CSocketMultiplexer m_multiplexer;
|
||||||
CEventQueue m_events;
|
CEventQueue m_events;
|
||||||
|
CEventQueueTimer* m_quitTimeoutTimer;
|
||||||
bool m_connectToServer_clientConnected;
|
bool m_connectToServer_clientConnected;
|
||||||
CString m_sendMessageToServer_receivedString;
|
CString m_sendMessageToServer_receivedString;
|
||||||
CString m_sendMessageToClient_receivedString;
|
CString m_sendMessageToClient_receivedString;
|
||||||
CIpcClient* m_sendMessageToServer_client;
|
CIpcClient* m_sendMessageToServer_client;
|
||||||
CIpcServer* m_sendMessageToClient_server;
|
CIpcServer* m_sendMessageToClient_server;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(CIpcTests, connectToServer)
|
TEST_F(CIpcTests, connectToServer)
|
||||||
|
@ -69,15 +73,17 @@ TEST_F(CIpcTests, connectToServer)
|
||||||
server.listen();
|
server.listen();
|
||||||
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
CIpcServer::getClientConnectedEvent(), &server,
|
CIpcServer::getMessageReceivedEvent(), &server,
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::connectToServer_handleClientConnected));
|
this, &CIpcTests::connectToServer_handleMessageReceived));
|
||||||
|
|
||||||
CIpcClient client;
|
CIpcClient client;
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
quitTimeout(2);
|
initQuitTimeout(2);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
|
m_events.removeHandler(CIpcServer::getMessageReceivedEvent(), &server);
|
||||||
|
cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ(true, m_connectToServer_clientConnected);
|
EXPECT_EQ(true, m_connectToServer_clientConnected);
|
||||||
}
|
}
|
||||||
|
@ -87,18 +93,26 @@ TEST_F(CIpcTests, sendMessageToServer)
|
||||||
CIpcServer server;
|
CIpcServer server;
|
||||||
server.listen();
|
server.listen();
|
||||||
|
|
||||||
CIpcClient client;
|
// event handler sends "test" command to server.
|
||||||
client.connect();
|
|
||||||
m_sendMessageToServer_client = &client;
|
|
||||||
|
|
||||||
// event handler sends "test" log line to client.
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
CIpcServer::getClientConnectedEvent(), &server,
|
CIpcServer::getClientConnectedEvent(), &server,
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::sendMessageToServer_handleClientConnected));
|
this, &CIpcTests::sendMessageToServer_handleClientConnected));
|
||||||
|
|
||||||
quitTimeout(2);
|
m_events.adoptHandler(
|
||||||
|
CIpcServer::getMessageReceivedEvent(), &server,
|
||||||
|
new TMethodEventJob<CIpcTests>(
|
||||||
|
this, &CIpcTests::sendMessageToServer_handleMessageReceived));
|
||||||
|
|
||||||
|
CIpcClient client;
|
||||||
|
client.connect();
|
||||||
|
m_sendMessageToServer_client = &client;
|
||||||
|
|
||||||
|
initQuitTimeout(2);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
|
m_events.removeHandler(CIpcServer::getClientConnectedEvent(), &server);
|
||||||
|
m_events.removeHandler(CIpcServer::getMessageReceivedEvent(), &server);
|
||||||
|
cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ("test", m_sendMessageToServer_receivedString);
|
EXPECT_EQ("test", m_sendMessageToServer_receivedString);
|
||||||
}
|
}
|
||||||
|
@ -109,22 +123,31 @@ TEST_F(CIpcTests, sendMessageToClient)
|
||||||
server.listen();
|
server.listen();
|
||||||
m_sendMessageToClient_server = &server;
|
m_sendMessageToClient_server = &server;
|
||||||
|
|
||||||
|
// event handler sends "test" log line to client.
|
||||||
|
m_events.adoptHandler(
|
||||||
|
CIpcServer::getClientConnectedEvent(), &server,
|
||||||
|
new TMethodEventJob<CIpcTests>(
|
||||||
|
this, &CIpcTests::sendMessageToClient_handleClientConnected));
|
||||||
|
|
||||||
CIpcClient client;
|
CIpcClient client;
|
||||||
client.connect();
|
client.connect();
|
||||||
|
|
||||||
// event handler sends "test" log line to server.
|
|
||||||
m_events.adoptHandler(
|
m_events.adoptHandler(
|
||||||
CIpcClient::getConnectedEvent(), &client,
|
CIpcClient::getMessageReceivedEvent(), &client,
|
||||||
new TMethodEventJob<CIpcTests>(
|
new TMethodEventJob<CIpcTests>(
|
||||||
this, &CIpcTests::sendMessageToClient_handleConnected));
|
this, &CIpcTests::sendMessageToClient_handleMessageReceived));
|
||||||
|
|
||||||
quitTimeout(2);
|
initQuitTimeout(2);
|
||||||
m_events.loop();
|
m_events.loop();
|
||||||
|
m_events.removeHandler(CIpcServer::getClientConnectedEvent(), &server);
|
||||||
|
m_events.removeHandler(CIpcClient::getMessageReceivedEvent(), &client);
|
||||||
|
cleanupQuitTimeout();
|
||||||
|
|
||||||
EXPECT_EQ("test", m_sendMessageToClient_receivedString);
|
EXPECT_EQ("test", m_sendMessageToClient_receivedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
CIpcTests::CIpcTests() :
|
CIpcTests::CIpcTests() :
|
||||||
|
m_quitTimeoutTimer(nullptr),
|
||||||
m_connectToServer_clientConnected(false),
|
m_connectToServer_clientConnected(false),
|
||||||
m_sendMessageToClient_server(nullptr),
|
m_sendMessageToClient_server(nullptr),
|
||||||
m_sendMessageToServer_client(nullptr)
|
m_sendMessageToServer_client(nullptr)
|
||||||
|
@ -136,56 +159,47 @@ CIpcTests::~CIpcTests()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::connectToServer_handleClientConnected(const CEvent&, void*)
|
CIpcTests::connectToServer_handleMessageReceived(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
m_connectToServer_clientConnected = true;
|
CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
|
||||||
raiseQuitEvent();
|
if (m->m_type == kIpcHello) {
|
||||||
|
m_connectToServer_clientConnected = true;
|
||||||
|
raiseQuitEvent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::sendMessageToServer_handleClientConnected(const CEvent& e, void*)
|
CIpcTests::sendMessageToServer_handleClientConnected(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
m_events.adoptHandler(
|
CIpcCommandMessage m("test");
|
||||||
CIpcClientProxy::getMessageReceivedEvent(), e.getData(),
|
|
||||||
new TMethodEventJob<CIpcTests>(
|
|
||||||
this, &CIpcTests::sendMessageToServer_handleMessageReceived));
|
|
||||||
|
|
||||||
CIpcMessage m;
|
|
||||||
m.m_type = kIpcCommand;
|
|
||||||
m.m_data = new CString("test");
|
|
||||||
m_sendMessageToServer_client->send(m);
|
m_sendMessageToServer_client->send(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::sendMessageToServer_handleMessageReceived(const CEvent& e, void*)
|
CIpcTests::sendMessageToServer_handleMessageReceived(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
|
CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
|
||||||
if (m->m_type == kIpcCommand) {
|
if (m->m_type == kIpcCommand) {
|
||||||
m_sendMessageToServer_receivedString = *static_cast<CString*>(m->m_data);
|
CIpcCommandMessage* cm = static_cast<CIpcCommandMessage*>(m);
|
||||||
|
m_sendMessageToServer_receivedString = cm->command();
|
||||||
raiseQuitEvent();
|
raiseQuitEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::sendMessageToClient_handleConnected(const CEvent& e, void*)
|
CIpcTests::sendMessageToClient_handleClientConnected(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
m_events.adoptHandler(
|
CIpcLogLineMessage m("test");
|
||||||
CIpcServerProxy::getMessageReceivedEvent(), e.getData(),
|
|
||||||
new TMethodEventJob<CIpcTests>(
|
|
||||||
this, &CIpcTests::sendMessageToClient_handleMessageReceived));
|
|
||||||
|
|
||||||
CIpcMessage m;
|
|
||||||
m.m_type = kIpcLogLine;
|
|
||||||
m.m_data = new CString("test");
|
|
||||||
m_sendMessageToClient_server->send(m, kIpcClientUnknown);
|
m_sendMessageToClient_server->send(m, kIpcClientUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
|
CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
|
||||||
{
|
{
|
||||||
CIpcMessage* m = static_cast<CIpcMessage*>(e.getData());
|
CIpcMessage* m = static_cast<CIpcMessage*>(e.getDataObject());
|
||||||
if (m->m_type == kIpcLogLine) {
|
if (m->m_type == kIpcLogLine) {
|
||||||
m_sendMessageToClient_receivedString = *static_cast<CString*>(m->m_data);
|
CIpcLogLineMessage* llm = static_cast<CIpcLogLineMessage*>(m);
|
||||||
|
m_sendMessageToClient_receivedString = llm->logLine();
|
||||||
raiseQuitEvent();
|
raiseQuitEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,15 +207,25 @@ CIpcTests::sendMessageToClient_handleMessageReceived(const CEvent& e, void*)
|
||||||
void
|
void
|
||||||
CIpcTests::raiseQuitEvent()
|
CIpcTests::raiseQuitEvent()
|
||||||
{
|
{
|
||||||
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit, nullptr));
|
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CIpcTests::quitTimeout(double timeout)
|
CIpcTests::initQuitTimeout(double timeout)
|
||||||
{
|
{
|
||||||
CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(timeout, NULL);
|
assert(m_quitTimeoutTimer == nullptr);
|
||||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, timer,
|
m_quitTimeoutTimer = EVENTQUEUE->newOneShotTimer(timeout, NULL);
|
||||||
new TMethodEventJob<CIpcTests>(this, &CIpcTests::handleQuitTimeout, timer));
|
EVENTQUEUE->adoptHandler(CEvent::kTimer, m_quitTimeoutTimer,
|
||||||
|
new TMethodEventJob<CIpcTests>(
|
||||||
|
this, &CIpcTests::handleQuitTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CIpcTests::cleanupQuitTimeout()
|
||||||
|
{
|
||||||
|
EVENTQUEUE->removeHandler(CEvent::kTimer, m_quitTimeoutTimer);
|
||||||
|
delete m_quitTimeoutTimer;
|
||||||
|
m_quitTimeoutTimer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -40,6 +40,11 @@ main(int argc, char **argv)
|
||||||
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CArch arch;
|
||||||
|
arch.init();
|
||||||
|
|
||||||
|
CLog log;
|
||||||
|
|
||||||
string lockFile;
|
string lockFile;
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
if (string(argv[i]).compare("--lock-file") == 0) {
|
if (string(argv[i]).compare("--lock-file") == 0) {
|
||||||
|
|
Loading…
Reference in New Issue