added logging facility and added a bunch of log messages.
This commit is contained in:
parent
23f948d55a
commit
1ed2b43e13
|
@ -13,7 +13,7 @@ RMR = /bin/rm -rf
|
|||
#
|
||||
# compiler options
|
||||
#
|
||||
GCXXDEFS = -D_POSIX_C_SOURCE=199309
|
||||
GCXXDEFS = -D_XOPEN_SOURCE=500
|
||||
GCXXINCS = -I$(DEPTH)/include -I/usr/X11R6/include
|
||||
GCXXOPTS = -Wall -W -fexceptions -fno-rtti
|
||||
CXXOPTIMIZER = -g
|
||||
|
|
|
@ -13,6 +13,7 @@ LCXXINCS = \
|
|||
$(NULL)
|
||||
CXXFILES = \
|
||||
XBase.cpp \
|
||||
CLog.cpp \
|
||||
CFunctionJob.cpp \
|
||||
CStopwatch.cpp \
|
||||
$(NULL)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "ProtocolTypes.h"
|
||||
#include "CTimerThread.h"
|
||||
#include "XSynergy.h"
|
||||
#include <stdio.h>
|
||||
#include "CLog.h"
|
||||
#include <memory>
|
||||
|
||||
//
|
||||
|
@ -29,6 +29,8 @@ CClient::~CClient()
|
|||
#include "CXWindowsSecondaryScreen.h"
|
||||
void CClient::run(const CNetworkAddress& serverAddress)
|
||||
{
|
||||
log((CLOG_DEBUG "starting client \"%s\"", m_name.c_str()));
|
||||
|
||||
std::auto_ptr<ISocket> socket;
|
||||
std::auto_ptr<IInputStream> input;
|
||||
std::auto_ptr<IOutputStream> output;
|
||||
|
@ -37,8 +39,10 @@ void CClient::run(const CNetworkAddress& serverAddress)
|
|||
CTimerThread timer(30.0); // FIXME -- timeout in member
|
||||
|
||||
// create socket and attempt to connect to server
|
||||
log((CLOG_DEBUG "connecting to server"));
|
||||
socket.reset(new CTCPSocket()); // FIXME -- use factory
|
||||
socket->connect(serverAddress);
|
||||
log((CLOG_INFO "connected to server"));
|
||||
|
||||
// get the input and output streams
|
||||
IInputStream* srcInput = socket->getInputStream();
|
||||
|
@ -59,16 +63,19 @@ void CClient::run(const CNetworkAddress& serverAddress)
|
|||
output.reset(new COutputPacketStream(srcOutput, true));
|
||||
|
||||
// wait for hello from server
|
||||
log((CLOG_DEBUG "wait for hello"));
|
||||
SInt32 major, minor;
|
||||
CProtocolUtil::readf(input.get(), "Synergy%2i%2i", &major, &minor);
|
||||
|
||||
// check versions
|
||||
log((CLOG_DEBUG "got hello version %d.%d", major, minor));
|
||||
if (major < kMajorVersion ||
|
||||
(major == kMajorVersion && minor < kMinorVersion)) {
|
||||
throw XIncompatibleClient(major, minor);
|
||||
}
|
||||
|
||||
// say hello back
|
||||
log((CLOG_DEBUG "say hello version %d.%d", kMajorVersion, kMinorVersion));
|
||||
CProtocolUtil::writef(output.get(), "Synergy%2i%2i%s",
|
||||
kMajorVersion, kMinorVersion,
|
||||
m_name.size(), m_name.data());
|
||||
|
@ -78,27 +85,27 @@ void CClient::run(const CNetworkAddress& serverAddress)
|
|||
m_output = output.get();
|
||||
}
|
||||
catch (XIncompatibleClient& e) {
|
||||
fprintf(stderr, "incompatible server version (%d.%d)\n",
|
||||
e.getMajor(), e.getMinor());
|
||||
log((CLOG_ERR "server has incompatible version %d.%d", e.getMajor(), e.getMinor()));
|
||||
return;
|
||||
}
|
||||
catch (XThread&) {
|
||||
fprintf(stderr, "connection timed out\n");
|
||||
log((CLOG_ERR "connection timed out"));
|
||||
throw;
|
||||
}
|
||||
catch (XBase& e) {
|
||||
fprintf(stderr, "connection failed: %s\n", e.what());
|
||||
log((CLOG_ERR "connection failed: %s", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// connect to screen
|
||||
std::auto_ptr<CScreenCleaner> screenCleaner;
|
||||
try {
|
||||
log((CLOG_DEBUG "creating secondary screen"));
|
||||
m_screen = new CXWindowsSecondaryScreen;
|
||||
screenCleaner.reset(new CScreenCleaner(this, m_screen));
|
||||
}
|
||||
catch (XBase& e) {
|
||||
fprintf(stderr, "cannot open screen: %s\n", e.what());
|
||||
log((CLOG_ERR "cannot open screen: %s", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -106,21 +113,24 @@ void CClient::run(const CNetworkAddress& serverAddress)
|
|||
// handle messages from server
|
||||
for (;;) {
|
||||
// wait for reply
|
||||
log((CLOG_DEBUG "waiting for message"));
|
||||
UInt8 code[4];
|
||||
UInt32 n = input->read(code, 4);
|
||||
|
||||
// verify we got an entire code
|
||||
if (n == 0) {
|
||||
log((CLOG_NOTE "server disconnected"));
|
||||
// server hungup
|
||||
break;
|
||||
}
|
||||
if (n != 4) {
|
||||
// client sent an incomplete message
|
||||
fprintf(stderr, "incomplete message from server\n");
|
||||
log((CLOG_ERR "incomplete message from server"));
|
||||
break;
|
||||
}
|
||||
|
||||
// parse message
|
||||
log((CLOG_DEBUG "msg from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
|
||||
if (memcmp(code, kMsgDMouseMove, 4) == 0) {
|
||||
onMouseMove();
|
||||
}
|
||||
|
@ -169,20 +179,22 @@ void CClient::run(const CNetworkAddress& serverAddress)
|
|||
}
|
||||
else {
|
||||
// unknown message
|
||||
fprintf(stderr, "unknown message from server\n");
|
||||
log((CLOG_ERR "unknown message from server"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (XBase& e) {
|
||||
fprintf(stderr, "error: %s\n", e.what());
|
||||
log((CLOG_ERR "error: %s", e.what()));
|
||||
return;
|
||||
}
|
||||
|
||||
// done with screen
|
||||
log((CLOG_DEBUG "destroying secondary screen"));
|
||||
screenCleaner.reset();
|
||||
|
||||
// done with socket
|
||||
log((CLOG_DEBUG "disconnecting from server"));
|
||||
socket->close();
|
||||
}
|
||||
|
||||
|
@ -215,6 +227,7 @@ void CClient::onQueryInfo()
|
|||
SInt32 w, h;
|
||||
m_screen->getSize(&w, &h);
|
||||
SInt32 zoneSize = m_screen->getJumpZoneSize();
|
||||
log((CLOG_DEBUG "sending info size=%d,%d zone=%d", w, h, zoneSize));
|
||||
CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize);
|
||||
}
|
||||
|
||||
|
|
|
@ -87,3 +87,9 @@ CString CScreenMap::getNeighbor(const CString& srcName,
|
|||
// return connection
|
||||
return index->second.m_neighbor[srcSide - kFirstDirection];
|
||||
}
|
||||
|
||||
const char* CScreenMap::dirName(EDirection dir)
|
||||
{
|
||||
static const char* s_name[] = { "left", "right", "top", "bottom" };
|
||||
return s_name[dir - kFirstDirection];
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ class CScreenMap {
|
|||
// if there is no neighbor in that direction.
|
||||
CString getNeighbor(const CString&, EDirection) const throw();
|
||||
|
||||
// get the name of a direction (for debugging)
|
||||
static const char* dirName(EDirection);
|
||||
|
||||
private:
|
||||
class CCell {
|
||||
public:
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "CTimerThread.h"
|
||||
#include "CStopwatch.h"
|
||||
#include "TMethodJob.h"
|
||||
#include <stdio.h>
|
||||
#include "CLog.h"
|
||||
#include <assert.h>
|
||||
#include <memory>
|
||||
|
||||
|
@ -38,6 +38,8 @@ CServer::~CServer()
|
|||
void CServer::run()
|
||||
{
|
||||
try {
|
||||
log((CLOG_NOTE "starting server"));
|
||||
|
||||
// connect to primary screen
|
||||
openPrimaryScreen();
|
||||
|
||||
|
@ -48,23 +50,27 @@ void CServer::run()
|
|||
// FIXME
|
||||
|
||||
// wait until done
|
||||
log((CLOG_DEBUG "waiting for quit"));
|
||||
CLock lock(&m_mutex);
|
||||
while (m_done == false) {
|
||||
m_done.wait();
|
||||
}
|
||||
|
||||
// clean up
|
||||
log((CLOG_DEBUG "stopping server"));
|
||||
closePrimaryScreen();
|
||||
cleanupThreads();
|
||||
}
|
||||
catch (XBase& e) {
|
||||
fprintf(stderr, "server error: %s\n", e.what());
|
||||
log((CLOG_ERR "server error: %s\n", e.what()));
|
||||
|
||||
// clean up
|
||||
closePrimaryScreen();
|
||||
cleanupThreads();
|
||||
}
|
||||
catch (...) {
|
||||
log((CLOG_DEBUG "server shutdown"));
|
||||
|
||||
// clean up
|
||||
closePrimaryScreen();
|
||||
cleanupThreads();
|
||||
|
@ -108,6 +114,7 @@ void CServer::setInfo(const CString& client,
|
|||
info->m_width = w;
|
||||
info->m_height = h;
|
||||
info->m_zoneSize = zoneSize;
|
||||
log((CLOG_NOTE "client \"%s\" size=%dx%d zone=%d", client.c_str(), w, h, zoneSize));
|
||||
}
|
||||
|
||||
bool CServer::onCommandKey(KeyID /*id*/,
|
||||
|
@ -118,6 +125,7 @@ bool CServer::onCommandKey(KeyID /*id*/,
|
|||
|
||||
void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
|
||||
{
|
||||
log((CLOG_DEBUG "onKeyDown id=%d mask=0x%04x", id, mask));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// handle command keys
|
||||
|
@ -133,6 +141,7 @@ void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
|
|||
|
||||
void CServer::onKeyUp(KeyID id, KeyModifierMask mask)
|
||||
{
|
||||
log((CLOG_DEBUG "onKeyUp id=%d mask=0x%04x", id, mask));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// handle command keys
|
||||
|
@ -148,6 +157,7 @@ void CServer::onKeyUp(KeyID id, KeyModifierMask mask)
|
|||
|
||||
void CServer::onKeyRepeat(KeyID id, KeyModifierMask mask)
|
||||
{
|
||||
log((CLOG_DEBUG "onKeyRepeat id=%d mask=0x%04x", id, mask));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// handle command keys
|
||||
|
@ -164,6 +174,7 @@ void CServer::onKeyRepeat(KeyID id, KeyModifierMask mask)
|
|||
|
||||
void CServer::onMouseDown(ButtonID id)
|
||||
{
|
||||
log((CLOG_DEBUG "onMouseDown id=%d", id));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// relay
|
||||
|
@ -174,6 +185,7 @@ void CServer::onMouseDown(ButtonID id)
|
|||
|
||||
void CServer::onMouseUp(ButtonID id)
|
||||
{
|
||||
log((CLOG_DEBUG "onMouseUp id=%d", id));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// relay
|
||||
|
@ -184,6 +196,8 @@ void CServer::onMouseUp(ButtonID id)
|
|||
|
||||
void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
|
||||
{
|
||||
log((CLOG_DEBUG "onMouseMovePrimary %d,%d", x, y));
|
||||
|
||||
// mouse move on primary (server's) screen
|
||||
assert(m_active != NULL);
|
||||
assert(m_active->m_protocol == NULL);
|
||||
|
@ -198,18 +212,22 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
|
|||
if (x < m_active->m_zoneSize) {
|
||||
x -= m_active->m_zoneSize;
|
||||
dir = CScreenMap::kLeft;
|
||||
log((CLOG_DEBUG "switch to left"));
|
||||
}
|
||||
else if (x >= m_active->m_width - m_active->m_zoneSize) {
|
||||
x += m_active->m_zoneSize;
|
||||
dir = CScreenMap::kRight;
|
||||
log((CLOG_DEBUG "switch to right"));
|
||||
}
|
||||
else if (y < m_active->m_zoneSize) {
|
||||
y -= m_active->m_zoneSize;
|
||||
dir = CScreenMap::kTop;
|
||||
log((CLOG_DEBUG "switch to top"));
|
||||
}
|
||||
else if (y >= m_active->m_height - m_active->m_zoneSize) {
|
||||
y += m_active->m_zoneSize;
|
||||
dir = CScreenMap::kBottom;
|
||||
log((CLOG_DEBUG "switch to bottom"));
|
||||
}
|
||||
else {
|
||||
// still on local screen
|
||||
|
@ -233,6 +251,8 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
|
|||
|
||||
void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
||||
{
|
||||
log((CLOG_DEBUG "onMouseMoveSecondary %+d,%+d", dx, dy));
|
||||
|
||||
// mouse move on secondary (client's) screen
|
||||
assert(m_active != NULL);
|
||||
assert(m_active->m_protocol != NULL);
|
||||
|
@ -264,8 +284,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
|||
|
||||
// get neighbor if we should switch
|
||||
if (newScreen == NULL) {
|
||||
// TRACE(("leave %s on %s", m_activeScreen->getName().c_str(),
|
||||
// s_dirName[dir]));
|
||||
log((CLOG_DEBUG "leave \"%s\" on %s", m_active->m_name.c_str(), CScreenMap::dirName(dir)));
|
||||
|
||||
SInt32 x = m_x, y = m_y;
|
||||
newScreen = getNeighbor(m_active, dir, x, y);
|
||||
|
@ -290,7 +309,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
|||
}
|
||||
else {
|
||||
// clamp to edge when locked
|
||||
// TRACE(("clamp to %s", m_activeScreen->getName().c_str()));
|
||||
log((CLOG_DEBUG "clamp to \"%s\"", m_active->m_name.c_str()));
|
||||
if (m_x < 0)
|
||||
m_x = 0;
|
||||
else if (m_x > m_active->m_width - 1)
|
||||
|
@ -305,8 +324,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
|||
if (newScreen == NULL || newScreen == m_active) {
|
||||
// do nothing if mouse didn't move
|
||||
if (m_x != xOld || m_y != yOld) {
|
||||
// TRACE(("move on %s to %d,%d",
|
||||
// m_activeScreen->getName().c_str(), m_x, m_y));
|
||||
log((CLOG_DEBUG "move on %s to %d,%d", m_active->m_name.c_str(), m_x, m_y));
|
||||
m_active->m_protocol->sendMouseMove(m_x, m_y);
|
||||
}
|
||||
}
|
||||
|
@ -319,6 +337,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
|
|||
|
||||
void CServer::onMouseWheel(SInt32 delta)
|
||||
{
|
||||
log((CLOG_DEBUG "onMouseWheel %+d", delta));
|
||||
assert(m_active != NULL);
|
||||
|
||||
// relay
|
||||
|
@ -340,8 +359,7 @@ void CServer::switchScreen(CScreenInfo* dst,
|
|||
assert(x >= 0 && y >= 0 && x < dst->m_width && y < dst->m_height);
|
||||
assert(m_active != NULL);
|
||||
|
||||
// TRACE(("switch %s to %s at %d,%d", m_active->m_name.c_str(),
|
||||
// dst->m_name.c_str(), x, y));
|
||||
log((CLOG_NOTE "switch from \"%s\" to \"%s\" at %d,%d", m_active->m_name.c_str(), dst->m_name.c_str(), x, y));
|
||||
|
||||
// wrapping means leaving the active screen and entering it again.
|
||||
// since that's a waste of time we skip that and just warp the
|
||||
|
@ -387,22 +405,27 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
|
|||
|
||||
CString srcName = src->m_name;
|
||||
assert(!srcName.empty());
|
||||
log((CLOG_DEBUG "find neighbor on %s of \"%s\"", CScreenMap::dirName(dir), srcName.c_str()));
|
||||
for (;;) {
|
||||
// look up name of neighbor
|
||||
const CString dstName(m_screenMap.getNeighbor(srcName, dir));
|
||||
|
||||
// if nothing in that direction then return NULL
|
||||
if (dstName.empty())
|
||||
if (dstName.empty()) {
|
||||
log((CLOG_DEBUG "no neighbor on %s of \"%s\"", CScreenMap::dirName(dir), srcName.c_str()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// look up neighbor cell. if the screen is connected then
|
||||
// we can stop. otherwise we skip over an unconnected
|
||||
// screen.
|
||||
CScreenList::const_iterator index = m_screens.find(dstName);
|
||||
if (index != m_screens.end()) {
|
||||
log((CLOG_DEBUG "\"%s\" is on %s of \"%s\"", dstName.c_str(), CScreenMap::dirName(dir), srcName.c_str()));
|
||||
return index->second;
|
||||
}
|
||||
|
||||
log((CLOG_DEBUG "ignored \"%s\" on %s of \"%s\"", dstName.c_str(), CScreenMap::dirName(dir), srcName.c_str()));
|
||||
srcName = dstName;
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +454,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
|
|||
if (x >= 0) {
|
||||
break;
|
||||
}
|
||||
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
|
||||
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
|
||||
dst = getNeighbor(lastGoodScreen, srcSide);
|
||||
}
|
||||
break;
|
||||
|
@ -445,7 +468,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
|
|||
if (x < w) {
|
||||
break;
|
||||
}
|
||||
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
|
||||
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
|
||||
dst = getNeighbor(lastGoodScreen, srcSide);
|
||||
}
|
||||
break;
|
||||
|
@ -459,7 +482,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
|
|||
if (y >= 0) {
|
||||
break;
|
||||
}
|
||||
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
|
||||
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
|
||||
dst = getNeighbor(lastGoodScreen, srcSide);
|
||||
}
|
||||
break;
|
||||
|
@ -473,7 +496,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
|
|||
if (y < h) {
|
||||
break;
|
||||
}
|
||||
// TRACE(("skipping over screen %s", dst->m_name.c_str()));
|
||||
log((CLOG_DEBUG "skipping over screen %s", dst->m_name.c_str()));
|
||||
dst = getNeighbor(lastGoodScreen, srcSide);
|
||||
}
|
||||
break;
|
||||
|
@ -548,6 +571,8 @@ void CServer::mapPosition(CScreenInfo* src,
|
|||
#include "CTCPListenSocket.h"
|
||||
void CServer::acceptClients(void*)
|
||||
{
|
||||
log((CLOG_DEBUG "starting to wait for clients"));
|
||||
|
||||
// add this thread to the list of threads to cancel. remove from
|
||||
// list in d'tor.
|
||||
CCleanupNote cleanupNote(this);
|
||||
|
@ -564,25 +589,30 @@ void CServer::acceptClients(void*)
|
|||
CNetworkAddress addr(50001 /* FIXME -- m_port */);
|
||||
for (;;) {
|
||||
try {
|
||||
log((CLOG_DEBUG "binding listen socket"));
|
||||
listen->bind(addr);
|
||||
break;
|
||||
}
|
||||
catch (XSocketAddressInUse&) {
|
||||
// give up if we've waited too long
|
||||
if (timer.getTime() >= m_bindTimeout) {
|
||||
log((CLOG_DEBUG "waited too long to bind, giving up"));
|
||||
throw;
|
||||
}
|
||||
|
||||
// wait a bit before retrying
|
||||
log((CLOG_DEBUG "bind failed; waiting to retry"));
|
||||
CThread::sleep(5.0);
|
||||
}
|
||||
}
|
||||
|
||||
// accept connections and begin processing them
|
||||
log((CLOG_DEBUG "waiting for client connections"));
|
||||
for (;;) {
|
||||
// accept connection
|
||||
CThread::testCancel();
|
||||
ISocket* socket = listen->accept();
|
||||
log((CLOG_NOTE "accepted client connection"));
|
||||
CThread::testCancel();
|
||||
|
||||
// start handshake thread
|
||||
|
@ -591,13 +621,15 @@ void CServer::acceptClients(void*)
|
|||
}
|
||||
}
|
||||
catch (XBase& e) {
|
||||
fprintf(stderr, "cannot listen for clients: %s\n", e.what());
|
||||
log((CLOG_ERR "cannot listen for clients: %s", e.what()));
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
void CServer::handshakeClient(void* vsocket)
|
||||
{
|
||||
log((CLOG_DEBUG "negotiating with new client"));
|
||||
|
||||
// get the socket pointer from the argument
|
||||
assert(vsocket != NULL);
|
||||
std::auto_ptr<ISocket> socket(reinterpret_cast<ISocket*>(vsocket));
|
||||
|
@ -638,11 +670,13 @@ void CServer::handshakeClient(void* vsocket)
|
|||
static const UInt32 maxHelloLen = 1024;
|
||||
|
||||
// say hello
|
||||
log((CLOG_DEBUG "saying hello"));
|
||||
CProtocolUtil::writef(output.get(), "Synergy%2i%2i",
|
||||
kMajorVersion, kMinorVersion);
|
||||
output->flush();
|
||||
|
||||
// wait for the reply
|
||||
log((CLOG_DEBUG "waiting for hello reply"));
|
||||
UInt32 n = input->getSize();
|
||||
if (n > maxHelloLen) {
|
||||
throw XBadClient();
|
||||
|
@ -651,6 +685,7 @@ void CServer::handshakeClient(void* vsocket)
|
|||
// get and parse the reply to hello
|
||||
SInt32 major, minor;
|
||||
try {
|
||||
log((CLOG_DEBUG "parsing hello reply"));
|
||||
CProtocolUtil::readf(input.get(), "Synergy%2i%2i%s",
|
||||
&major, &minor, &name);
|
||||
}
|
||||
|
@ -662,6 +697,7 @@ void CServer::handshakeClient(void* vsocket)
|
|||
}
|
||||
|
||||
// create a protocol interpreter for the version
|
||||
log((CLOG_DEBUG "creating interpreter for client %s version %d.%d", name.c_str(), major, minor));
|
||||
protocol.reset(CServerProtocol::create(major, minor,
|
||||
this, name, input.get(), output.get()));
|
||||
|
||||
|
@ -670,28 +706,28 @@ void CServer::handshakeClient(void* vsocket)
|
|||
name, protocol.get()));
|
||||
|
||||
// ask and wait for the client's info
|
||||
log((CLOG_DEBUG "waiting for info for client %s", name.c_str()));
|
||||
protocol->queryInfo();
|
||||
}
|
||||
|
||||
// handle messages from client. returns when the client
|
||||
// disconnects.
|
||||
log((CLOG_NOTE "client %s is connected", name.c_str()));
|
||||
protocol->run();
|
||||
}
|
||||
catch (XIncompatibleClient& e) {
|
||||
// client is incompatible
|
||||
fprintf(stderr, "client is incompatible (%s, %d.%d)\n",
|
||||
name.c_str(), e.getMajor(), e.getMinor());
|
||||
log((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
|
||||
// FIXME -- could print network address if socket had suitable method
|
||||
}
|
||||
catch (XBadClient&) {
|
||||
// client not behaving
|
||||
fprintf(stderr, "protocol error from client %s\n", name.c_str());
|
||||
log((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
|
||||
// FIXME -- could print network address if socket had suitable method
|
||||
}
|
||||
catch (XBase& e) {
|
||||
// misc error
|
||||
fprintf(stderr, "error communicating with client %s: %s\n",
|
||||
name.c_str(), e.what());
|
||||
log((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
|
||||
// FIXME -- could print network address if socket had suitable method
|
||||
}
|
||||
}
|
||||
|
@ -710,7 +746,9 @@ void CServer::openPrimaryScreen()
|
|||
assert(m_primary == NULL);
|
||||
|
||||
// open screen
|
||||
log((CLOG_DEBUG "creating primary screen"));
|
||||
m_primary = new CXWindowsPrimaryScreen;
|
||||
log((CLOG_DEBUG "opening primary screen"));
|
||||
m_primary->open(this);
|
||||
|
||||
// add connection
|
||||
|
@ -719,6 +757,7 @@ void CServer::openPrimaryScreen()
|
|||
// update info
|
||||
m_primary->getSize(&m_active->m_width, &m_active->m_height);
|
||||
m_active->m_zoneSize = m_primary->getJumpZoneSize();
|
||||
log((CLOG_NOTE "server size=%dx%d zone=%d", m_active->m_width, m_active->m_height, m_active->m_zoneSize));
|
||||
// FIXME -- need way for primary screen to call us back
|
||||
}
|
||||
|
||||
|
@ -731,6 +770,7 @@ void CServer::closePrimaryScreen() throw()
|
|||
|
||||
// close the primary screen
|
||||
try {
|
||||
log((CLOG_DEBUG "closing primary screen"));
|
||||
m_primary->close();
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -738,6 +778,7 @@ void CServer::closePrimaryScreen() throw()
|
|||
}
|
||||
|
||||
// clean up
|
||||
log((CLOG_DEBUG "destroying primary screen"));
|
||||
delete m_primary;
|
||||
m_primary = NULL;
|
||||
}
|
||||
|
@ -763,6 +804,7 @@ void CServer::removeCleanupThread(const CThread& thread)
|
|||
|
||||
void CServer::cleanupThreads() throw()
|
||||
{
|
||||
log((CLOG_DEBUG "cleaning up threads"));
|
||||
m_mutex.lock();
|
||||
while (m_cleanupList.begin() != m_cleanupList.end()) {
|
||||
// get the next thread and cancel it
|
||||
|
@ -778,11 +820,13 @@ void CServer::cleanupThreads() throw()
|
|||
|
||||
// FIXME -- delete remaining threads from list
|
||||
m_mutex.unlock();
|
||||
log((CLOG_DEBUG "cleaned up threads"));
|
||||
}
|
||||
|
||||
CServer::CScreenInfo* CServer::addConnection(
|
||||
const CString& name, IServerProtocol* protocol)
|
||||
{
|
||||
log((CLOG_DEBUG "adding connection \"%s\"", name.c_str()));
|
||||
CLock lock(&m_mutex);
|
||||
assert(m_screens.count(name) == 0);
|
||||
CScreenInfo* newScreen = new CScreenInfo(name, protocol);
|
||||
|
@ -792,6 +836,7 @@ CServer::CScreenInfo* CServer::addConnection(
|
|||
|
||||
void CServer::removeConnection(const CString& name)
|
||||
{
|
||||
log((CLOG_DEBUG "removing connection \"%s\"", name.c_str()));
|
||||
CLock lock(&m_mutex);
|
||||
CScreenList::iterator index = m_screens.find(name);
|
||||
assert(index == m_screens.end());
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CProtocolUtil.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "IInputStream.h"
|
||||
#include "CLog.h"
|
||||
#include <string.h>
|
||||
|
||||
//
|
||||
|
@ -40,6 +41,7 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
|
|||
}
|
||||
|
||||
// parse message
|
||||
log((CLOG_DEBUG "msg from \"%s\": %c%c%c%c", getClient().c_str(), code[0], code[1], code[2], code[3]));
|
||||
if (memcmp(code, kMsgDInfo, 4) == 0) {
|
||||
recvInfo();
|
||||
}
|
||||
|
@ -53,6 +55,8 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
|
|||
|
||||
void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
|
||||
{
|
||||
log((CLOG_INFO "querying client \"%s\" info", getClient().c_str()));
|
||||
|
||||
// send request
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgQInfo);
|
||||
|
||||
|
@ -69,74 +73,87 @@ void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
|
|||
|
||||
void CServerProtocol1_0::sendClose() throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send close to \"%s\"", getClient().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCClose);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendEnter(
|
||||
SInt32 xAbs, SInt32 yAbs) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send enter to \"%s\", %d,%d", getClient().c_str(), xAbs, yAbs));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCEnter, xAbs, yAbs);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendLeave() throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send leave to \"%s\"", getClient().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCLeave);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendGrabClipboard() throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send grab clipboard to \"%s\"", getClient().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCClipboard);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendQueryClipboard() throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "query clipboard to \"%s\"", getClient().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgQClipboard);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendScreenSaver(bool on) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send screen saver to \"%s\"", getClient().c_str()));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendKeyDown(
|
||||
KeyID key, KeyModifierMask mask) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send key down to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDKeyDown, key, mask);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendKeyRepeat(
|
||||
KeyID key, KeyModifierMask mask) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send key repeat to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDKeyRepeat, key, mask);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendKeyUp(
|
||||
KeyID key, KeyModifierMask mask) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send key up to \"%s\" id=%d, mask=0x%04x", getClient().c_str(), key, mask));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDKeyUp, key, mask);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendMouseDown(
|
||||
ButtonID button) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send mouse down to \"%s\" id=%d", getClient().c_str(), button));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDMouseDown, button);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendMouseUp(
|
||||
ButtonID button) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send mouse up to \"%s\" id=%d", getClient().c_str(), button));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDMouseUp, button);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendMouseMove(
|
||||
SInt32 xAbs, SInt32 yAbs) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send mouse move to \"%s\" %d,%d", getClient().c_str(), xAbs, yAbs));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDMouseMove, xAbs, yAbs);
|
||||
}
|
||||
|
||||
void CServerProtocol1_0::sendMouseWheel(
|
||||
SInt32 delta) throw(XIO)
|
||||
{
|
||||
log((CLOG_INFO "send mouse wheel to \"%s\" %+d", getClient().c_str(), delta));
|
||||
CProtocolUtil::writef(getOutputStream(), kMsgDMouseWheel, delta);
|
||||
}
|
||||
|
||||
|
@ -145,6 +162,7 @@ void CServerProtocol1_0::recvInfo() throw(XIO,XBadClient)
|
|||
// parse the message
|
||||
SInt32 w, h, zoneInfo;
|
||||
CProtocolUtil::readf(getInputStream(), kMsgDInfo + 4, &w, &h, &zoneInfo);
|
||||
log((CLOG_INFO "received client \"%s\" info size=%dx%d, zone=%d", getClient().c_str(), w, h, zoneInfo));
|
||||
|
||||
// validate
|
||||
if (w == 0 || h == 0) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "CServer.h"
|
||||
#include "CThread.h"
|
||||
#include "TMethodJob.h"
|
||||
#include "CLog.h"
|
||||
#include <assert.h>
|
||||
#include <X11/X.h>
|
||||
|
||||
|
@ -33,6 +34,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
|
|||
m_server = server;
|
||||
|
||||
// open the display
|
||||
log((CLOG_DEBUG "XOpenDisplay(%s)", "NULL"));
|
||||
m_display = ::XOpenDisplay(NULL); // FIXME -- allow non-default
|
||||
if (m_display == NULL)
|
||||
throw int(5); // FIXME -- make exception for this
|
||||
|
@ -44,6 +46,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
|
|||
// get screen size
|
||||
m_w = WidthOfScreen(screen);
|
||||
m_h = HeightOfScreen(screen);
|
||||
log((CLOG_INFO "primary display size: %dx%d", m_w, m_h));
|
||||
|
||||
// get the root window
|
||||
Window root = RootWindow(m_display, m_screen);
|
||||
|
@ -80,10 +83,12 @@ void CXWindowsPrimaryScreen::close()
|
|||
assert(m_eventThread != NULL);
|
||||
|
||||
// stop event thread
|
||||
log((CLOG_DEBUG "stopping event thread"));
|
||||
m_eventThread->cancel();
|
||||
m_eventThread->wait();
|
||||
delete m_eventThread;
|
||||
m_eventThread = NULL;
|
||||
log((CLOG_DEBUG "stopped event thread"));
|
||||
|
||||
// destroy window
|
||||
::XDestroyWindow(m_display, m_window);
|
||||
|
@ -92,10 +97,12 @@ void CXWindowsPrimaryScreen::close()
|
|||
// close the display
|
||||
::XCloseDisplay(m_display);
|
||||
m_display = NULL;
|
||||
log((CLOG_DEBUG "closed display"));
|
||||
}
|
||||
|
||||
void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
|
||||
{
|
||||
log((CLOG_INFO "entering primary at %d,%d", x, y));
|
||||
assert(m_display != NULL);
|
||||
assert(m_window != None);
|
||||
assert(m_active == true);
|
||||
|
@ -123,6 +130,7 @@ void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
|
|||
|
||||
void CXWindowsPrimaryScreen::leave()
|
||||
{
|
||||
log((CLOG_INFO "leaving primary"));
|
||||
assert(m_display != NULL);
|
||||
assert(m_window != None);
|
||||
assert(m_active == false);
|
||||
|
@ -141,9 +149,12 @@ void CXWindowsPrimaryScreen::leave()
|
|||
GrabModeAsync, GrabModeAsync,
|
||||
m_window, None, CurrentTime);
|
||||
assert(result != GrabNotViewable);
|
||||
if (result != GrabSuccess)
|
||||
if (result != GrabSuccess) {
|
||||
log((CLOG_DEBUG "waiting to grab pointer"));
|
||||
CThread::sleep(0.25);
|
||||
}
|
||||
} while (result != GrabSuccess);
|
||||
log((CLOG_DEBUG "grabbed pointer"));
|
||||
|
||||
// now the keyboard
|
||||
result = ::XGrabKeyboard(m_display, m_window, True,
|
||||
|
@ -151,9 +162,11 @@ void CXWindowsPrimaryScreen::leave()
|
|||
assert(result != GrabNotViewable);
|
||||
if (result != GrabSuccess) {
|
||||
::XUngrabPointer(m_display, CurrentTime);
|
||||
log((CLOG_DEBUG "ungrabbed pointer, waiting to grab keyboard"));
|
||||
CThread::sleep(0.25);
|
||||
}
|
||||
} while (result != GrabSuccess);
|
||||
log((CLOG_DEBUG "grabbed keyboard"));
|
||||
|
||||
// move the mouse to the center of grab window
|
||||
warpCursor(m_w >> 1, m_h >> 1);
|
||||
|
@ -169,6 +182,7 @@ void CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
|||
Window root = RootWindow(m_display, m_screen);
|
||||
::XWarpPointer(m_display, None, root, 0, 0, 0, 0, x, y);
|
||||
::XSync(m_display, False);
|
||||
log((CLOG_DEBUG "warped to %d,%d", x, y));
|
||||
|
||||
// discard mouse events since we just added one we don't want
|
||||
XEvent xevent;
|
||||
|
@ -237,6 +251,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
|
|||
break;
|
||||
|
||||
case KeyPress: {
|
||||
log((CLOG_DEBUG "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||
const KeyID key = mapKey(xevent.xkey.keycode, mask);
|
||||
if (key != kKeyNone) {
|
||||
|
@ -248,6 +263,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
|
|||
// FIXME -- simulate key repeat. X sends press/release for
|
||||
// repeat. must detect auto repeat and use kKeyRepeat.
|
||||
case KeyRelease: {
|
||||
log((CLOG_DEBUG "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||
const KeyID key = mapKey(xevent.xkey.keycode, mask);
|
||||
if (key != kKeyNone) {
|
||||
|
@ -257,6 +273,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
|
|||
}
|
||||
|
||||
case ButtonPress: {
|
||||
log((CLOG_DEBUG "event: ButtonPress button=%d", xevent.xbutton.button));
|
||||
const ButtonID button = mapButton(xevent.xbutton.button);
|
||||
if (button != kButtonNone) {
|
||||
m_server->onMouseDown(button);
|
||||
|
@ -265,6 +282,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
|
|||
}
|
||||
|
||||
case ButtonRelease: {
|
||||
log((CLOG_DEBUG "event: ButtonRelease button=%d", xevent.xbutton.button));
|
||||
const ButtonID button = mapButton(xevent.xbutton.button);
|
||||
if (button != kButtonNone) {
|
||||
m_server->onMouseUp(button);
|
||||
|
@ -273,6 +291,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
|
|||
}
|
||||
|
||||
case MotionNotify: {
|
||||
log((CLOG_DEBUG "event: MotionNotify %d,%d", xevent.xmotion.x_root, xevent.xmotion.y_root));
|
||||
SInt32 x, y;
|
||||
if (!m_active) {
|
||||
x = xevent.xmotion.x_root;
|
||||
|
|
Loading…
Reference in New Issue