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