Added support for heartbeat global option.
This commit is contained in:
parent
8685afd9f6
commit
366537dc22
|
@ -34,7 +34,8 @@ CServerProxy::CServerProxy(IClient* client,
|
||||||
m_client(client),
|
m_client(client),
|
||||||
m_input(adoptedInput),
|
m_input(adoptedInput),
|
||||||
m_output(adoptedOutput),
|
m_output(adoptedOutput),
|
||||||
m_seqNum(0)
|
m_seqNum(0),
|
||||||
|
m_heartRate(kHeartRate)
|
||||||
{
|
{
|
||||||
assert(m_client != NULL);
|
assert(m_client != NULL);
|
||||||
assert(m_input != NULL);
|
assert(m_input != NULL);
|
||||||
|
@ -76,7 +77,7 @@ CServerProxy::mainLoop()
|
||||||
// wait for a message
|
// wait for a message
|
||||||
LOG((CLOG_DEBUG2 "waiting for message"));
|
LOG((CLOG_DEBUG2 "waiting for message"));
|
||||||
UInt8 code[4];
|
UInt8 code[4];
|
||||||
UInt32 n = getInputStream()->read(code, 4, kHeartRate);
|
UInt32 n = getInputStream()->read(code, 4, m_heartRate);
|
||||||
|
|
||||||
// check if server hungup
|
// check if server hungup
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
@ -86,7 +87,7 @@ CServerProxy::mainLoop()
|
||||||
|
|
||||||
// check for time out
|
// check for time out
|
||||||
if (n == (UInt32)-1 ||
|
if (n == (UInt32)-1 ||
|
||||||
(kHeartRate >= 0.0 && heartbeat.getTime() > kHeartRate)) {
|
(m_heartRate >= 0.0 && heartbeat.getTime() > m_heartRate)) {
|
||||||
// send heartbeat
|
// send heartbeat
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
CProtocolUtil::writef(getOutputStream(), kMsgCNoop);
|
CProtocolUtil::writef(getOutputStream(), kMsgCNoop);
|
||||||
|
@ -663,9 +664,20 @@ CServerProxy::resetOptions()
|
||||||
// forward
|
// forward
|
||||||
getClient()->resetOptions();
|
getClient()->resetOptions();
|
||||||
|
|
||||||
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
|
// reset heart rate
|
||||||
|
m_heartRate = kHeartRate;
|
||||||
|
|
||||||
// reset modifier translation table
|
// reset modifier translation table
|
||||||
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id)
|
for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) {
|
||||||
m_modifierTranslationTable[id] = id;
|
m_modifierTranslationTable[id] = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send heartbeat if necessary
|
||||||
|
if (m_heartRate >= 0.0) {
|
||||||
|
CProtocolUtil::writef(getOutputStream(), kMsgCNoop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -679,6 +691,8 @@ CServerProxy::setOptions()
|
||||||
// forward
|
// forward
|
||||||
getClient()->setOptions(options);
|
getClient()->setOptions(options);
|
||||||
|
|
||||||
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
// update modifier table
|
// update modifier table
|
||||||
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||||
KeyModifierID id = kKeyModifierIDNull;
|
KeyModifierID id = kKeyModifierIDNull;
|
||||||
|
@ -697,6 +711,15 @@ CServerProxy::setOptions()
|
||||||
else if (options[i] == kOptionModifierMapForSuper) {
|
else if (options[i] == kOptionModifierMapForSuper) {
|
||||||
id = kKeyModifierIDSuper;
|
id = kKeyModifierIDSuper;
|
||||||
}
|
}
|
||||||
|
else if (options[i] == kOptionHeartbeat) {
|
||||||
|
// update heart rate
|
||||||
|
m_heartRate = 1.0e-3 * static_cast<double>(options[i + 1]);
|
||||||
|
|
||||||
|
// send heartbeat if necessary
|
||||||
|
if (m_heartRate >= 0.0) {
|
||||||
|
CProtocolUtil::writef(getOutputStream(), kMsgCNoop);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (id != kKeyModifierIDNull) {
|
if (id != kKeyModifierIDNull) {
|
||||||
m_modifierTranslationTable[id] =
|
m_modifierTranslationTable[id] =
|
||||||
static_cast<KeyModifierID>(options[i + 1]);
|
static_cast<KeyModifierID>(options[i + 1]);
|
||||||
|
|
|
@ -130,6 +130,7 @@ private:
|
||||||
bool m_ignoreMouse;
|
bool m_ignoreMouse;
|
||||||
|
|
||||||
KeyModifierID m_modifierTranslationTable[kKeyModifierIDLast];
|
KeyModifierID m_modifierTranslationTable[kKeyModifierIDLast];
|
||||||
|
double m_heartRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,3 +59,9 @@ CClientProxy::getName() const
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CMutex*
|
||||||
|
CClientProxy::getMutex() const
|
||||||
|
{
|
||||||
|
return &m_mutex;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#define CCLIENTPROXY_H
|
#define CCLIENTPROXY_H
|
||||||
|
|
||||||
#include "IClient.h"
|
#include "IClient.h"
|
||||||
|
#include "CMutex.h"
|
||||||
#include "CString.h"
|
#include "CString.h"
|
||||||
|
|
||||||
class IInputStream;
|
class IInputStream;
|
||||||
|
@ -84,7 +85,16 @@ public:
|
||||||
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
|
||||||
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! Get mutex
|
||||||
|
/*!
|
||||||
|
Returns the mutex for this object. Subclasses should use this
|
||||||
|
mutex to protect their data.
|
||||||
|
*/
|
||||||
|
const CMutex* getMutex() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
CMutex m_mutex;
|
||||||
IServer* m_server;
|
IServer* m_server;
|
||||||
CString m_name;
|
CString m_name;
|
||||||
IInputStream* m_input;
|
IInputStream* m_input;
|
||||||
|
|
|
@ -31,7 +31,9 @@
|
||||||
|
|
||||||
CClientProxy1_0::CClientProxy1_0(IServer* server, const CString& name,
|
CClientProxy1_0::CClientProxy1_0(IServer* server, const CString& name,
|
||||||
IInputStream* input, IOutputStream* output) :
|
IInputStream* input, IOutputStream* output) :
|
||||||
CClientProxy(server, name, input, output)
|
CClientProxy(server, name, input, output),
|
||||||
|
m_heartRate(kHeartRate),
|
||||||
|
m_heartDeath(kHeartRate * kHeartBeatsUntilDeath)
|
||||||
{
|
{
|
||||||
for (UInt32 i = 0; i < kClipboardEnd; ++i) {
|
for (UInt32 i = 0; i < kClipboardEnd; ++i) {
|
||||||
m_clipboardDirty[i] = true;
|
m_clipboardDirty[i] = true;
|
||||||
|
@ -81,7 +83,7 @@ CClientProxy1_0::mainLoop()
|
||||||
|
|
||||||
// wait for a message
|
// wait for a message
|
||||||
UInt8 code[4];
|
UInt8 code[4];
|
||||||
UInt32 n = getInputStream()->read(code, 4, kHeartRate);
|
UInt32 n = getInputStream()->read(code, 4, m_heartRate);
|
||||||
CThread::testCancel();
|
CThread::testCancel();
|
||||||
|
|
||||||
// check if client hungup
|
// check if client hungup
|
||||||
|
@ -92,7 +94,7 @@ CClientProxy1_0::mainLoop()
|
||||||
|
|
||||||
// check if client has stopped sending heartbeats
|
// check if client has stopped sending heartbeats
|
||||||
if (n == (UInt32)-1) {
|
if (n == (UInt32)-1) {
|
||||||
if (kHeartDeath >= 0.0 && heartTimer.getTime() > kHeartDeath) {
|
if (m_heartDeath >= 0.0 && heartTimer.getTime() > m_heartDeath) {
|
||||||
LOG((CLOG_NOTE "client \"%s\" is dead", getName().c_str()));
|
LOG((CLOG_NOTE "client \"%s\" is dead", getName().c_str()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -117,6 +119,7 @@ CClientProxy1_0::mainLoop()
|
||||||
}
|
}
|
||||||
else if (memcmp(code, kMsgCNoop, 4) == 0) {
|
else if (memcmp(code, kMsgCNoop, 4) == 0) {
|
||||||
// discard no-ops
|
// discard no-ops
|
||||||
|
LOG((CLOG_DEBUG2 "no-op from", getName().c_str()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (memcmp(code, kMsgCClipboard, 4) == 0) {
|
else if (memcmp(code, kMsgCClipboard, 4) == 0) {
|
||||||
|
@ -168,7 +171,7 @@ void
|
||||||
CClientProxy1_0::setClipboard(ClipboardID id, const CString& data)
|
CClientProxy1_0::setClipboard(ClipboardID id, const CString& data)
|
||||||
{
|
{
|
||||||
// ignore if this clipboard is already clean
|
// ignore if this clipboard is already clean
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
if (m_clipboardDirty[id]) {
|
if (m_clipboardDirty[id]) {
|
||||||
// this clipboard is now clean
|
// this clipboard is now clean
|
||||||
m_clipboardDirty[id] = false;
|
m_clipboardDirty[id] = false;
|
||||||
|
@ -185,14 +188,14 @@ CClientProxy1_0::grabClipboard(ClipboardID id)
|
||||||
CProtocolUtil::writef(getOutputStream(), kMsgCClipboard, id, 0);
|
CProtocolUtil::writef(getOutputStream(), kMsgCClipboard, id, 0);
|
||||||
|
|
||||||
// this clipboard is now dirty
|
// this clipboard is now dirty
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
m_clipboardDirty[id] = true;
|
m_clipboardDirty[id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::setClipboardDirty(ClipboardID id, bool dirty)
|
CClientProxy1_0::setClipboardDirty(ClipboardID id, bool dirty)
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
m_clipboardDirty[id] = dirty;
|
m_clipboardDirty[id] = dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +260,11 @@ CClientProxy1_0::resetOptions()
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG1 "send reset options to \"%s\"", getName().c_str()));
|
LOG((CLOG_DEBUG1 "send reset options to \"%s\"", getName().c_str()));
|
||||||
CProtocolUtil::writef(getOutputStream(), kMsgCResetOptions);
|
CProtocolUtil::writef(getOutputStream(), kMsgCResetOptions);
|
||||||
|
|
||||||
|
// reset heart rate and death
|
||||||
|
CLock lock(getMutex());
|
||||||
|
m_heartRate = kHeartRate;
|
||||||
|
m_heartDeath = kHeartRate * kHeartBeatsUntilDeath;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -264,19 +272,31 @@ CClientProxy1_0::setOptions(const COptionsList& options)
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG1 "send set options to \"%s\" size=%d", getName().c_str(), options.size()));
|
LOG((CLOG_DEBUG1 "send set options to \"%s\" size=%d", getName().c_str(), options.size()));
|
||||||
CProtocolUtil::writef(getOutputStream(), kMsgDSetOptions, &options);
|
CProtocolUtil::writef(getOutputStream(), kMsgDSetOptions, &options);
|
||||||
|
|
||||||
|
// check options
|
||||||
|
CLock lock(getMutex());
|
||||||
|
for (UInt32 i = 0, n = options.size(); i < n; i += 2) {
|
||||||
|
if (options[i] == kOptionHeartbeat) {
|
||||||
|
m_heartRate = 1.0e-3 * static_cast<double>(options[i + 1]);
|
||||||
|
if (m_heartRate <= 0.0) {
|
||||||
|
m_heartRate = -1.0;
|
||||||
|
}
|
||||||
|
m_heartDeath = m_heartRate * kHeartBeatsUntilDeath;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SInt32
|
SInt32
|
||||||
CClientProxy1_0::getJumpZoneSize() const
|
CClientProxy1_0::getJumpZoneSize() const
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
return m_info.m_zoneSize;
|
return m_info.m_zoneSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
x = m_info.m_x;
|
x = m_info.m_x;
|
||||||
y = m_info.m_y;
|
y = m_info.m_y;
|
||||||
w = m_info.m_w;
|
w = m_info.m_w;
|
||||||
|
@ -292,7 +312,7 @@ CClientProxy1_0::getCursorPos(SInt32&, SInt32&) const
|
||||||
void
|
void
|
||||||
CClientProxy1_0::getCursorCenter(SInt32& x, SInt32& y) const
|
CClientProxy1_0::getCursorCenter(SInt32& x, SInt32& y) const
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
x = m_info.m_mx;
|
x = m_info.m_mx;
|
||||||
y = m_info.m_my;
|
y = m_info.m_my;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +321,7 @@ void
|
||||||
CClientProxy1_0::recvInfo(bool notify)
|
CClientProxy1_0::recvInfo(bool notify)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
CLock lock(&m_mutex);
|
CLock lock(getMutex());
|
||||||
|
|
||||||
// parse the message
|
// parse the message
|
||||||
SInt16 x, y, w, h, zoneSize, mx, my;
|
SInt16 x, y, w, h, zoneSize, mx, my;
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "CClientProxy.h"
|
#include "CClientProxy.h"
|
||||||
#include "ProtocolTypes.h"
|
#include "ProtocolTypes.h"
|
||||||
#include "CMutex.h"
|
|
||||||
|
|
||||||
//! Proxy for client implementing protocol version 1.0
|
//! Proxy for client implementing protocol version 1.0
|
||||||
class CClientProxy1_0 : public CClientProxy {
|
class CClientProxy1_0 : public CClientProxy {
|
||||||
|
@ -60,9 +59,10 @@ private:
|
||||||
void recvGrabClipboard();
|
void recvGrabClipboard();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CMutex m_mutex;
|
|
||||||
CClientInfo m_info;
|
CClientInfo m_info;
|
||||||
bool m_clipboardDirty[kClipboardEnd];
|
bool m_clipboardDirty[kClipboardEnd];
|
||||||
|
double m_heartRate;
|
||||||
|
double m_heartDeath;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "XSocket.h"
|
#include "XSocket.h"
|
||||||
#include "stdistream.h"
|
#include "stdistream.h"
|
||||||
#include "stdostream.h"
|
#include "stdostream.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
//
|
//
|
||||||
// CConfig
|
// CConfig
|
||||||
|
@ -504,31 +505,57 @@ CConfig::readLine(std::istream& s, CString& line)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
OptionValue
|
||||||
CConfig::parseBoolean(const CString& arg)
|
CConfig::parseBoolean(const CString& arg)
|
||||||
{
|
{
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "true"))
|
if (CStringUtil::CaselessCmp::equal(arg, "true")) {
|
||||||
return true;
|
return static_cast<OptionValue>(true);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "false"))
|
}
|
||||||
return false;
|
if (CStringUtil::CaselessCmp::equal(arg, "false")) {
|
||||||
|
return static_cast<OptionValue>(false);
|
||||||
|
}
|
||||||
throw XConfigRead("invalid argument");
|
throw XConfigRead("invalid argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionValue
|
||||||
|
CConfig::parseInt(const CString& arg)
|
||||||
|
{
|
||||||
|
const char* s = arg.c_str();
|
||||||
|
char* end;
|
||||||
|
long tmp = strtol(s, &end, 10);
|
||||||
|
if (*end != '\0') {
|
||||||
|
// invalid characters
|
||||||
|
throw XConfigRead("invalid argument");
|
||||||
|
}
|
||||||
|
OptionValue value = static_cast<OptionValue>(tmp);
|
||||||
|
if (value != tmp) {
|
||||||
|
// out of range
|
||||||
|
throw XConfigRead("argument out of range");
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
OptionValue
|
OptionValue
|
||||||
CConfig::parseModifierKey(const CString& arg)
|
CConfig::parseModifierKey(const CString& arg)
|
||||||
{
|
{
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "shift"))
|
if (CStringUtil::CaselessCmp::equal(arg, "shift")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDShift);
|
return static_cast<OptionValue>(kKeyModifierIDShift);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "ctrl"))
|
}
|
||||||
|
if (CStringUtil::CaselessCmp::equal(arg, "ctrl")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDControl);
|
return static_cast<OptionValue>(kKeyModifierIDControl);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "alt"))
|
}
|
||||||
|
if (CStringUtil::CaselessCmp::equal(arg, "alt")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDAlt);
|
return static_cast<OptionValue>(kKeyModifierIDAlt);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "meta"))
|
}
|
||||||
|
if (CStringUtil::CaselessCmp::equal(arg, "meta")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDMeta);
|
return static_cast<OptionValue>(kKeyModifierIDMeta);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "super"))
|
}
|
||||||
|
if (CStringUtil::CaselessCmp::equal(arg, "super")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDSuper);
|
return static_cast<OptionValue>(kKeyModifierIDSuper);
|
||||||
if (CStringUtil::CaselessCmp::equal(arg, "none"))
|
}
|
||||||
|
if (CStringUtil::CaselessCmp::equal(arg, "none")) {
|
||||||
return static_cast<OptionValue>(kKeyModifierIDNull);
|
return static_cast<OptionValue>(kKeyModifierIDNull);
|
||||||
|
}
|
||||||
throw XConfigRead("invalid argument");
|
throw XConfigRead("invalid argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,10 +583,13 @@ CConfig::getOptionName(OptionID id)
|
||||||
if (id == kOptionModifierMapForSuper) {
|
if (id == kOptionModifierMapForSuper) {
|
||||||
return "super";
|
return "super";
|
||||||
}
|
}
|
||||||
|
if (id == kOptionHeartbeat) {
|
||||||
|
return "heartbeat";
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
CString
|
||||||
CConfig::getOptionValue(OptionID id, OptionValue value)
|
CConfig::getOptionValue(OptionID id, OptionValue value)
|
||||||
{
|
{
|
||||||
if (id == kOptionHalfDuplexCapsLock ||
|
if (id == kOptionHalfDuplexCapsLock ||
|
||||||
|
@ -591,6 +621,9 @@ CConfig::getOptionValue(OptionID id, OptionValue value)
|
||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (id == kOptionHeartbeat) {
|
||||||
|
return CStringUtil::print("%d", value);
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -599,7 +632,7 @@ void
|
||||||
CConfig::readSection(std::istream& s)
|
CConfig::readSection(std::istream& s)
|
||||||
{
|
{
|
||||||
static const char s_section[] = "section:";
|
static const char s_section[] = "section:";
|
||||||
static const char s_network[] = "network";
|
static const char s_options[] = "options";
|
||||||
static const char s_screens[] = "screens";
|
static const char s_screens[] = "screens";
|
||||||
static const char s_links[] = "links";
|
static const char s_links[] = "links";
|
||||||
static const char s_aliases[] = "aliases";
|
static const char s_aliases[] = "aliases";
|
||||||
|
@ -627,8 +660,8 @@ CConfig::readSection(std::istream& s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read section
|
// read section
|
||||||
if (name == s_network) {
|
if (name == s_options) {
|
||||||
readSectionNetwork(s);
|
readSectionOptions(s);
|
||||||
}
|
}
|
||||||
else if (name == s_screens) {
|
else if (name == s_screens) {
|
||||||
readSectionScreens(s);
|
readSectionScreens(s);
|
||||||
|
@ -645,7 +678,7 @@ CConfig::readSection(std::istream& s)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CConfig::readSectionNetwork(std::istream& s)
|
CConfig::readSectionOptions(std::istream& s)
|
||||||
{
|
{
|
||||||
CString line;
|
CString line;
|
||||||
CString name;
|
CString name;
|
||||||
|
@ -693,6 +726,9 @@ CConfig::readSectionNetwork(std::istream& s)
|
||||||
throw XConfigRead("invalid http argument");
|
throw XConfigRead("invalid http argument");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (name == "heartbeat") {
|
||||||
|
addOption("", kOptionHeartbeat, parseInt(value));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw XConfigRead("unknown argument");
|
throw XConfigRead("unknown argument");
|
||||||
}
|
}
|
||||||
|
@ -931,15 +967,28 @@ operator>>(std::istream& s, CConfig& config)
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& s, const CConfig& config)
|
operator<<(std::ostream& s, const CConfig& config)
|
||||||
{
|
{
|
||||||
// network section
|
// options section
|
||||||
s << "section: network" << std::endl;
|
s << "section: options" << std::endl;
|
||||||
|
const CConfig::CScreenOptions* options = config.getOptions("");
|
||||||
|
if (options != NULL && options->size() > 0) {
|
||||||
|
for (CConfig::CScreenOptions::const_iterator
|
||||||
|
option = options->begin();
|
||||||
|
option != options->end(); ++option) {
|
||||||
|
const char* name = CConfig::getOptionName(option->first);
|
||||||
|
CString value = CConfig::getOptionValue(option->first,
|
||||||
|
option->second);
|
||||||
|
if (name != NULL && !value.empty()) {
|
||||||
|
s << "\t" << name << " = " << value << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (config.m_synergyAddress.isValid()) {
|
if (config.m_synergyAddress.isValid()) {
|
||||||
s << "\taddress=" << config.m_synergyAddress.getHostname().c_str() <<
|
s << "\taddress = " <<
|
||||||
std::endl;
|
config.m_synergyAddress.getHostname().c_str() << std::endl;
|
||||||
}
|
}
|
||||||
if (config.m_httpAddress.isValid()) {
|
if (config.m_httpAddress.isValid()) {
|
||||||
s << "\thttp=" << config.m_httpAddress.getHostname().c_str() <<
|
s << "\thttp = " <<
|
||||||
std::endl;
|
config.m_httpAddress.getHostname().c_str() << std::endl;
|
||||||
}
|
}
|
||||||
s << "end" << std::endl;
|
s << "end" << std::endl;
|
||||||
|
|
||||||
|
@ -954,9 +1003,9 @@ operator<<(std::ostream& s, const CConfig& config)
|
||||||
option = options->begin();
|
option = options->begin();
|
||||||
option != options->end(); ++option) {
|
option != options->end(); ++option) {
|
||||||
const char* name = CConfig::getOptionName(option->first);
|
const char* name = CConfig::getOptionName(option->first);
|
||||||
const char* value = CConfig::getOptionValue(option->first,
|
CString value = CConfig::getOptionValue(option->first,
|
||||||
option->second);
|
option->second);
|
||||||
if (name != NULL && value != NULL) {
|
if (name != NULL && !value.empty()) {
|
||||||
s << "\t\t" << name << " = " << value << std::endl;
|
s << "\t\t" << name << " = " << value << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,12 +292,13 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool readLine(std::istream&, CString&);
|
static bool readLine(std::istream&, CString&);
|
||||||
static bool parseBoolean(const CString&);
|
static OptionValue parseBoolean(const CString&);
|
||||||
|
static OptionValue parseInt(const CString&);
|
||||||
static OptionValue parseModifierKey(const CString&);
|
static OptionValue parseModifierKey(const CString&);
|
||||||
static const char* getOptionName(OptionID);
|
static const char* getOptionName(OptionID);
|
||||||
static const char* getOptionValue(OptionID, OptionValue);
|
static CString getOptionValue(OptionID, OptionValue);
|
||||||
void readSection(std::istream&);
|
void readSection(std::istream&);
|
||||||
void readSectionNetwork(std::istream&);
|
void readSectionOptions(std::istream&);
|
||||||
void readSectionScreens(std::istream&);
|
void readSectionScreens(std::istream&);
|
||||||
void readSectionLinks(std::istream&);
|
void readSectionLinks(std::istream&);
|
||||||
void readSectionAliases(std::istream&);
|
void readSectionAliases(std::istream&);
|
||||||
|
|
|
@ -217,12 +217,29 @@ CServer::setConfig(const CConfig& config)
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
m_config = config;
|
m_config = config;
|
||||||
|
|
||||||
|
// process global options
|
||||||
|
const CConfig::CScreenOptions* options = m_config.getOptions("");
|
||||||
|
if (options != NULL && options->size() > 0) {
|
||||||
|
/*
|
||||||
|
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
||||||
|
index != options->end(); ++index) {
|
||||||
|
const OptionID id = index->first;
|
||||||
|
const OptionValue value = index->second;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
// tell primary screen about reconfiguration
|
// tell primary screen about reconfiguration
|
||||||
if (m_primaryClient != NULL) {
|
if (m_primaryClient != NULL) {
|
||||||
m_primaryClient->reconfigure(getActivePrimarySides());
|
m_primaryClient->reconfigure(getActivePrimarySides());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME -- tell all (connected) clients about current options
|
// tell all (connected) clients about current options
|
||||||
|
for (CClientList::const_iterator index = m_clients.begin();
|
||||||
|
index != m_clients.end(); ++index) {
|
||||||
|
IClient* client = index->second;
|
||||||
|
sendOptions(client);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1622,21 +1639,32 @@ CServer::sendOptions(IClient* client) const
|
||||||
{
|
{
|
||||||
// note -- must be locked on entry
|
// note -- must be locked on entry
|
||||||
|
|
||||||
// look up options for client. we're done if there aren't any.
|
COptionsList optionsList;
|
||||||
|
|
||||||
|
// look up options for client
|
||||||
const CConfig::CScreenOptions* options =
|
const CConfig::CScreenOptions* options =
|
||||||
m_config.getOptions(client->getName());
|
m_config.getOptions(client->getName());
|
||||||
if (options == NULL || options->size() == 0) {
|
if (options != NULL && options->size() > 0) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert options to a more convenient form for sending
|
// convert options to a more convenient form for sending
|
||||||
COptionsList optionsList;
|
|
||||||
optionsList.reserve(2 * options->size());
|
optionsList.reserve(2 * options->size());
|
||||||
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
||||||
index != options->end(); ++index) {
|
index != options->end(); ++index) {
|
||||||
optionsList.push_back(index->first);
|
optionsList.push_back(index->first);
|
||||||
optionsList.push_back(static_cast<UInt32>(index->second));
|
optionsList.push_back(static_cast<UInt32>(index->second));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// look up global options
|
||||||
|
options = m_config.getOptions("");
|
||||||
|
if (options != NULL && options->size() > 0) {
|
||||||
|
// convert options to a more convenient form for sending
|
||||||
|
optionsList.reserve(optionsList.size() + 2 * options->size());
|
||||||
|
for (CConfig::CScreenOptions::const_iterator index = options->begin();
|
||||||
|
index != options->end(); ++index) {
|
||||||
|
optionsList.push_back(index->first);
|
||||||
|
optionsList.push_back(static_cast<UInt32>(index->second));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// send the options
|
// send the options
|
||||||
client->setOptions(optionsList);
|
client->setOptions(optionsList);
|
||||||
|
|
|
@ -50,6 +50,7 @@ static const OptionID kOptionModifierMapForControl = OPTION_CODE("MMFC");
|
||||||
static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA");
|
static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA");
|
||||||
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM");
|
||||||
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR");
|
||||||
|
static const OptionID kOptionHeartbeat = OPTION_CODE("HART");
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
#undef OPTION_CODE
|
#undef OPTION_CODE
|
||||||
|
|
|
@ -31,8 +31,8 @@ static const UInt32 kMaxHelloLength = 1024;
|
||||||
// heartbeat.
|
// heartbeat.
|
||||||
static const double kHeartRate = -1.0;
|
static const double kHeartRate = -1.0;
|
||||||
|
|
||||||
// time without a heartbeat that constitutes death
|
// number of skipped heartbeats that constitutes death
|
||||||
static const double kHeartDeath = 3.0 * kHeartRate;
|
static const double kHeartBeatsUntilDeath = 3.0;
|
||||||
|
|
||||||
// direction constants
|
// direction constants
|
||||||
enum EDirection {
|
enum EDirection {
|
||||||
|
|
Loading…
Reference in New Issue